|
|
|
@ -20,7 +20,6 @@ using System;
@@ -20,7 +20,6 @@ using System;
|
|
|
|
|
using System.Collections.ObjectModel; |
|
|
|
|
using System.Collections.Specialized; |
|
|
|
|
using System.ComponentModel; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Threading; |
|
|
|
|
using System.Windows; |
|
|
|
|
using System.Windows.Controls; |
|
|
|
@ -53,9 +52,9 @@ namespace ICSharpCode.ILSpy
@@ -53,9 +52,9 @@ namespace ICSharpCode.ILSpy
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const int SearchMode_Type = 0; |
|
|
|
|
const int SearchMode_Member = 1; |
|
|
|
|
const int SearchMode_Literal = 2; |
|
|
|
|
public const int SearchMode_Type = 0; |
|
|
|
|
public const int SearchMode_Member = 1; |
|
|
|
|
public const int SearchMode_Literal = 2; |
|
|
|
|
|
|
|
|
|
private SearchPane() |
|
|
|
|
{ |
|
|
|
@ -184,6 +183,11 @@ namespace ICSharpCode.ILSpy
@@ -184,6 +183,11 @@ namespace ICSharpCode.ILSpy
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal interface ISearch |
|
|
|
|
{ |
|
|
|
|
void Search(TypeDefinition type, Language language, Action<SearchResult> addResult); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sealed class RunningSearch |
|
|
|
|
{ |
|
|
|
|
readonly Dispatcher dispatcher; |
|
|
|
@ -195,9 +199,6 @@ namespace ICSharpCode.ILSpy
@@ -195,9 +199,6 @@ namespace ICSharpCode.ILSpy
|
|
|
|
|
public readonly ObservableCollection<SearchResult> Results = new ObservableCollection<SearchResult>(); |
|
|
|
|
int resultCount; |
|
|
|
|
|
|
|
|
|
TypeCode searchTermLiteralType = TypeCode.Empty; |
|
|
|
|
object searchTermLiteralValue; |
|
|
|
|
|
|
|
|
|
public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, int searchMode, Language language) |
|
|
|
|
{ |
|
|
|
|
this.dispatcher = Dispatcher.CurrentDispatcher; |
|
|
|
@ -217,44 +218,17 @@ namespace ICSharpCode.ILSpy
@@ -217,44 +218,17 @@ namespace ICSharpCode.ILSpy
|
|
|
|
|
public void Run() |
|
|
|
|
{ |
|
|
|
|
try { |
|
|
|
|
if (searchMode == SearchMode_Literal) { |
|
|
|
|
if (1 == searchTerm.Length) |
|
|
|
|
{ |
|
|
|
|
CSharpParser parser = new CSharpParser(); |
|
|
|
|
PrimitiveExpression pe = parser.ParseExpression(searchTerm[0]) as PrimitiveExpression; |
|
|
|
|
if (pe != null && pe.Value != null) { |
|
|
|
|
TypeCode peValueType = Type.GetTypeCode(pe.Value.GetType()); |
|
|
|
|
switch (peValueType) { |
|
|
|
|
case TypeCode.Byte: |
|
|
|
|
case TypeCode.SByte: |
|
|
|
|
case TypeCode.Int16: |
|
|
|
|
case TypeCode.UInt16: |
|
|
|
|
case TypeCode.Int32: |
|
|
|
|
case TypeCode.UInt32: |
|
|
|
|
case TypeCode.Int64: |
|
|
|
|
case TypeCode.UInt64: |
|
|
|
|
searchTermLiteralType = TypeCode.Int64; |
|
|
|
|
searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, pe.Value, false); |
|
|
|
|
break; |
|
|
|
|
case TypeCode.Single: |
|
|
|
|
case TypeCode.Double: |
|
|
|
|
case TypeCode.String: |
|
|
|
|
searchTermLiteralType = peValueType; |
|
|
|
|
searchTermLiteralValue = pe.Value; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
foreach (var loadedAssembly in assemblies) { |
|
|
|
|
var searcher = ResolveSearcher(searchMode, searchTerm); |
|
|
|
|
foreach (var loadedAssembly in assemblies) |
|
|
|
|
{ |
|
|
|
|
ModuleDefinition module = loadedAssembly.ModuleDefinition; |
|
|
|
|
if (module == null) |
|
|
|
|
continue; |
|
|
|
|
CancellationToken cancellationToken = cts.Token; |
|
|
|
|
|
|
|
|
|
foreach (TypeDefinition type in module.Types) { |
|
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
|
PerformSearch(type); |
|
|
|
|
searcher.Search(type, language, AddResult); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} catch (OperationCanceledException) { |
|
|
|
@ -278,253 +252,400 @@ namespace ICSharpCode.ILSpy
@@ -278,253 +252,400 @@ namespace ICSharpCode.ILSpy
|
|
|
|
|
cts.Token.ThrowIfCancellationRequested(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsMatch(string text) |
|
|
|
|
private ISearch ResolveSearcher(int mode, string[] terms) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < searchTerm.Length; ++i) { |
|
|
|
|
// How to handle overlapping matches?
|
|
|
|
|
if (text.IndexOf(searchTerm[i], StringComparison.OrdinalIgnoreCase) < 0) |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
if (terms.Length == 1) |
|
|
|
|
{ |
|
|
|
|
if (terms[0].StartsWith("t:")) |
|
|
|
|
return new TypeSearcher(terms); |
|
|
|
|
|
|
|
|
|
void PerformSearch(TypeDefinition type) |
|
|
|
|
{ |
|
|
|
|
if (searchMode == SearchMode_Type && IsMatch(type.Name)) { |
|
|
|
|
AddResult(new SearchResult { |
|
|
|
|
Member = type, |
|
|
|
|
Image = TypeTreeNode.GetIcon(type), |
|
|
|
|
Name = language.TypeToString(type, includeNamespace: false), |
|
|
|
|
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace, |
|
|
|
|
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
if (terms[0].StartsWith("m:")) |
|
|
|
|
return new MemberSearcher(terms); |
|
|
|
|
|
|
|
|
|
foreach (TypeDefinition nestedType in type.NestedTypes) { |
|
|
|
|
PerformSearch(nestedType); |
|
|
|
|
if (terms[0].StartsWith("c:")) |
|
|
|
|
return new LiteralSearcher(terms); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (searchMode == SearchMode_Type) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
foreach (FieldDefinition field in type.Fields) { |
|
|
|
|
if (IsMatch(field)) { |
|
|
|
|
AddResult(new SearchResult { |
|
|
|
|
Member = field, |
|
|
|
|
Image = FieldTreeNode.GetIcon(field), |
|
|
|
|
Name = field.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (PropertyDefinition property in type.Properties) { |
|
|
|
|
if (IsMatch(property)) { |
|
|
|
|
AddResult(new SearchResult { |
|
|
|
|
Member = property, |
|
|
|
|
Image = PropertyTreeNode.GetIcon(property), |
|
|
|
|
Name = property.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (EventDefinition ev in type.Events) { |
|
|
|
|
if (IsMatch(ev)) { |
|
|
|
|
AddResult(new SearchResult { |
|
|
|
|
Member = ev, |
|
|
|
|
Image = EventTreeNode.GetIcon(ev), |
|
|
|
|
Name = ev.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (MethodDefinition method in type.Methods) { |
|
|
|
|
switch (method.SemanticsAttributes) { |
|
|
|
|
case MethodSemanticsAttributes.Setter: |
|
|
|
|
case MethodSemanticsAttributes.Getter: |
|
|
|
|
case MethodSemanticsAttributes.AddOn: |
|
|
|
|
case MethodSemanticsAttributes.RemoveOn: |
|
|
|
|
case MethodSemanticsAttributes.Fire: |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (IsMatch(method)) { |
|
|
|
|
AddResult(new SearchResult { |
|
|
|
|
Member = method, |
|
|
|
|
Image = MethodTreeNode.GetIcon(method), |
|
|
|
|
Name = method.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
switch (mode) |
|
|
|
|
{ |
|
|
|
|
case SearchMode_Type: return new TypeSearcher(terms); |
|
|
|
|
case SearchMode_Member: return new MemberSearcher(terms); |
|
|
|
|
case SearchMode_Literal: return new LiteralSearcher(terms); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsMatch(FieldDefinition field) |
|
|
|
|
{ |
|
|
|
|
if (searchMode == SearchMode_Literal) |
|
|
|
|
return IsLiteralMatch(field.Constant); |
|
|
|
|
else |
|
|
|
|
return IsMatch(field.Name); |
|
|
|
|
internal sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode |
|
|
|
|
{ |
|
|
|
|
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { |
|
|
|
|
add { } |
|
|
|
|
remove { } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsMatch(PropertyDefinition property) |
|
|
|
|
public MemberReference Member { get; set; } |
|
|
|
|
|
|
|
|
|
public string Location { get; set; } |
|
|
|
|
public string Name { get; set; } |
|
|
|
|
public ImageSource Image { get; set; } |
|
|
|
|
public ImageSource LocationImage { get; set; } |
|
|
|
|
|
|
|
|
|
public override string ToString() |
|
|
|
|
{ |
|
|
|
|
if (searchMode == SearchMode_Literal) |
|
|
|
|
return MethodIsLiteralMatch(property.GetMethod) || MethodIsLiteralMatch(property.SetMethod); |
|
|
|
|
else |
|
|
|
|
return IsMatch(property.Name); |
|
|
|
|
return Name; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsMatch(EventDefinition ev) |
|
|
|
|
internal class LiteralSearcher : SearcherBase |
|
|
|
|
{ |
|
|
|
|
private readonly TypeCode searchTermLiteralType; |
|
|
|
|
private readonly object searchTermLiteralValue; |
|
|
|
|
|
|
|
|
|
public LiteralSearcher(string[] terms) : base(terms) |
|
|
|
|
{ |
|
|
|
|
if (1 == searchTerm.Length) |
|
|
|
|
{ |
|
|
|
|
if (searchMode == SearchMode_Literal) |
|
|
|
|
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod); |
|
|
|
|
else |
|
|
|
|
return IsMatch(ev.Name); |
|
|
|
|
var parser = new CSharpParser(); |
|
|
|
|
var pe = parser.ParseExpression(searchTerm[0]) as PrimitiveExpression; |
|
|
|
|
|
|
|
|
|
if (pe != null && pe.Value != null) |
|
|
|
|
{ |
|
|
|
|
TypeCode peValueType = Type.GetTypeCode(pe.Value.GetType()); |
|
|
|
|
switch (peValueType) |
|
|
|
|
{ |
|
|
|
|
case TypeCode.Byte: |
|
|
|
|
case TypeCode.SByte: |
|
|
|
|
case TypeCode.Int16: |
|
|
|
|
case TypeCode.UInt16: |
|
|
|
|
case TypeCode.Int32: |
|
|
|
|
case TypeCode.UInt32: |
|
|
|
|
case TypeCode.Int64: |
|
|
|
|
case TypeCode.UInt64: |
|
|
|
|
searchTermLiteralType = TypeCode.Int64; |
|
|
|
|
searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, pe.Value, false); |
|
|
|
|
break; |
|
|
|
|
case TypeCode.Single: |
|
|
|
|
case TypeCode.Double: |
|
|
|
|
case TypeCode.String: |
|
|
|
|
searchTermLiteralType = peValueType; |
|
|
|
|
searchTermLiteralValue = pe.Value; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(FieldDefinition field) |
|
|
|
|
{ |
|
|
|
|
return IsLiteralMatch(field.Constant); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(PropertyDefinition property) |
|
|
|
|
{ |
|
|
|
|
return MethodIsLiteralMatch(property.GetMethod) || MethodIsLiteralMatch(property.SetMethod); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(EventDefinition ev) |
|
|
|
|
{ |
|
|
|
|
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsMatch(MethodDefinition m) |
|
|
|
|
protected override bool IsMatch(MethodDefinition m) |
|
|
|
|
{ |
|
|
|
|
return MethodIsLiteralMatch(m); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsLiteralMatch(object val) |
|
|
|
|
{ |
|
|
|
|
if (val == null) |
|
|
|
|
return false; |
|
|
|
|
switch (searchTermLiteralType) |
|
|
|
|
{ |
|
|
|
|
if (searchMode == SearchMode_Literal) |
|
|
|
|
return MethodIsLiteralMatch(m); |
|
|
|
|
else |
|
|
|
|
return IsMatch(m.Name); |
|
|
|
|
case TypeCode.Int64: |
|
|
|
|
TypeCode tc = Type.GetTypeCode(val.GetType()); |
|
|
|
|
if (tc >= TypeCode.SByte && tc <= TypeCode.UInt64) |
|
|
|
|
return CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false).Equals(searchTermLiteralValue); |
|
|
|
|
else |
|
|
|
|
return false; |
|
|
|
|
case TypeCode.Single: |
|
|
|
|
case TypeCode.Double: |
|
|
|
|
case TypeCode.String: |
|
|
|
|
return searchTermLiteralValue.Equals(val); |
|
|
|
|
default: |
|
|
|
|
// substring search with searchTerm
|
|
|
|
|
return IsMatch(val.ToString()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsLiteralMatch(object val) |
|
|
|
|
bool MethodIsLiteralMatch(MethodDefinition m) |
|
|
|
|
{ |
|
|
|
|
if (m == null) |
|
|
|
|
return false; |
|
|
|
|
var body = m.Body; |
|
|
|
|
if (body == null) |
|
|
|
|
return false; |
|
|
|
|
if (searchTermLiteralType == TypeCode.Int64) |
|
|
|
|
{ |
|
|
|
|
if (val == null) |
|
|
|
|
return false; |
|
|
|
|
switch (searchTermLiteralType) { |
|
|
|
|
case TypeCode.Int64: |
|
|
|
|
TypeCode tc = Type.GetTypeCode(val.GetType()); |
|
|
|
|
if (tc >= TypeCode.SByte && tc <= TypeCode.UInt64) |
|
|
|
|
return CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false).Equals(searchTermLiteralValue); |
|
|
|
|
else |
|
|
|
|
return false; |
|
|
|
|
long val = (long)searchTermLiteralValue; |
|
|
|
|
foreach (var inst in body.Instructions) |
|
|
|
|
{ |
|
|
|
|
switch (inst.OpCode.Code) |
|
|
|
|
{ |
|
|
|
|
case Code.Ldc_I8: |
|
|
|
|
if (val == (long)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4: |
|
|
|
|
if (val == (int)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_S: |
|
|
|
|
if (val == (sbyte)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_M1: |
|
|
|
|
if (val == -1) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_0: |
|
|
|
|
if (val == 0) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_1: |
|
|
|
|
if (val == 1) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_2: |
|
|
|
|
if (val == 2) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_3: |
|
|
|
|
if (val == 3) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_4: |
|
|
|
|
if (val == 4) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_5: |
|
|
|
|
if (val == 5) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_6: |
|
|
|
|
if (val == 6) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_7: |
|
|
|
|
if (val == 7) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_8: |
|
|
|
|
if (val == 8) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (searchTermLiteralType != TypeCode.Empty) |
|
|
|
|
{ |
|
|
|
|
Code expectedCode; |
|
|
|
|
switch (searchTermLiteralType) |
|
|
|
|
{ |
|
|
|
|
case TypeCode.Single: |
|
|
|
|
expectedCode = Code.Ldc_R4; |
|
|
|
|
break; |
|
|
|
|
case TypeCode.Double: |
|
|
|
|
expectedCode = Code.Ldc_R8; |
|
|
|
|
break; |
|
|
|
|
case TypeCode.String: |
|
|
|
|
return searchTermLiteralValue.Equals(val); |
|
|
|
|
expectedCode = Code.Ldstr; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
// substring search with searchTerm
|
|
|
|
|
return IsMatch(val.ToString()); |
|
|
|
|
throw new InvalidOperationException(); |
|
|
|
|
} |
|
|
|
|
foreach (var inst in body.Instructions) |
|
|
|
|
{ |
|
|
|
|
if (inst.OpCode.Code == expectedCode && searchTermLiteralValue.Equals(inst.Operand)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
foreach (var inst in body.Instructions) |
|
|
|
|
{ |
|
|
|
|
if (inst.OpCode.Code == Code.Ldstr && IsMatch((string)inst.Operand)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal class MemberSearcher : SearcherBase |
|
|
|
|
{ |
|
|
|
|
public MemberSearcher(string[] terms) : base(terms) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(FieldDefinition field) |
|
|
|
|
{ |
|
|
|
|
return IsMatch(field.Name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(PropertyDefinition property) |
|
|
|
|
{ |
|
|
|
|
return IsMatch(property.Name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(EventDefinition ev) |
|
|
|
|
{ |
|
|
|
|
return IsMatch(ev.Name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected override bool IsMatch(MethodDefinition m) |
|
|
|
|
{ |
|
|
|
|
return IsMatch(m.Name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MethodIsLiteralMatch(MethodDefinition m) |
|
|
|
|
internal abstract class SearcherBase : SearchPane.ISearch |
|
|
|
|
{ |
|
|
|
|
protected string[] searchTerm; |
|
|
|
|
|
|
|
|
|
protected SearcherBase(string[] terms) |
|
|
|
|
{ |
|
|
|
|
if (terms.Length == 1 && terms[0].Length > 2 && terms[0][1] == ':') |
|
|
|
|
terms[0] = terms[0].Substring(2); |
|
|
|
|
|
|
|
|
|
searchTerm = terms; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected bool IsMatch(string text) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < searchTerm.Length; ++i) |
|
|
|
|
{ |
|
|
|
|
if (m == null) |
|
|
|
|
return false; |
|
|
|
|
var body = m.Body; |
|
|
|
|
if (body == null) |
|
|
|
|
// How to handle overlapping matches?
|
|
|
|
|
if (text.IndexOf(searchTerm[i], StringComparison.OrdinalIgnoreCase) < 0) |
|
|
|
|
return false; |
|
|
|
|
if (searchTermLiteralType == TypeCode.Int64) { |
|
|
|
|
long val = (long)searchTermLiteralValue; |
|
|
|
|
foreach (var inst in body.Instructions) { |
|
|
|
|
switch (inst.OpCode.Code) { |
|
|
|
|
case Code.Ldc_I8: |
|
|
|
|
if (val == (long)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4: |
|
|
|
|
if (val == (int)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_S: |
|
|
|
|
if (val == (sbyte)inst.Operand) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_M1: |
|
|
|
|
if (val == -1) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_0: |
|
|
|
|
if (val == 0) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_1: |
|
|
|
|
if (val == 1) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_2: |
|
|
|
|
if (val == 2) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_3: |
|
|
|
|
if (val == 3) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_4: |
|
|
|
|
if (val == 4) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_5: |
|
|
|
|
if (val == 5) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_6: |
|
|
|
|
if (val == 6) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_7: |
|
|
|
|
if (val == 7) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
case Code.Ldc_I4_8: |
|
|
|
|
if (val == 8) |
|
|
|
|
return true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (searchTermLiteralType != TypeCode.Empty) { |
|
|
|
|
Code expectedCode; |
|
|
|
|
switch (searchTermLiteralType) { |
|
|
|
|
case TypeCode.Single: |
|
|
|
|
expectedCode = Code.Ldc_R4; |
|
|
|
|
break; |
|
|
|
|
case TypeCode.Double: |
|
|
|
|
expectedCode = Code.Ldc_R8; |
|
|
|
|
break; |
|
|
|
|
case TypeCode.String: |
|
|
|
|
expectedCode = Code.Ldstr; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
throw new InvalidOperationException(); |
|
|
|
|
} |
|
|
|
|
foreach (var inst in body.Instructions) { |
|
|
|
|
if (inst.OpCode.Code == expectedCode && searchTermLiteralValue.Equals(inst.Operand)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
foreach (var inst in body.Instructions) { |
|
|
|
|
if (inst.OpCode.Code == Code.Ldstr && IsMatch((string)inst.Operand)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode |
|
|
|
|
protected virtual bool IsMatch(FieldDefinition field) |
|
|
|
|
{ |
|
|
|
|
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { |
|
|
|
|
add { } |
|
|
|
|
remove { } |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual bool IsMatch(PropertyDefinition property) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual bool IsMatch(EventDefinition ev) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual bool IsMatch(MethodDefinition m) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public virtual void Search(TypeDefinition type, Language language, Action<SearchPane.SearchResult> addResult) |
|
|
|
|
{ |
|
|
|
|
foreach (FieldDefinition field in type.Fields) |
|
|
|
|
{ |
|
|
|
|
if (IsMatch(field)) |
|
|
|
|
{ |
|
|
|
|
addResult(new SearchPane.SearchResult |
|
|
|
|
{ |
|
|
|
|
Member = field, |
|
|
|
|
Image = FieldTreeNode.GetIcon(field), |
|
|
|
|
Name = field.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (PropertyDefinition property in type.Properties) |
|
|
|
|
{ |
|
|
|
|
if (IsMatch(property)) |
|
|
|
|
{ |
|
|
|
|
addResult(new SearchPane.SearchResult |
|
|
|
|
{ |
|
|
|
|
Member = property, |
|
|
|
|
Image = PropertyTreeNode.GetIcon(property), |
|
|
|
|
Name = property.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (EventDefinition ev in type.Events) |
|
|
|
|
{ |
|
|
|
|
if (IsMatch(ev)) |
|
|
|
|
{ |
|
|
|
|
addResult(new SearchPane.SearchResult |
|
|
|
|
{ |
|
|
|
|
Member = ev, |
|
|
|
|
Image = EventTreeNode.GetIcon(ev), |
|
|
|
|
Name = ev.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach (MethodDefinition method in type.Methods) |
|
|
|
|
{ |
|
|
|
|
switch (method.SemanticsAttributes) |
|
|
|
|
{ |
|
|
|
|
case MethodSemanticsAttributes.Setter: |
|
|
|
|
case MethodSemanticsAttributes.Getter: |
|
|
|
|
case MethodSemanticsAttributes.AddOn: |
|
|
|
|
case MethodSemanticsAttributes.RemoveOn: |
|
|
|
|
case MethodSemanticsAttributes.Fire: |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (IsMatch(method)) |
|
|
|
|
{ |
|
|
|
|
addResult(new SearchPane.SearchResult |
|
|
|
|
{ |
|
|
|
|
Member = method, |
|
|
|
|
Image = MethodTreeNode.GetIcon(method), |
|
|
|
|
Name = method.Name, |
|
|
|
|
LocationImage = TypeTreeNode.GetIcon(type), |
|
|
|
|
Location = language.TypeToString(type, includeNamespace: true) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public MemberReference Member { get; set; } |
|
|
|
|
internal class TypeSearcher : SearcherBase |
|
|
|
|
{ |
|
|
|
|
public TypeSearcher(string[] terms) : base(terms) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public string Location { get; set; } |
|
|
|
|
public string Name { get; set; } |
|
|
|
|
public ImageSource Image { get; set; } |
|
|
|
|
public ImageSource LocationImage { get; set; } |
|
|
|
|
public override void Search(TypeDefinition type, Language language, Action<SearchPane.SearchResult> addResult) |
|
|
|
|
{ |
|
|
|
|
if (IsMatch(type.Name)) |
|
|
|
|
{ |
|
|
|
|
addResult(new SearchPane.SearchResult |
|
|
|
|
{ |
|
|
|
|
Member = type, |
|
|
|
|
Image = TypeTreeNode.GetIcon(type), |
|
|
|
|
Name = language.TypeToString(type, includeNamespace: false), |
|
|
|
|
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace, |
|
|
|
|
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override string ToString() |
|
|
|
|
foreach (TypeDefinition nestedType in type.NestedTypes) |
|
|
|
|
{ |
|
|
|
|
return Name; |
|
|
|
|
Search(nestedType, language, addResult); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|