Browse Source

code cleanup

pull/550/head
Siegfried Pammer 10 years ago
parent
commit
11670cdb1d
  1. 1
      ILSpy/ILSpy.csproj
  2. 411
      ILSpy/SearchPane.cs
  3. 336
      ILSpy/SearchStrategies.cs

1
ILSpy/ILSpy.csproj

@ -177,6 +177,7 @@ @@ -177,6 +177,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Commands\SimpleCommand.cs" />
<Compile Include="SearchStrategies.cs" />
<Compile Include="TaskHelper.cs" />
<Compile Include="TextView\FoldingCommands.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />

411
ILSpy/SearchPane.cs

@ -186,11 +186,6 @@ namespace ICSharpCode.ILSpy @@ -186,11 +186,6 @@ namespace ICSharpCode.ILSpy
}
}
internal interface ISearch
{
void Search(TypeDefinition type, Language language, Action<SearchResult> addResult);
}
sealed class RunningSearch
{
readonly Dispatcher dispatcher;
@ -221,9 +216,8 @@ namespace ICSharpCode.ILSpy @@ -221,9 +216,8 @@ namespace ICSharpCode.ILSpy
public void Run()
{
try {
var searcher = ResolveSearcher(searchMode, searchTerm);
foreach (var loadedAssembly in assemblies)
{
var searcher = GetSearchStrategy(searchMode, searchTerm);
foreach (var loadedAssembly in assemblies) {
ModuleDefinition module = loadedAssembly.ModuleDefinition;
if (module == null)
continue;
@ -255,399 +249,54 @@ namespace ICSharpCode.ILSpy @@ -255,399 +249,54 @@ namespace ICSharpCode.ILSpy
cts.Token.ThrowIfCancellationRequested();
}
private ISearch ResolveSearcher(int mode, string[] terms)
AbstractSearchStrategy GetSearchStrategy(int mode, string[] terms)
{
if (terms.Length == 1)
{
if (terms.Length == 1) {
if (terms[0].StartsWith("t:"))
return new TypeSearcher(terms);
return new TypeSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("m:"))
return new MemberSearcher(terms);
return new MemberSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("c:"))
return new LiteralSearcher(terms);
return new LiteralSearchStrategy(terms[0].Substring(2));
}
switch (mode)
{
case SearchMode_Type: return new TypeSearcher(terms);
case SearchMode_Member: return new MemberSearcher(terms);
case SearchMode_Literal: return new LiteralSearcher(terms);
switch (mode) {
case SearchMode_Type:
return new TypeSearchStrategy(terms);
case SearchMode_Member:
return new MemberSearchStrategy(terms);
case SearchMode_Literal:
return new LiteralSearchStrategy(terms);
}
return null;
}
}
internal sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode
{
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
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()
{
return Name;
}
}
}
internal class LiteralSearcher : SearcherBase
sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode
{
private readonly TypeCode searchTermLiteralType;
private readonly object searchTermLiteralValue;
public LiteralSearcher(string[] terms) : base(terms)
{
if (1 == searchTerm.Length)
{
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);
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
protected override bool IsMatch(EventDefinition ev)
{
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod);
}
protected override bool IsMatch(MethodDefinition m)
{
return MethodIsLiteralMatch(m);
}
bool IsLiteralMatch(object val)
{
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;
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.String:
return searchTermLiteralValue.Equals(val);
default:
// substring search with searchTerm
return IsMatch(val.ToString());
}
}
bool MethodIsLiteralMatch(MethodDefinition m)
{
if (m == null)
return false;
var body = m.Body;
if (body == null)
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;
}
}
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);
}
}
internal abstract class SearcherBase : SearchPane.ISearch
{
protected string[] searchTerm;
protected Regex regex = null;
protected SearcherBase(string[] terms)
{
if (terms.Length == 1 && terms[0].Length > 2 && terms[0][1] == ':')
{
var search = terms[0].Substring(2);
if (search.StartsWith("/") && search.EndsWith("/") && search.Length > 4)
regex = SafeNewRegex(search.Substring(1, search.Length - 2));
terms[0] = search;
}
searchTerm = terms;
}
protected bool IsMatch(string text)
{
if (regex != null)
return regex.IsMatch(text);
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;
}
protected virtual bool IsMatch(FieldDefinition field)
{
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;
}
private void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchPane.SearchResult> addResult, Func<T, bool> matcher, Func<T, ImageSource> image) where T : MemberReference
{
foreach (var item in items)
{
if (matcher(item))
{
addResult(new SearchPane.SearchResult
{
Member = item,
Image = image(item),
Name = item.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
}
public virtual void Search(TypeDefinition type, Language language, Action<SearchPane.SearchResult> addResult)
{
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(NotSpecialMethod),
type,
language,
addResult,
IsMatch, MethodTreeNode.GetIcon);
}
private bool NotSpecialMethod(MethodDefinition arg)
{
return (arg.SemanticsAttributes & (
MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.AddOn
| MethodSemanticsAttributes.RemoveOn
| MethodSemanticsAttributes.Fire)) == 0;
}
private Regex SafeNewRegex(string unsafePattern)
{
try
{
return new Regex(unsafePattern, RegexOptions.Compiled);
}
catch (ArgumentException)
{
return null;
}
}
}
internal class TypeSearcher : SearcherBase
{
public TypeSearcher(string[] terms) : base(terms)
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchPane.SearchResult> addResult)
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 (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
});
}
foreach (TypeDefinition nestedType in type.NestedTypes)
{
Search(nestedType, language, addResult);
}
return Name;
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon="Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)]
[ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon = "Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)]
[ExportToolbarCommand(ToolTip = "Search (F3)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper
{

336
ILSpy/SearchStrategies.cs

@ -0,0 +1,336 @@ @@ -0,0 +1,336 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Media;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy
{
abstract class AbstractSearchStrategy
{
protected string[] searchTerm;
protected Regex regex;
protected AbstractSearchStrategy(params string[] terms)
{
if (terms.Length == 1 && terms[0].Length > 2) {
var search = terms[0];
if (search.StartsWith("/") && search.EndsWith("/") && search.Length > 4)
regex = SafeNewRegex(search.Substring(1, search.Length - 2));
terms[0] = search;
}
searchTerm = terms;
}
protected bool IsMatch(string text)
{
if (regex != null)
return regex.IsMatch(text);
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;
}
protected virtual bool IsMatch(FieldDefinition field)
{
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;
}
void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, bool> matcher, Func<T, ImageSource> image) where T : MemberReference
{
foreach (var item in items) {
if (matcher(item)) {
addResult(new SearchResult
{
Member = item,
Image = image(item),
Name = item.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
}
public virtual void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
{
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(NotSpecialMethod), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
}
bool NotSpecialMethod(MethodDefinition arg)
{
return (arg.SemanticsAttributes & (
MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.AddOn
| MethodSemanticsAttributes.RemoveOn
| MethodSemanticsAttributes.Fire)) == 0;
}
Regex SafeNewRegex(string unsafePattern)
{
try {
return new Regex(unsafePattern, RegexOptions.Compiled);
} catch (ArgumentException) {
return null;
}
}
}
class LiteralSearchStrategy : AbstractSearchStrategy
{
readonly TypeCode searchTermLiteralType;
readonly object searchTermLiteralValue;
public LiteralSearchStrategy(params string[] terms)
: base(terms)
{
if (1 == searchTerm.Length) {
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);
}
protected override bool IsMatch(MethodDefinition m)
{
return MethodIsLiteralMatch(m);
}
bool IsLiteralMatch(object val)
{
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;
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.String:
return searchTermLiteralValue.Equals(val);
default:
// substring search with searchTerm
return IsMatch(val.ToString());
}
}
bool MethodIsLiteralMatch(MethodDefinition m)
{
if (m == null)
return false;
var body = m.Body;
if (body == null)
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;
}
}
class MemberSearchStrategy : AbstractSearchStrategy
{
public MemberSearchStrategy(params 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);
}
}
class TypeSearchStrategy : AbstractSearchStrategy
{
public TypeSearchStrategy(params string[] terms)
: base(terms)
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (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
});
}
foreach (TypeDefinition nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
}
}
Loading…
Cancel
Save