Browse Source

Reimplement search strategies.

pull/1030/head
Siegfried Pammer 7 years ago
parent
commit
7ded12c5fb
  1. 6
      ICSharpCode.Decompiler/SRMExtensions.cs
  2. 2
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs
  3. 4
      ILSpy/ILSpy.csproj
  4. 5
      ILSpy/Languages/CSharpLanguage.cs
  5. 5
      ILSpy/Languages/Language.cs
  6. 129
      ILSpy/Search/AbstractSearchStrategy.cs
  7. 64
      ILSpy/Search/LiteralSearchStrategy.cs
  8. 124
      ILSpy/Search/MemberSearchStrategy.cs
  9. 35
      ILSpy/Search/MetadataTokenSearchStrategy.cs
  10. 53
      ILSpy/Search/SearchPane.cs
  11. 53
      ILSpy/Search/TypeAndMemberSearchStrategy.cs
  12. 34
      ILSpy/Search/TypeSearchStrategy.cs

6
ICSharpCode.Decompiler/SRMExtensions.cs

@ -333,7 +333,7 @@ namespace ICSharpCode.Decompiler
} }
#endregion #endregion
public static unsafe SRM.BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, IDecompilerTypeSystem typeSystem) public static unsafe SRM.BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, ICompilation typeSystem)
{ {
if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0) if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0)
return default; return default;
@ -346,9 +346,9 @@ namespace ICSharpCode.Decompiler
{ {
MetadataModule module; MetadataModule module;
public FieldValueSizeDecoder(IDecompilerTypeSystem typeSystem) public FieldValueSizeDecoder(ICompilation typeSystem)
{ {
this.module = typeSystem.MainModule; this.module = (MetadataModule)typeSystem.MainModule;
} }
public int GetArrayType(int elementType, ArrayShape shape) => GetPrimitiveType(PrimitiveTypeCode.Object); public int GetArrayType(int elementType, ArrayShape shape) => GetPrimitiveType(PrimitiveTypeCode.Object);

2
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -4,7 +4,7 @@ using System.Linq;
namespace ICSharpCode.Decompiler.Util namespace ICSharpCode.Decompiler.Util
{ {
static class CollectionExtensions public static class CollectionExtensions
{ {
public static void Deconstruct<K, V>(this KeyValuePair<K, V> pair, out K key, out V value) public static void Deconstruct<K, V>(this KeyValuePair<K, V> pair, out K key, out V value)
{ {

4
ILSpy/ILSpy.csproj

@ -204,7 +204,7 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Commands\SimpleCommand.cs" /> <Compile Include="Commands\SimpleCommand.cs" />
<Compile Include="Search\SearchStrategies.cs" /> <Compile Include="Search\AbstractSearchStrategy.cs" />
<Compile Include="TaskHelper.cs" /> <Compile Include="TaskHelper.cs" />
<Compile Include="TextView\EditorCommands.cs" /> <Compile Include="TextView\EditorCommands.cs" />
<Compile Include="TextView\FoldingCommands.cs" /> <Compile Include="TextView\FoldingCommands.cs" />
@ -235,9 +235,7 @@
<Compile Include="TreeNodes\ResourceNodes\XamlResourceNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\XmlResourceNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\XmlResourceNode.cs" />
<Compile Include="TreeNodes\SearchMsdnContextMenuEntry.cs" /> <Compile Include="TreeNodes\SearchMsdnContextMenuEntry.cs" />
<Compile Include="Search\TypeAndMemberSearchStrategy.cs" />
<Compile Include="Analyzers\Builtin\TypeExtensionMethodsAnalyzer.cs" /> <Compile Include="Analyzers\Builtin\TypeExtensionMethodsAnalyzer.cs" />
<Compile Include="Search\TypeSearchStrategy.cs" />
<EmbeddedResource Include="..\doc\LGPL.txt"> <EmbeddedResource Include="..\doc\LGPL.txt">
<Link>LGPL.txt</Link> <Link>LGPL.txt</Link>
</EmbeddedResource> </EmbeddedResource>

5
ILSpy/Languages/CSharpLanguage.cs

@ -555,6 +555,11 @@ namespace ICSharpCode.ILSpy
return buffer.ToString(); return buffer.ToString();
} }
public override bool SearchCanUseILNames(string text)
{
return !text.Contains("<");
}
public override bool ShowMember(IEntity member) public override bool ShowMember(IEntity member)
{ {
PEFile assembly = member.ParentModule.PEFile; PEFile assembly = member.ParentModule.PEFile;

5
ILSpy/Languages/Language.cs

@ -266,6 +266,11 @@ namespace ICSharpCode.ILSpy
return true; return true;
} }
public virtual bool SearchCanUseILNames(string text)
{
return true;
}
public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandle member) public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandle member)
{ {
var parts = new Dictionary<SRM.MethodDefinitionHandle, SRM.MethodDefinitionHandle[]>(); var parts = new Dictionary<SRM.MethodDefinitionHandle, SRM.MethodDefinitionHandle[]>();

129
ILSpy/Search/SearchStrategies.cs → ILSpy/Search/AbstractSearchStrategy.cs

@ -7,33 +7,45 @@ using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using System.Reflection; using System.Reflection;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy.Search
{ {
abstract class AbstractSearchStrategy abstract class AbstractSearchStrategy
{ {
protected string[] searchTerm; protected readonly (string Term, bool CanUseILNames)[] searchTerm;
protected Regex regex; protected readonly Regex regex;
protected bool fullNameSearch; protected readonly bool fullNameSearch;
protected readonly bool needsLanguageSpecificNames;
protected AbstractSearchStrategy(params string[] terms) protected readonly Language language;
protected readonly Action<SearchResult> addResult;
protected AbstractSearchStrategy(Language language, Action<SearchResult> addResult, params string[] terms)
{ {
this.language = language;
this.addResult = addResult;
if (terms.Length == 1 && terms[0].Length > 2) { if (terms.Length == 1 && terms[0].Length > 2) {
var search = terms[0]; string search = terms[0];
if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4) { if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4) {
var regexString = search.Substring(1, search.Length - 1); var regexString = search.Substring(1, search.Length - 1);
fullNameSearch = search.Contains("\\."); fullNameSearch = search.Contains("\\.");
if (regexString.EndsWith("/", StringComparison.Ordinal)) if (regexString.EndsWith("/", StringComparison.Ordinal))
regexString = regexString.Substring(0, regexString.Length - 1); regexString = regexString.Substring(0, regexString.Length - 1);
regex = SafeNewRegex(regexString); regex = SafeNewRegex(regexString);
needsLanguageSpecificNames = true;
searchTerm = new[] { (search, false) };
} else { } else {
fullNameSearch = search.Contains("."); fullNameSearch = search.Contains(".");
needsLanguageSpecificNames = fullNameSearch || !language.SearchCanUseILNames(search);
searchTerm = new[] { (search, !needsLanguageSpecificNames) };
} }
} else {
terms[0] = search; searchTerm = terms.SelectArray(t => (t, language.SearchCanUseILNames(t)));
needsLanguageSpecificNames = searchTerm.Any(t => !t.CanUseILNames);
} }
searchTerm = terms;
} }
protected float CalculateFitness(IEntity member) protected float CalculateFitness(IEntity member)
@ -57,42 +69,17 @@ namespace ICSharpCode.ILSpy
return 1.0f / text.Length; return 1.0f / text.Length;
} }
protected virtual bool IsMatch(IField field, Language language) protected virtual bool IsMatch(MetadataReader metadata, StringHandle nameHandle, string languageSpecificName)
{
return false;
}
protected virtual bool IsMatch(IProperty property, Language language)
{
return false;
}
protected virtual bool IsMatch(IEvent ev, Language language)
{
return false;
}
protected virtual bool IsMatch(IMethod m, Language language)
{
return false;
}
protected virtual bool MatchName(IEntity m, Language language)
{
return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains(".")));
}
protected virtual bool IsMatch(Func<string, string> getText)
{ {
if (regex != null) { if (regex != null) {
return regex.IsMatch(getText("")); return regex.IsMatch(languageSpecificName);
} }
for (int i = 0; i < searchTerm.Length; ++i) { for (int i = 0; i < searchTerm.Length; ++i) {
// How to handle overlapping matches? // How to handle overlapping matches?
var term = searchTerm[i]; var term = searchTerm[i].Term;
if (string.IsNullOrEmpty(term)) continue; if (string.IsNullOrEmpty(term)) continue;
string text = getText(term); string text = nameHandle.IsNil || !searchTerm[i].CanUseILNames || term.Contains(".") ? languageSpecificName : metadata.GetString(nameHandle);
switch (term[0]) { switch (term[0]) {
case '+': // must contain case '+': // must contain
term = term.Substring(1); term = term.Substring(1);
@ -107,7 +94,8 @@ namespace ICSharpCode.ILSpy
if (equalCompareLength == -1) if (equalCompareLength == -1)
equalCompareLength = text.Length; equalCompareLength = text.Length;
if (term.Length > 1 && String.Compare(term, 1, text, 0, Math.Max(term.Length, equalCompareLength), StringComparison.OrdinalIgnoreCase) != 0) if (term.Length > 1 && String.Compare(term, 1, text, 0, Math.Max(term.Length, equalCompareLength),
StringComparison.OrdinalIgnoreCase) != 0)
return false; return false;
} }
break; break;
@ -151,7 +139,7 @@ namespace ICSharpCode.ILSpy
return false; return false;
} }
string GetLanguageSpecificName(Language language, IEntity member, bool fullName = false) protected string GetLanguageSpecificName(IEntity member, bool fullName)
{ {
switch (member) { switch (member) {
case ITypeDefinition t: case ITypeDefinition t:
@ -169,39 +157,25 @@ namespace ICSharpCode.ILSpy
} }
} }
void Add<T>(Func<IEnumerable<T>> itemsGetter, ITypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IEntity protected ImageSource GetIcon(IEntity member)
{ {
IEnumerable<T> items = Enumerable.Empty<T>(); switch (member) {
try { case ITypeDefinition t:
items = itemsGetter(); return TypeTreeNode.GetIcon(t);
} catch (Exception ex) { case IField f:
System.Diagnostics.Debug.Print(ex.ToString()); return FieldTreeNode.GetIcon(f);
} case IProperty p:
foreach (var item in items) { return PropertyTreeNode.GetIcon(p);
if (matcher(item, language)) { case IMethod m:
addResult(new SearchResult { return MethodTreeNode.GetIcon(m);
Member = item, case IEvent e:
Fitness = CalculateFitness(item), return EventTreeNode.GetIcon(e);
Image = image(item), default:
Name = GetLanguageSpecificName(language, item), throw new NotSupportedException(member?.GetType() + " not supported!");
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
} }
} }
public virtual void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult) public abstract void Search(PEFile module);
{
Add(() => type.Fields, type, language, addResult, IsMatch, FieldTreeNode.GetIcon);
Add(() => type.Properties, type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p));
Add(() => type.Events, type, language, addResult, IsMatch, EventTreeNode.GetIcon);
Add(() => type.Methods.Where(m => !m.IsAccessor), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
Regex SafeNewRegex(string unsafePattern) Regex SafeNewRegex(string unsafePattern)
{ {
@ -211,5 +185,18 @@ namespace ICSharpCode.ILSpy
return null; return null;
} }
} }
protected SearchResult ResultFromEntity(IEntity item)
{
var declaringType = item.DeclaringTypeDefinition;
return new SearchResult {
Member = item,
Fitness = CalculateFitness(item),
Image = GetIcon(item),
Name = GetLanguageSpecificName(item, fullName: false),
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : item.Namespace
};
}
} }
} }

64
ILSpy/Search/LiteralSearchStrategy.cs

@ -7,19 +7,22 @@ using ICSharpCode.Decompiler;
using static System.Reflection.Metadata.PEReaderExtensions; using static System.Reflection.Metadata.PEReaderExtensions;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Metadata;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy.Search
{ {
class LiteralSearchStrategy : AbstractSearchStrategy class LiteralSearchStrategy : AbstractSearchStrategy
{ {
readonly TypeCode searchTermLiteralType; readonly TypeCode searchTermLiteralType;
readonly object searchTermLiteralValue; readonly object searchTermLiteralValue;
public LiteralSearchStrategy(params string[] terms) public LiteralSearchStrategy(Language language, Action<SearchResult> addResult, params string[] terms)
: base(terms) : base(language, addResult, terms)
{ {
if (searchTerm.Length == 1) { if (terms.Length == 1) {
var lexer = new Lexer(new LATextReader(new System.IO.StringReader(searchTerm[0]))); var lexer = new Lexer(new LATextReader(new System.IO.StringReader(terms[0])));
var value = lexer.NextToken(); var value = lexer.NextToken();
if (value != null && value.LiteralValue != null) { if (value != null && value.LiteralValue != null) {
@ -47,27 +50,31 @@ namespace ICSharpCode.ILSpy
} }
} }
protected override bool IsMatch(IField field, Language language) public override void Search(PEFile module)
{ {
return IsLiteralMatch(field.ConstantValue); var metadata = module.Metadata;
} var typeSystem = module.GetTypeSystemOrNull();
if (typeSystem == null) return;
protected override bool IsMatch(IProperty property, Language language)
{
return MethodIsLiteralMatch(property.Getter) || MethodIsLiteralMatch(property.Setter);
}
protected override bool IsMatch(IEvent ev, Language language) foreach (var handle in metadata.MethodDefinitions) {
{ var md = metadata.GetMethodDefinition(handle);
return MethodIsLiteralMatch(ev.AddAccessor) || MethodIsLiteralMatch(ev.RemoveAccessor) || MethodIsLiteralMatch(ev.InvokeAccessor); if (!md.HasBody() || !MethodIsLiteralMatch(module, md)) continue;
} var method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
addResult(ResultFromEntity(method));
}
protected override bool IsMatch(IMethod m, Language language) foreach (var handle in metadata.FieldDefinitions) {
{ var fd = metadata.GetFieldDefinition(handle);
return MethodIsLiteralMatch(m); if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA) || !fd.HasFlag(System.Reflection.FieldAttributes.Literal))
continue;
// TODO
//fd.GetInitialValue(module.Reader, typeSystem);
//IField field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
//addResult(ResultFromEntity(field));
}
} }
bool IsLiteralMatch(object val) bool IsLiteralMatch(PEFile module, object val)
{ {
if (val == null) if (val == null)
return false; return false;
@ -84,21 +91,12 @@ namespace ICSharpCode.ILSpy
return searchTermLiteralValue.Equals(val); return searchTermLiteralValue.Equals(val);
default: default:
// substring search with searchTerm // substring search with searchTerm
return IsMatch(t => val.ToString()); return IsMatch(module.Metadata, MetadataTokens.StringHandle(0), val.ToString());
} }
} }
bool MethodIsLiteralMatch(IMethod method) bool MethodIsLiteralMatch(PEFile module, MethodDefinition methodDefinition)
{ {
if (method == null)
return false;
var module = ((MetadataModule)method.ParentModule).PEFile;
var m = (SRM.MethodDefinitionHandle)method.MetadataToken;
if (m.IsNil)
return false;
var methodDefinition = module.Metadata.GetMethodDefinition(m);
if (!methodDefinition.HasBody())
return false;
var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader();
if (searchTermLiteralType == TypeCode.Int64) { if (searchTermLiteralType == TypeCode.Int64) {
long val = (long)searchTermLiteralValue; long val = (long)searchTermLiteralValue;
@ -205,7 +203,7 @@ namespace ICSharpCode.ILSpy
ILParser.SkipOperand(ref blob, code); ILParser.SkipOperand(ref blob, code);
continue; continue;
} }
if (base.IsMatch(t => ILParser.DecodeUserString(ref blob, module.Metadata))) if (IsMatch(module.Metadata, MetadataTokens.StringHandle(0), ILParser.DecodeUserString(ref blob, module.Metadata)))
return true; return true;
} }
} }

124
ILSpy/Search/MemberSearchStrategy.cs

@ -1,46 +1,128 @@
using ICSharpCode.Decompiler.TypeSystem; using System;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy.Search
{ {
class MemberSearchStrategy : AbstractSearchStrategy class MemberSearchStrategy : AbstractSearchStrategy
{ {
MemberSearchKind searchKind; readonly MemberSearchKind searchKind;
public MemberSearchStrategy(string term, MemberSearchKind searchKind = MemberSearchKind.All) public MemberSearchStrategy(Language language, Action<SearchResult> addResult, string term, MemberSearchKind searchKind = MemberSearchKind.All)
: this(new[] { term }, searchKind) : this(language, addResult, new[] { term }, searchKind)
{ {
} }
public MemberSearchStrategy(string[] terms, MemberSearchKind searchKind = MemberSearchKind.All) public MemberSearchStrategy(Language language, Action<SearchResult> addResult, string[] terms, MemberSearchKind searchKind = MemberSearchKind.All)
: base(terms) : base(language, addResult, terms)
{ {
this.searchKind = searchKind; this.searchKind = searchKind;
} }
protected override bool IsMatch(IField field, Language language) public override void Search(PEFile module)
{ {
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Field) && MatchName(field, language); var metadata = module.Metadata;
} var typeSystem = module.GetTypeSystemOrNull();
if (typeSystem == null) return;
protected override bool IsMatch(IProperty property, Language language) if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Type) {
{ foreach (var handle in metadata.TypeDefinitions) {
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Property) && MatchName(property, language); var td = metadata.GetTypeDefinition(handle);
} string languageSpecificName = null;
ITypeDefinition type = null;
if (needsLanguageSpecificNames) {
type = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
languageSpecificName = GetLanguageSpecificName(type, fullName: true);
}
if (!IsMatch(module.Metadata, td.Name, languageSpecificName))
continue;
if (type == null) {
type = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
}
addResult(ResultFromEntity(type));
}
}
protected override bool IsMatch(IEvent ev, Language language) if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Method) {
{ foreach (var handle in metadata.MethodDefinitions) {
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Event) && MatchName(ev, language); // TODO use method semantics to skip accessors
} var md = metadata.GetMethodDefinition(handle);
string languageSpecificName = null;
IMethod method = null;
if (needsLanguageSpecificNames) {
method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
languageSpecificName = GetLanguageSpecificName(method, fullName: true);
}
if (!IsMatch(module.Metadata, md.Name, languageSpecificName))
continue;
if (method == null) {
method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
}
addResult(ResultFromEntity(method));
}
}
protected override bool IsMatch(IMethod m, Language language) if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Field) {
{ foreach (var handle in metadata.FieldDefinitions) {
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Method) && MatchName(m, language); var fd = metadata.GetFieldDefinition(handle);
string languageSpecificName = null;
IField field = null;
if (needsLanguageSpecificNames) {
field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
languageSpecificName = GetLanguageSpecificName(field, fullName: true);
}
if (!IsMatch(module.Metadata, fd.Name, languageSpecificName))
continue;
if (field == null) {
field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
}
addResult(ResultFromEntity(field));
}
}
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Property) {
foreach (var handle in metadata.PropertyDefinitions) {
var pd = metadata.GetPropertyDefinition(handle);
string languageSpecificName = null;
IProperty property = null;
if (needsLanguageSpecificNames) {
property = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
languageSpecificName = GetLanguageSpecificName(property, fullName: true);
}
if (!IsMatch(module.Metadata, pd.Name, languageSpecificName))
continue;
if (property == null) {
property = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
}
addResult(ResultFromEntity(property));
}
}
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Event) {
foreach (var handle in metadata.EventDefinitions) {
var ed = metadata.GetEventDefinition(handle);
string languageSpecificName = null;
IEvent @event = null;
if (needsLanguageSpecificNames) {
@event = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
languageSpecificName = GetLanguageSpecificName(@event, fullName: true);
}
if (!IsMatch(module.Metadata, ed.Name, languageSpecificName))
continue;
if (@event == null) {
@event = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
}
addResult(ResultFromEntity(@event));
}
}
} }
} }
enum MemberSearchKind enum MemberSearchKind
{ {
All, All,
Type,
Member,
Field, Field,
Property, Property,
Event, Event,

35
ILSpy/Search/MetadataTokenSearchStrategy.cs

@ -1,24 +1,37 @@
using System.Globalization; using System;
using SRM = System.Reflection.Metadata; using System.Globalization;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy.Search
{ {
class MetadataTokenSearchStrategy : TypeAndMemberSearchStrategy class MetadataTokenSearchStrategy : AbstractSearchStrategy
{ {
readonly int searchTermToken; readonly EntityHandle searchTermToken;
public MetadataTokenSearchStrategy(params string[] terms) public MetadataTokenSearchStrategy(Language language, Action<SearchResult> addResult, params string[] terms)
: base(terms) : base(language, addResult, terms)
{ {
if (searchTerm.Length == 1) { if (terms.Length == 1) {
int.TryParse(searchTerm[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out searchTermToken); int.TryParse(terms[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var token);
searchTermToken = MetadataTokenHelpers.EntityHandleOrNil(token);
} }
} }
protected override bool MatchName(IEntity m, Language language) public override void Search(PEFile module)
{ {
return SRM.Ecma335.MetadataTokens.GetToken(m.MetadataToken) == searchTermToken; if (searchTermToken.IsNil) return;
var typeSystem = module.GetTypeSystemOrNull();
if (typeSystem == null) return;
switch (searchTermToken.Kind) {
case HandleKind.TypeDefinition:
var type = ((MetadataModule)typeSystem.MainModule).GetDefinition((TypeDefinitionHandle)searchTermToken);
addResult(ResultFromEntity(type));
break;
}
} }
} }
} }

53
ILSpy/Search/SearchPane.cs

@ -19,15 +19,14 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -128,7 +127,8 @@ namespace ICSharpCode.ILSpy
listBox.ItemsSource = null; listBox.ItemsSource = null;
} else { } else {
MainWindow mainWindow = MainWindow.Instance; MainWindow mainWindow = MainWindow.Instance;
currentSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm, (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage); currentSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm,
(SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage);
listBox.ItemsSource = currentSearch.Results; listBox.ItemsSource = currentSearch.Results;
new Thread(currentSearch.Run).Start(); new Thread(currentSearch.Run).Start();
} }
@ -216,16 +216,13 @@ namespace ICSharpCode.ILSpy
{ {
try { try {
var searcher = GetSearchStrategy(searchMode, searchTerm); var searcher = GetSearchStrategy(searchMode, searchTerm);
// TODO : parallelize
foreach (var loadedAssembly in assemblies) { foreach (var loadedAssembly in assemblies) {
var typeSystem = loadedAssembly.GetTypeSystemOrNull(); var module = loadedAssembly.GetPEFileOrNull();
if (typeSystem == null) if (module == null)
continue; continue;
CancellationToken cancellationToken = cts.Token; CancellationToken cancellationToken = cts.Token;
searcher.Search(module);
foreach (var type in typeSystem.MainModule.TopLevelTypeDefinitions) {
cancellationToken.ThrowIfCancellationRequested();
searcher.Search(type, language, AddResult);
}
} }
} catch (OperationCanceledException) { } catch (OperationCanceledException) {
// ignore cancellation // ignore cancellation
@ -276,53 +273,53 @@ namespace ICSharpCode.ILSpy
{ {
if (terms.Length == 1) { if (terms.Length == 1) {
if (terms[0].StartsWith("tm:", StringComparison.Ordinal)) if (terms[0].StartsWith("tm:", StringComparison.Ordinal))
return new TypeAndMemberSearchStrategy(terms[0].Substring(3)); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(3));
if (terms[0].StartsWith("t:", StringComparison.Ordinal)) if (terms[0].StartsWith("t:", StringComparison.Ordinal))
return new TypeSearchStrategy(terms[0].Substring(2)); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(2), MemberSearchKind.Type);
if (terms[0].StartsWith("m:", StringComparison.Ordinal)) if (terms[0].StartsWith("m:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2)); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(2), MemberSearchKind.Member);
if (terms[0].StartsWith("md:", StringComparison.Ordinal)) if (terms[0].StartsWith("md:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(3), MemberSearchKind.Method); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(3), MemberSearchKind.Method);
if (terms[0].StartsWith("f:", StringComparison.Ordinal)) if (terms[0].StartsWith("f:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Field); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(2), MemberSearchKind.Field);
if (terms[0].StartsWith("p:", StringComparison.Ordinal)) if (terms[0].StartsWith("p:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Property); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(2), MemberSearchKind.Property);
if (terms[0].StartsWith("e:", StringComparison.Ordinal)) if (terms[0].StartsWith("e:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Event); return new MemberSearchStrategy(language, AddResult, terms[0].Substring(2), MemberSearchKind.Event);
if (terms[0].StartsWith("c:", StringComparison.Ordinal)) if (terms[0].StartsWith("c:", StringComparison.Ordinal))
return new LiteralSearchStrategy(terms[0].Substring(2)); return new LiteralSearchStrategy(language, AddResult, terms[0].Substring(2));
if (terms[0].StartsWith("@", StringComparison.Ordinal)) if (terms[0].StartsWith("@", StringComparison.Ordinal))
return new MetadataTokenSearchStrategy(terms[0].Substring(1)); return new MetadataTokenSearchStrategy(language, AddResult, terms[0].Substring(1));
} }
switch (mode) switch (mode)
{ {
case SearchMode.TypeAndMember: case SearchMode.TypeAndMember:
return new TypeAndMemberSearchStrategy(terms); return new MemberSearchStrategy(language, AddResult, terms);
case SearchMode.Type: case SearchMode.Type:
return new TypeSearchStrategy(terms); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Type);
case SearchMode.Member: case SearchMode.Member:
return new MemberSearchStrategy(terms); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Member);
case SearchMode.Literal: case SearchMode.Literal:
return new LiteralSearchStrategy(terms); return new LiteralSearchStrategy(language, AddResult, terms);
case SearchMode.Method: case SearchMode.Method:
return new MemberSearchStrategy(terms, MemberSearchKind.Method); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Method);
case SearchMode.Field: case SearchMode.Field:
return new MemberSearchStrategy(terms, MemberSearchKind.Field); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Field);
case SearchMode.Property: case SearchMode.Property:
return new MemberSearchStrategy(terms, MemberSearchKind.Property); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Property);
case SearchMode.Event: case SearchMode.Event:
return new MemberSearchStrategy(terms, MemberSearchKind.Event); return new MemberSearchStrategy(language, AddResult, terms, MemberSearchKind.Event);
case SearchMode.Token: case SearchMode.Token:
return new MetadataTokenSearchStrategy(terms); return new MetadataTokenSearchStrategy(language, AddResult, terms);
} }
return null; return null;

53
ILSpy/Search/TypeAndMemberSearchStrategy.cs

@ -1,53 +0,0 @@
using System;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
class TypeAndMemberSearchStrategy : AbstractSearchStrategy
{
public TypeAndMemberSearchStrategy(params string[] terms)
: base(terms)
{
}
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (MatchName(type, language))
{
string name = language.TypeToString(type, includeNamespace: false);
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Image = TypeTreeNode.GetIcon(type),
Fitness = CalculateFitness(type),
Name = name,
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
base.Search(type, language, addResult);
}
protected override bool IsMatch(IField field, Language language)
{
return MatchName(field, language);
}
protected override bool IsMatch(IProperty property, Language language)
{
return MatchName(property, language);
}
protected override bool IsMatch(IEvent ev, Language language)
{
return MatchName(ev, language);
}
protected override bool IsMatch(IMethod m, Language language)
{
return MatchName(m, language);
}
}
}

34
ILSpy/Search/TypeSearchStrategy.cs

@ -1,34 +0,0 @@
using System;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
class TypeSearchStrategy : AbstractSearchStrategy
{
public TypeSearchStrategy(params string[] terms)
: base(terms)
{
}
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (MatchName(type, language)) {
string name = language.TypeToString(type, includeNamespace: false);
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Fitness = CalculateFitness(type),
Image = TypeTreeNode.GetIcon(type),
Name = name,
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
}
}
Loading…
Cancel
Save