diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 5e5178cf6..4dd8b7430 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -40,6 +40,7 @@ using ICSharpCode.Decompiler.Util;
using System.Reflection;
using ICSharpCode.Decompiler.Disassembler;
using GenericContext = ICSharpCode.Decompiler.Metadata.GenericContext;
+using System.Text;
namespace ICSharpCode.ILSpy
{
@@ -555,9 +556,86 @@ namespace ICSharpCode.ILSpy
return buffer.ToString();
}
- public override bool SearchCanUseILNames(string text)
+ string ToCSharpString(MetadataReader metadata, TypeDefinitionHandle handle, bool fullName)
{
- return !text.Contains("<");
+ StringBuilder builder = new StringBuilder();
+ var currentTypeDefHandle = handle;
+ var typeDef = metadata.GetTypeDefinition(currentTypeDefHandle);
+
+ while (!currentTypeDefHandle.IsNil) {
+ if (builder.Length > 0)
+ builder.Insert(0, '.');
+ typeDef = metadata.GetTypeDefinition(currentTypeDefHandle);
+ var part = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(typeDef.Name), out int typeParamCount);
+ var genericParams = typeDef.GetGenericParameters();
+ if (genericParams.Count > 0) {
+ builder.Insert(0, '>');
+ int firstIndex = genericParams.Count - typeParamCount;
+ for (int i = genericParams.Count - 1; i >= genericParams.Count - typeParamCount; i--) {
+ builder.Insert(0, metadata.GetString(metadata.GetGenericParameter(genericParams[i]).Name));
+ builder.Insert(0, i == firstIndex ? '<' : ',');
+ }
+ }
+ builder.Insert(0, part);
+ currentTypeDefHandle = typeDef.GetDeclaringType();
+ if (!fullName) break;
+ }
+
+ if (fullName && !typeDef.Namespace.IsNil) {
+ builder.Insert(0, '.');
+ builder.Insert(0, metadata.GetString(typeDef.Namespace));
+ }
+
+ return builder.ToString();
+ }
+
+ public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
+ {
+ MetadataReader metadata = module.Metadata;
+ switch (handle.Kind) {
+ case HandleKind.TypeDefinition:
+ return ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName);
+ case HandleKind.FieldDefinition:
+ var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
+ var declaringType = fd.GetDeclaringType();
+ if (fullName)
+ return ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(fd.Name);
+ return metadata.GetString(fd.Name);
+ case HandleKind.MethodDefinition:
+ var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
+ declaringType = md.GetDeclaringType();
+ string methodName = metadata.GetString(md.Name);
+ var genericParams = md.GetGenericParameters();
+ if (genericParams.Count > 0) {
+ methodName += "<";
+ int i = 0;
+ foreach (var h in genericParams) {
+ if (i > 0)
+ methodName += ",";
+ var gp = metadata.GetGenericParameter(h);
+ methodName += metadata.GetString(gp.Name);
+ }
+ methodName += ">";
+ }
+
+ if (fullName)
+ return ToCSharpString(metadata, declaringType, fullName) + "." + methodName;
+ return methodName;
+ case HandleKind.EventDefinition:
+ var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
+ declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
+ if (fullName)
+ return ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(ed.Name);
+ return metadata.GetString(ed.Name);
+ case HandleKind.PropertyDefinition:
+ var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
+ declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
+ if (fullName)
+ return ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(pd.Name);
+ return metadata.GetString(pd.Name);
+ default:
+ return null;
+ }
}
public override bool ShowMember(IEntity member)
diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs
index 0759deb24..e371366bb 100644
--- a/ILSpy/Languages/Language.cs
+++ b/ILSpy/Languages/Language.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
@@ -266,9 +267,49 @@ namespace ICSharpCode.ILSpy
return true;
}
- public virtual bool SearchCanUseILNames(string text)
+ ///
+ /// This should produce a string representation of the entity for search to match search strings against.
+ ///
+ public virtual string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
{
- return true;
+ MetadataReader metadata = module.Metadata;
+ switch (handle.Kind) {
+ case HandleKind.TypeDefinition:
+ if (fullName)
+ return ((TypeDefinitionHandle)handle).GetFullTypeName(metadata).ToILNameString();
+ var td = metadata.GetTypeDefinition((TypeDefinitionHandle)handle);
+ return metadata.GetString(td.Name);
+ case HandleKind.FieldDefinition:
+ var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
+ var declaringType = fd.GetDeclaringType();
+ if (fullName)
+ return fd.GetDeclaringType().GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(fd.Name);
+ return metadata.GetString(fd.Name);
+ case HandleKind.MethodDefinition:
+ var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
+ declaringType = md.GetDeclaringType();
+ string methodName = metadata.GetString(md.Name);
+ int genericParamCount = md.GetGenericParameters().Count;
+ if (genericParamCount > 0)
+ methodName += "``" + genericParamCount;
+ if (fullName)
+ return md.GetDeclaringType().GetFullTypeName(metadata).ToILNameString() + "." + methodName;
+ return methodName;
+ case HandleKind.EventDefinition:
+ var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
+ declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
+ if (fullName)
+ return declaringType.GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(ed.Name);
+ return metadata.GetString(ed.Name);
+ case HandleKind.PropertyDefinition:
+ var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
+ declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
+ if (fullName)
+ return declaringType.GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(pd.Name);
+ return metadata.GetString(pd.Name);
+ default:
+ return null;
+ }
}
public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandle member)
diff --git a/ILSpy/Search/AbstractSearchStrategy.cs b/ILSpy/Search/AbstractSearchStrategy.cs
index 75f0ebb7f..c0de48398 100644
--- a/ILSpy/Search/AbstractSearchStrategy.cs
+++ b/ILSpy/Search/AbstractSearchStrategy.cs
@@ -15,10 +15,9 @@ namespace ICSharpCode.ILSpy.Search
{
abstract class AbstractSearchStrategy
{
- protected readonly (string Term, bool CanUseILNames)[] searchTerm;
+ protected readonly string[] searchTerm;
protected readonly Regex regex;
protected readonly bool fullNameSearch;
- protected readonly bool needsLanguageSpecificNames;
protected readonly Language language;
protected readonly Action addResult;
@@ -35,17 +34,11 @@ namespace ICSharpCode.ILSpy.Search
if (regexString.EndsWith("/", StringComparison.Ordinal))
regexString = regexString.Substring(0, regexString.Length - 1);
regex = SafeNewRegex(regexString);
- needsLanguageSpecificNames = true;
- searchTerm = new[] { (search, false) };
} else {
fullNameSearch = search.Contains(".");
- needsLanguageSpecificNames = fullNameSearch || !language.SearchCanUseILNames(search);
- searchTerm = new[] { (search, !needsLanguageSpecificNames) };
}
- } else {
- searchTerm = terms.SelectArray(t => (t, language.SearchCanUseILNames(t)));
- needsLanguageSpecificNames = searchTerm.Any(t => !t.CanUseILNames);
}
+ searchTerm = terms;
}
protected float CalculateFitness(IEntity member)
@@ -69,17 +62,17 @@ namespace ICSharpCode.ILSpy.Search
return 1.0f / text.Length;
}
- protected virtual bool IsMatch(MetadataReader metadata, StringHandle nameHandle, string languageSpecificName)
+ protected virtual bool IsMatch(string entityName)
{
if (regex != null) {
- return regex.IsMatch(languageSpecificName);
+ return regex.IsMatch(entityName);
}
for (int i = 0; i < searchTerm.Length; ++i) {
// How to handle overlapping matches?
- var term = searchTerm[i].Term;
+ var term = searchTerm[i];
if (string.IsNullOrEmpty(term)) continue;
- string text = nameHandle.IsNil || !searchTerm[i].CanUseILNames || term.Contains(".") ? languageSpecificName : metadata.GetString(nameHandle);
+ string text = entityName;
switch (term[0]) {
case '+': // must contain
term = term.Substring(1);
diff --git a/ILSpy/Search/LiteralSearchStrategy.cs b/ILSpy/Search/LiteralSearchStrategy.cs
index 6c8ed2feb..4eb7d6707 100644
--- a/ILSpy/Search/LiteralSearchStrategy.cs
+++ b/ILSpy/Search/LiteralSearchStrategy.cs
@@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Search
return searchTermLiteralValue.Equals(val);
default:
// substring search with searchTerm
- return IsMatch(metadata, MetadataTokens.StringHandle(0), val.ToString());
+ return IsMatch(val.ToString());
}
}
@@ -208,7 +208,7 @@ namespace ICSharpCode.ILSpy.Search
ILParser.SkipOperand(ref blob, code);
continue;
}
- if (IsMatch(module.Metadata, MetadataTokens.StringHandle(0), ILParser.DecodeUserString(ref blob, module.Metadata)))
+ if (IsMatch(ILParser.DecodeUserString(ref blob, module.Metadata)))
return true;
}
}
diff --git a/ILSpy/Search/MemberSearchStrategy.cs b/ILSpy/Search/MemberSearchStrategy.cs
index 6aeddf7fe..010a1fe61 100644
--- a/ILSpy/Search/MemberSearchStrategy.cs
+++ b/ILSpy/Search/MemberSearchStrategy.cs
@@ -27,18 +27,10 @@ namespace ICSharpCode.ILSpy.Search
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Type) {
foreach (var handle in metadata.TypeDefinitions) {
- 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))
+ string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch);
+ if (languageSpecificName != null && !IsMatch(languageSpecificName))
continue;
- if (type == null) {
- type = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
- }
+ var type = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
addResult(ResultFromEntity(type));
}
}
@@ -46,72 +38,40 @@ namespace ICSharpCode.ILSpy.Search
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Method) {
foreach (var handle in metadata.MethodDefinitions) {
// 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))
+ string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch);
+ if (languageSpecificName != null && !IsMatch(languageSpecificName))
continue;
- if (method == null) {
- method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
- }
+ var method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
addResult(ResultFromEntity(method));
}
}
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Field) {
foreach (var handle in metadata.FieldDefinitions) {
- 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))
+ string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch);
+ if (languageSpecificName != null && !IsMatch(languageSpecificName))
continue;
- if (field == null) {
- field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
- }
+ var 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))
+ string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch);
+ if (languageSpecificName != null && !IsMatch(languageSpecificName))
continue;
- if (property == null) {
- property = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
- }
+ var 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))
+ string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch);
+ if (!IsMatch(languageSpecificName))
continue;
- if (@event == null) {
- @event = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
- }
+ var @event = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle);
addResult(ResultFromEntity(@event));
}
}