diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index f8fc8cea7..1d366c06c 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -230,7 +230,7 @@ namespace ICSharpCode.Decompiler.ILAst { if (input == null) throw new ArgumentNullException("Input is null!"); - + List ranges = input.Where(r => r != null).OrderBy(r => r.From).ToList(); for (int i = 0; i < ranges.Count - 1;) { ILRange curr = ranges[i]; @@ -424,8 +424,10 @@ namespace ICSharpCode.Decompiler.ILAst } } else if (Operand is MethodReference) { MethodReference method = (MethodReference)Operand; - method.DeclaringType.WriteTo(output, true, true); - output.Write("::"); + if (method.DeclaringType != null) { + method.DeclaringType.WriteTo(output, true, true); + output.Write("::"); + } output.WriteReference(method.Name, method); } else if (Operand is FieldReference) { FieldReference field = (FieldReference)Operand; diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index 0d55ca6e3..361f6a5a8 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -67,22 +67,22 @@ namespace ICSharpCode.ILSpy public static readonly BitmapImage Enum = LoadBitmap("Enum"); - private static readonly BitmapImage Field = LoadBitmap("Field"); - private static readonly BitmapImage FieldReadOnly = LoadBitmap("FieldReadOnly"); - private static readonly BitmapImage Literal = LoadBitmap("Literal"); - private static readonly BitmapImage EnumValue = LoadBitmap("EnumValue"); - - private static readonly BitmapImage Method = LoadBitmap("Method"); - private static readonly BitmapImage Constructor = LoadBitmap("Constructor"); - private static readonly BitmapImage VirtualMethod = LoadBitmap("VirtualMethod"); - private static readonly BitmapImage Operator = LoadBitmap("Operator"); - private static readonly BitmapImage ExtensionMethod = LoadBitmap("ExtensionMethod"); - private static readonly BitmapImage PInvokeMethod = LoadBitmap("PInvokeMethod"); - - private static readonly BitmapImage Property = LoadBitmap("Property"); - private static readonly BitmapImage Indexer = LoadBitmap("Indexer"); - - private static readonly BitmapImage Event = LoadBitmap("Event"); + public static readonly BitmapImage Field = LoadBitmap("Field"); + public static readonly BitmapImage FieldReadOnly = LoadBitmap("FieldReadOnly"); + public static readonly BitmapImage Literal = LoadBitmap("Literal"); + public static readonly BitmapImage EnumValue = LoadBitmap("EnumValue"); + + public static readonly BitmapImage Method = LoadBitmap("Method"); + public static readonly BitmapImage Constructor = LoadBitmap("Constructor"); + public static readonly BitmapImage VirtualMethod = LoadBitmap("VirtualMethod"); + public static readonly BitmapImage Operator = LoadBitmap("Operator"); + public static readonly BitmapImage ExtensionMethod = LoadBitmap("ExtensionMethod"); + public static readonly BitmapImage PInvokeMethod = LoadBitmap("PInvokeMethod"); + + public static readonly BitmapImage Property = LoadBitmap("Property"); + public static readonly BitmapImage Indexer = LoadBitmap("Indexer"); + + public static readonly BitmapImage Event = LoadBitmap("Event"); private static readonly BitmapImage OverlayProtected = LoadBitmap("OverlayProtected"); private static readonly BitmapImage OverlayInternal = LoadBitmap("OverlayInternal"); diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index fa623930e..4fbe51a1a 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -33,6 +33,9 @@ Command="BrowseForward" CanExecute="ForwardCommandCanExecute" Executed="ForwardCommandExecuted" /> + diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 5a1555b62..58add211b 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -506,6 +506,10 @@ namespace ICSharpCode.ILSpy } } + void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e) + { + SearchPane.Instance.Show(); + } #endregion #region Decompile (TreeView_SelectionChanged) diff --git a/ILSpy/SearchPane.cs b/ILSpy/SearchPane.cs index 13b7a1e71..d935b424c 100644 --- a/ILSpy/SearchPane.cs +++ b/ILSpy/SearchPane.cs @@ -61,9 +61,15 @@ namespace ICSharpCode.ILSpy } } + const int SearchMode_Type = 0; + const int SearchMode_Member = 1; + private SearchPane() { InitializeComponent(); + searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" }); + searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" }); + searchModeComboBox.SelectedIndex = SearchMode_Type; } public void Show() @@ -89,6 +95,11 @@ namespace ICSharpCode.ILSpy ((SearchPane)o).StartSearch((string)e.NewValue); } + void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + StartSearch(this.SearchTerm); + } + void StartSearch(string searchTerm) { if (currentSearch != null) { @@ -99,7 +110,7 @@ namespace ICSharpCode.ILSpy listBox.ItemsSource = null; } else { MainWindow mainWindow = MainWindow.Instance; - currentSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm, mainWindow.CurrentLanguage); + currentSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm, searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage); listBox.ItemsSource = currentSearch.Results; new Thread(currentSearch.Run).Start(); } @@ -118,7 +129,7 @@ namespace ICSharpCode.ILSpy void ListBox_KeyDown(object sender, KeyEventArgs e) { - if (e.Key == Key.Space || e.Key == Key.Return) { + if (e.Key == Key.Return) { e.Handled = true; JumpToSelectedItem(); } @@ -131,158 +142,191 @@ namespace ICSharpCode.ILSpy MainWindow.Instance.JumpToReference(result.Member); } } - } - - sealed class RunningSearch - { - readonly Dispatcher dispatcher; - readonly CancellationTokenSource cts = new CancellationTokenSource(); - readonly LoadedAssembly[] assemblies; - readonly string searchTerm; - readonly Language language; - public readonly ObservableCollection Results = new ObservableCollection(); - int resultCount; - - public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, Language language) - { - this.dispatcher = Dispatcher.CurrentDispatcher; - this.assemblies = assemblies; - this.searchTerm = searchTerm; - this.language = language; - } - public void Cancel() + protected override void OnKeyDown(KeyEventArgs e) { - cts.Cancel(); - } - - public void Run() - { - try { - foreach (var loadedAssembly in assemblies) { - AssemblyDefinition asm = loadedAssembly.AssemblyDefinition; - if (asm == null) - continue; - CancellationToken cancellationToken = cts.Token; - foreach (TypeDefinition type in asm.MainModule.Types) { - cancellationToken.ThrowIfCancellationRequested(); - PerformSearch(type); - } - } - } catch (OperationCanceledException) { - // ignore cancellation + base.OnKeyDown(e); + if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + searchModeComboBox.SelectedIndex = SearchMode_Type; + e.Handled = true; + } else if (e.Key == Key.M && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + searchModeComboBox.SelectedIndex = SearchMode_Member; + e.Handled = true; } } - void AddResult(SearchResult result) + void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e) { - if (++resultCount == 1000) { - result = new SearchResult { Name = "Search aborted, more than 1000 results found." }; - cts.Cancel(); + if (e.Key == Key.Down && listBox.HasItems) { + e.Handled = true; + listBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); + listBox.SelectedIndex = 0; } - dispatcher.BeginInvoke( - DispatcherPriority.Normal, - new Action(delegate { this.Results.Add(result); })); - cts.Token.ThrowIfCancellationRequested(); - } - - bool IsMatch(string text) - { - if (text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0) - return true; - else - return false; } - void PerformSearch(TypeDefinition type) + sealed class RunningSearch { - 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 - }); + readonly Dispatcher dispatcher; + readonly CancellationTokenSource cts = new CancellationTokenSource(); + readonly LoadedAssembly[] assemblies; + readonly string searchTerm; + readonly int searchMode; + readonly Language language; + public readonly ObservableCollection Results = new ObservableCollection(); + int resultCount; + + public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, int searchMode, Language language) + { + this.dispatcher = Dispatcher.CurrentDispatcher; + this.assemblies = assemblies; + this.searchTerm = searchTerm; + this.language = language; + this.searchMode = searchMode; + + this.Results.Add(new SearchResult { Name = "Searching..." }); } - foreach (TypeDefinition nestedType in type.NestedTypes) { - PerformSearch(nestedType); + public void Cancel() + { + cts.Cancel(); } - foreach (FieldDefinition field in type.Fields) { - if (IsMatch(field.Name)) { - AddResult(new SearchResult { - Member = field, - Image = FieldTreeNode.GetIcon(field), - Name = field.Name, - LocationImage = TypeTreeNode.GetIcon(type), - Location = language.TypeToString(type, includeNamespace: true) - }); + public void Run() + { + try { + foreach (var loadedAssembly in assemblies) { + AssemblyDefinition asm = loadedAssembly.AssemblyDefinition; + if (asm == null) + continue; + CancellationToken cancellationToken = cts.Token; + foreach (TypeDefinition type in asm.MainModule.Types) { + cancellationToken.ThrowIfCancellationRequested(); + PerformSearch(type); + } + } + } catch (OperationCanceledException) { + // ignore cancellation } + // remove the 'Searching...' entry + dispatcher.BeginInvoke( + DispatcherPriority.Normal, + new Action(delegate { this.Results.RemoveAt(this.Results.Count - 1); })); } - foreach (PropertyDefinition property in type.Properties) { - if (IsMatch(property.Name)) { - AddResult(new SearchResult { - Member = property, - Image = PropertyTreeNode.GetIcon(property), - Name = property.Name, - LocationImage = TypeTreeNode.GetIcon(type), - Location = language.TypeToString(type, includeNamespace: true) - }); + + void AddResult(SearchResult result) + { + if (++resultCount == 1000) { + result = new SearchResult { Name = "Search aborted, more than 1000 results found." }; + cts.Cancel(); } + dispatcher.BeginInvoke( + DispatcherPriority.Normal, + new Action(delegate { this.Results.Insert(this.Results.Count - 1, result); })); + cts.Token.ThrowIfCancellationRequested(); } - foreach (EventDefinition ev in type.Events) { - if (IsMatch(ev.Name)) { - AddResult(new SearchResult { - Member = ev, - Image = EventTreeNode.GetIcon(ev), - Name = ev.Name, - LocationImage = TypeTreeNode.GetIcon(type), - Location = language.TypeToString(type, includeNamespace: true) - }); - } + + bool IsMatch(string text) + { + if (text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0) + return true; + else + return false; } - foreach (MethodDefinition method in type.Methods) { - if (IsMatch(method.Name)) { + + void PerformSearch(TypeDefinition type) + { + if (searchMode == SearchMode_Type && IsMatch(type.Name)) { AddResult(new SearchResult { - Member = method, - Image = MethodTreeNode.GetIcon(method), - Name = method.Name, - LocationImage = TypeTreeNode.GetIcon(type), - Location = language.TypeToString(type, includeNamespace: true) + 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) { + PerformSearch(nestedType); + } + + if (searchMode == SearchMode_Type) + return; + + foreach (FieldDefinition field in type.Fields) { + if (IsMatch(field.Name)) { + 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.Name)) { + 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.Name)) { + 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) { + if (IsMatch(method.Name)) { + AddResult(new SearchResult { + Member = method, + Image = MethodTreeNode.GetIcon(method), + Name = method.Name, + LocationImage = TypeTreeNode.GetIcon(type), + Location = language.TypeToString(type, includeNamespace: true) + }); + } + } } } - } - - class SearchResult : INotifyPropertyChanged - { - 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() + sealed class SearchResult : INotifyPropertyChanged, IMemberTreeNode { - return Name; + 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; + } } } [ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon="Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)] - sealed class ShowSearchCommand : SimpleCommand + [ExportToolbarCommand(ToolTip = "Search (F3)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)] + sealed class ShowSearchCommand : CommandWrapper { - public override void Execute(object parameter) + public ShowSearchCommand() + : base(NavigationCommands.Search) { - SearchPane.Instance.Show(); } } } \ No newline at end of file diff --git a/ILSpy/SearchPane.xaml b/ILSpy/SearchPane.xaml index 3cc2290dd..daff5de85 100644 --- a/ILSpy/SearchPane.xaml +++ b/ILSpy/SearchPane.xaml @@ -1,19 +1,35 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + @@ -25,5 +41,5 @@ - + \ No newline at end of file