Browse Source

New Search Mode: Search for constants (literals).

pull/254/head
Daniel Grunwald 15 years ago
parent
commit
684ad7d8fb
  1. 203
      ILSpy/SearchPane.cs

203
ILSpy/SearchPane.cs

@ -20,6 +20,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -30,8 +31,12 @@ using System.Windows.Documents;
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.ILAst;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -55,12 +60,14 @@ namespace ICSharpCode.ILSpy
const int SearchMode_Type = 0; const int SearchMode_Type = 0;
const int SearchMode_Member = 1; const int SearchMode_Member = 1;
const int SearchMode_Literal = 2;
private SearchPane() private SearchPane()
{ {
InitializeComponent(); InitializeComponent();
searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" }); searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" }); searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.SelectedIndex = SearchMode_Type; searchModeComboBox.SelectedIndex = SearchMode_Type;
} }
@ -162,11 +169,14 @@ namespace ICSharpCode.ILSpy
readonly CancellationTokenSource cts = new CancellationTokenSource(); readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly LoadedAssembly[] assemblies; readonly LoadedAssembly[] assemblies;
readonly string searchTerm; readonly string searchTerm;
readonly int searchMode; int searchMode;
readonly Language language; readonly Language language;
public readonly ObservableCollection<SearchResult> Results = new ObservableCollection<SearchResult>(); public readonly ObservableCollection<SearchResult> Results = new ObservableCollection<SearchResult>();
int resultCount; int resultCount;
TypeCode searchTermLiteralType = TypeCode.Empty;
object searchTermLiteralValue;
public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, int searchMode, Language language) public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, int searchMode, Language language)
{ {
this.dispatcher = Dispatcher.CurrentDispatcher; this.dispatcher = Dispatcher.CurrentDispatcher;
@ -186,6 +196,33 @@ namespace ICSharpCode.ILSpy
public void Run() public void Run()
{ {
try { try {
if (searchMode == SearchMode_Literal) {
CSharpParser parser = new CSharpParser();
PrimitiveExpression pe = parser.ParseExpression(new StringReader(searchTerm)) 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) { foreach (var loadedAssembly in assemblies) {
AssemblyDefinition asm = loadedAssembly.AssemblyDefinition; AssemblyDefinition asm = loadedAssembly.AssemblyDefinition;
if (asm == null) if (asm == null)
@ -245,7 +282,7 @@ namespace ICSharpCode.ILSpy
return; return;
foreach (FieldDefinition field in type.Fields) { foreach (FieldDefinition field in type.Fields) {
if (IsMatch(field.Name)) { if (IsMatch(field)) {
AddResult(new SearchResult { AddResult(new SearchResult {
Member = field, Member = field,
Image = FieldTreeNode.GetIcon(field), Image = FieldTreeNode.GetIcon(field),
@ -256,7 +293,7 @@ namespace ICSharpCode.ILSpy
} }
} }
foreach (PropertyDefinition property in type.Properties) { foreach (PropertyDefinition property in type.Properties) {
if (IsMatch(property.Name)) { if (IsMatch(property)) {
AddResult(new SearchResult { AddResult(new SearchResult {
Member = property, Member = property,
Image = PropertyTreeNode.GetIcon(property), Image = PropertyTreeNode.GetIcon(property),
@ -267,7 +304,7 @@ namespace ICSharpCode.ILSpy
} }
} }
foreach (EventDefinition ev in type.Events) { foreach (EventDefinition ev in type.Events) {
if (IsMatch(ev.Name)) { if (IsMatch(ev)) {
AddResult(new SearchResult { AddResult(new SearchResult {
Member = ev, Member = ev,
Image = EventTreeNode.GetIcon(ev), Image = EventTreeNode.GetIcon(ev),
@ -278,7 +315,15 @@ namespace ICSharpCode.ILSpy
} }
} }
foreach (MethodDefinition method in type.Methods) { foreach (MethodDefinition method in type.Methods) {
if (IsMatch(method.Name)) { 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 { AddResult(new SearchResult {
Member = method, Member = method,
Image = MethodTreeNode.GetIcon(method), Image = MethodTreeNode.GetIcon(method),
@ -289,6 +334,152 @@ namespace ICSharpCode.ILSpy
} }
} }
} }
bool IsMatch(FieldDefinition field)
{
if (searchMode == SearchMode_Literal)
return IsLiteralMatch(field.Constant);
else
return IsMatch(field.Name);
}
bool IsMatch(PropertyDefinition property)
{
if (searchMode == SearchMode_Literal)
return MethodIsLiteralMatch(property.GetMethod) || MethodIsLiteralMatch(property.SetMethod);
else
return IsMatch(property.Name);
}
bool IsMatch(EventDefinition ev)
{
if (searchMode == SearchMode_Literal)
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod);
else
return IsMatch(ev.Name);
}
bool IsMatch(MethodDefinition m)
{
if (searchMode == SearchMode_Literal)
return MethodIsLiteralMatch(m);
else
return IsMatch(m.Name);
}
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 Convert.ToInt64(val) == (long)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;
}
} }
sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode
@ -311,7 +502,7 @@ namespace ICSharpCode.ILSpy
} }
} }
} }
[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)] [ExportToolbarCommand(ToolTip = "Search (F3)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper sealed class ShowSearchCommand : CommandWrapper

Loading…
Cancel
Save