diff --git a/ILSpy/AnalyzerTreeView.cs b/ILSpy/AnalyzerTreeView.cs index 94f4ed66c..b0088cbc5 100644 --- a/ILSpy/AnalyzerTreeView.cs +++ b/ILSpy/AnalyzerTreeView.cs @@ -17,6 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; using ICSharpCode.ILSpy.TreeNodes.Analyzer; using ICSharpCode.TreeView; @@ -44,8 +47,24 @@ namespace ICSharpCode.ILSpy private AnalyzerTreeView() { this.ShowRoot = false; - this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage }; + this.Root = new AnalyzerRootNode { Language = MainWindow.Instance.CurrentLanguage }; ContextMenuProvider.Add(this); + MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged; + } + + void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Reset) { + this.Root.Children.Clear(); + } else { + List removedAssemblies = new List(); + if (e.OldItems != null) + removedAssemblies.AddRange(e.OldItems.Cast()); + List addedAssemblies = new List(); + if (e.NewItems != null) + addedAssemblies.AddRange(e.NewItems.Cast()); + ((AnalyzerRootNode)this.Root).HandleAssemblyListChanged(removedAssemblies, addedAssemblies); + } } public void Show() @@ -68,5 +87,18 @@ namespace ICSharpCode.ILSpy { this.Root.Children.Clear(); } + + sealed class AnalyzerRootNode : AnalyzerTreeNode + { + public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) + { + this.Children.RemoveAll( + delegate(SharpTreeNode n) { + AnalyzerTreeNode an = n as AnalyzerTreeNode; + return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); + }); + return true; + } + } } } \ No newline at end of file diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index a3616b2f9..0f5729696 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -166,6 +166,8 @@ + + diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index a1f5da3fc..8b2a6d57b 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -33,7 +33,6 @@ using System.Windows.Media.Imaging; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.ILSpy.TreeNodes.Analyzer; using ICSharpCode.ILSpy.XmlDoc; using ICSharpCode.TreeView; using Microsoft.Win32; @@ -214,6 +213,8 @@ namespace ICSharpCode.ILSpy get { return assemblyList; } } + public event NotifyCollectionChangedEventHandler CurrentAssemblyListChanged; + List commandLineLoadedAssemblies = new List(); bool HandleCommandLineArguments(CommandLineArguments args) @@ -331,9 +332,17 @@ namespace ICSharpCode.ILSpy void assemblyList_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (e.OldItems != null) - foreach (LoadedAssembly asm in e.OldItems) - history.RemoveAll(n => n.TreeNodes.Any(nd => nd.AncestorsAndSelf().OfType().Any(a => a.LoadedAssembly == asm))); + if (e.Action == NotifyCollectionChangedAction.Reset) { + history.RemoveAll(_ => true); + } + if (e.OldItems != null) { + var oldAssemblies = new HashSet(e.OldItems.Cast()); + history.RemoveAll(n => n.TreeNodes.Any( + nd => nd.AncestorsAndSelf().OfType().Any( + a => oldAssemblies.Contains(a.LoadedAssembly)))); + } + if (CurrentAssemblyListChanged != null) + CurrentAssemblyListChanged(this, e); } void LoadInitialAssemblies() diff --git a/ILSpy/SearchPane.cs b/ILSpy/SearchPane.cs index 1b829ea71..b7b7e16b5 100644 --- a/ILSpy/SearchPane.cs +++ b/ILSpy/SearchPane.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Text; @@ -62,12 +63,31 @@ namespace ICSharpCode.ILSpy searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" }); searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" }); searchModeComboBox.SelectedIndex = SearchMode_Type; + + MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged; + } + + bool runSearchOnNextShow; + + void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (IsVisible) { + StartSearch(this.SearchTerm); + } else { + StartSearch(null); + runSearchOnNextShow = true; + } } public void Show() { - if (!IsVisible) + if (!IsVisible) { MainWindow.Instance.ShowInTopPane("Search", this); + if (runSearchOnNextShow) { + runSearchOnNextShow = false; + StartSearch(this.SearchTerm); + } + } Dispatcher.BeginInvoke( DispatcherPriority.Background, new Func(searchBox.Focus)); diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs index f0247dc55..f2681ae8b 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs @@ -27,13 +27,12 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedEventFiredByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventFiredByTreeNode : AnalyzerSearchTreeNode { private readonly EventDefinition analyzedEvent; private readonly FieldDefinition eventBackingField; private readonly MethodDefinition eventFiringMethod; - private readonly ThreadingSupport threading; private ConcurrentDictionary foundMethods; public AnalyzedEventFiredByTreeNode(EventDefinition analyzedEvent) @@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedEvent"); this.analyzedEvent = analyzedEvent; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; this.eventBackingField = GetBackingField(analyzedEvent); this.eventFiringMethod = analyzedEvent.EventType.Resolve().Methods.First(md => md.Name == "Invoke"); @@ -54,26 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Raised By"; } } - public override object Icon - { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) + protected override IEnumerable FetchChildren(CancellationToken ct) { foundMethods = new ConcurrentDictionary(); @@ -84,7 +62,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foundMethods = null; } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { // HACK: in lieu of proper flow analysis, I'm going to use a simple heuristic // If the method accesses the event's backing field, and calls invoke on a delegate diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index 99aa27af6..156c9c091 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -27,10 +27,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerSearchTreeNode { private readonly EventDefinition analyzedEvent; - private readonly ThreadingSupport threading; public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent) { @@ -38,8 +37,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedEvent"); this.analyzedEvent = analyzedEvent; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -47,36 +44,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Overridden By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedEvent, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedEvent, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedEvent.Name; string declTypeName = analyzedEvent.DeclaringType.FullName; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs index 84a937942..47e072889 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs @@ -21,7 +21,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedEventTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode { private readonly EventDefinition analyzedEvent; private readonly string prefix; @@ -35,6 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.LazyLoading = true; } + public override MemberReference Member { + get { return analyzedEvent; } + } + public override object Icon { get { return EventTreeNode.GetIcon(analyzedEvent); } @@ -49,12 +53,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = true; - MainWindow.Instance.JumpToReference(analyzedEvent); - } - protected override void LoadChildren() { if (analyzedEvent.AddMethod != null) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs index edc14fd04..0075c5add 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs @@ -27,13 +27,12 @@ using System.Collections; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedFieldAccessTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedFieldAccessTreeNode : AnalyzerSearchTreeNode { private readonly bool showWrites; // true: show writes; false: show read access private readonly FieldDefinition analyzedField; - private readonly ThreadingSupport threading; private Lazy foundMethods; - private object hashLock = new object(); + private readonly object hashLock = new object(); public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites) { @@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedField = analyzedField; this.showWrites = showWrites; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -51,30 +48,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return showWrites ? "Assigned By" : "Read By"; } } - public override object Icon - { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) + protected override IEnumerable FetchChildren(CancellationToken ct) { foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); - var analyzer = new ScopedWhereUsedAnalyzer(analyzedField, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedField, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -82,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foundMethods = null; } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedField.Name; string declTypeName = analyzedField.DeclaringType.FullName; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs index 6e08c566e..6a6fa7574 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs @@ -21,7 +21,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal class AnalyzedFieldTreeNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedFieldTreeNode : AnalyzerEntityTreeNode { private readonly FieldDefinition analyzedField; @@ -47,12 +47,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = true; - MainWindow.Instance.JumpToReference(analyzedField); - } - protected override void LoadChildren() { this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, false)); @@ -60,8 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true)); } - MemberReference IMemberTreeNode.Member - { + public override MemberReference Member { get { return analyzedField; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs index f6773be82..761b4fc3e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs @@ -26,11 +26,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerSearchTreeNode { private readonly EventDefinition analyzedEvent; private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent) { @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedEvent = analyzedEvent; this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -48,35 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Implemented By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs index 3f139e040..00a8eadc1 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs @@ -26,10 +26,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerSearchTreeNode { private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod) { @@ -37,8 +36,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedMethod"); this.analyzedMethod = analyzedMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -46,35 +43,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Implemented By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs index 56f89ad13..b6c56f3cd 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs @@ -26,11 +26,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerSearchTreeNode { private readonly PropertyDefinition analyzedProperty; private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty) { @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedProperty = analyzedProperty; this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -48,35 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Implemented By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index 4e8af7663..a50d93aab 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -32,10 +32,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Searches for overrides of the analyzed method. /// - internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerSearchTreeNode { private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod) { @@ -43,8 +42,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedMethod"); this.analyzedMethod = analyzedMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -52,36 +49,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Overridden By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { AnalyzerTreeNode newNode = null; try { diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs index ad7654eae..615d06e38 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs @@ -21,7 +21,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedMethodTreeNode : AnalyzerEntityTreeNode { private readonly MethodDefinition analyzedMethod; private readonly string prefix; @@ -48,12 +48,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = true; - MainWindow.Instance.JumpToReference(analyzedMethod); - } - protected override void LoadChildren() { if (analyzedMethod.HasBody) @@ -71,8 +65,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod)); } - MemberReference IMemberTreeNode.Member - { + public override MemberReference Member { get { return analyzedMethod; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index 175ce4efc..989de1cab 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -27,10 +27,9 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerSearchTreeNode { private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; private ConcurrentDictionary foundMethods; public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedMethod"); this.analyzedMethod = analyzedMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -48,30 +45,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Used By"; } } - public override object Icon - { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) + protected override IEnumerable FetchChildren(CancellationToken ct) { foundMethods = new ConcurrentDictionary(); - var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -79,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foundMethods = null; } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedMethod.Name; foreach (MethodDefinition method in type.Methods) { diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs index 1b18a9ae1..a072dfe0a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using Mono.Cecil; using Mono.Cecil.Cil; @@ -27,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Shows the methods that are used by this method. /// - internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerSearchTreeNode { private readonly MethodDefinition analyzedMethod; @@ -37,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedMethod"); this.analyzedMethod = analyzedMethod; - this.LazyLoading = true; } public override object Text @@ -45,20 +45,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Uses"; } } - public override object Icon - { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - analyzedMethod.Body = null; - foreach (var child in GetChildren().OrderBy(n => n.Text)) { - this.Children.Add(child); - } - } - - private IEnumerable GetChildren() + protected override IEnumerable FetchChildren(CancellationToken ct) { foreach (var f in GetUsedFields().Distinct()) { var node = new AnalyzedFieldTreeNode(f); diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index 8f264d7ff..a75b11a00 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -28,10 +28,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerSearchTreeNode { private readonly PropertyDefinition analyzedProperty; - private readonly ThreadingSupport threading; public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty) { @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedProperty"); this.analyzedProperty = analyzedProperty; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -48,36 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Overridden By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedProperty, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedProperty, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedProperty.Name; string declTypeName = analyzedProperty.DeclaringType.FullName; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs index b08127b52..2623bed8f 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs @@ -22,7 +22,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedPropertyTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedPropertyTreeNode : AnalyzerEntityTreeNode { private readonly PropertyDefinition analyzedProperty; private readonly bool isIndexer; @@ -52,12 +52,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = true; - MainWindow.Instance.JumpToReference(analyzedProperty); - } - protected override void LoadChildren() { if (analyzedProperty.GetMethod != null) @@ -90,5 +84,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod) || AnalyzedPropertyOverridesTreeNode.CanShow(property); } + + public override MemberReference Member { + get { return analyzedProperty; } + } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs index 26c2bca71..9f71749a1 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -25,10 +25,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerSearchTreeNode { private readonly TypeDefinition analyzedType; - private readonly ThreadingSupport threading; public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType) { @@ -36,8 +35,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedType"); this.analyzedType = analyzedType; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -45,36 +42,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Exposed By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (analyzedType.IsEnum && type == analyzedType) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs index 605190b88..8d80d17bf 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -25,10 +25,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode + internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerSearchTreeNode { private readonly TypeDefinition analyzedType; - private readonly ThreadingSupport threading; public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType) { @@ -36,8 +35,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedType"); this.analyzedType = analyzedType; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -45,36 +42,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Extension Methods"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!HasExtensionAttribute(type)) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index 10b477bcf..0ab354ce4 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -27,10 +27,9 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerSearchTreeNode { private readonly TypeDefinition analyzedType; - private readonly ThreadingSupport threading; private readonly bool isSystemObject; public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType) @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedType"); this.analyzedType = analyzedType; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; this.isSystemObject = (analyzedType.FullName == "System.Object"); } @@ -50,36 +47,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Instantiated By"; } } - public override object Icon + protected override IEnumerable FetchChildren(CancellationToken ct) { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) - { - ScopedWhereUsedAnalyzer analyzer; - - analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { foreach (MethodDefinition method in type.Methods) { bool found = false; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs index bc50ffbec..4e3f623f0 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs @@ -21,7 +21,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedTypeTreeNode : AnalyzerEntityTreeNode { private readonly TypeDefinition analyzedType; @@ -46,12 +46,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = true; - MainWindow.Instance.JumpToReference(analyzedType); - } - protected override void LoadChildren() { if (AnalyzedTypeInstantiationsTreeNode.CanShow(analyzedType)) @@ -64,8 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType)); } - MemberReference IMemberTreeNode.Member - { + public override MemberReference Member { get { return analyzedType; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs index f31eb5d5e..f8d15423c 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs @@ -28,10 +28,9 @@ using ICSharpCode.Decompiler.Ast; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerSearchTreeNode { private readonly MethodDefinition analyzedMethod; - private readonly ThreadingSupport threading; private ConcurrentDictionary foundMethods; private MethodDefinition baseMethod; private List possibleTypes; @@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer throw new ArgumentNullException("analyzedMethod"); this.analyzedMethod = analyzedMethod; - this.threading = new ThreadingSupport(); - this.LazyLoading = true; } public override object Text @@ -51,30 +48,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer get { return "Used By"; } } - public override object Icon - { - get { return Images.Search; } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - protected override void OnCollapsing() - { - if (threading.IsRunning) { - this.LazyLoading = true; - threading.Cancel(); - this.Children.Clear(); - } - } - - private IEnumerable FetchChildren(CancellationToken ct) + protected override IEnumerable FetchChildren(CancellationToken ct) { InitializeAnalyzer(); - var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -107,7 +85,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer baseMethod = null; } - private IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedMethod.Name; foreach (MethodDefinition method in type.Methods) { diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs new file mode 100644 index 000000000..184caa0fa --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + /// + /// Base class for entity nodes. + /// + public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode + { + public abstract MemberReference Member { get; } + + public override void ActivateItem(System.Windows.RoutedEventArgs e) + { + e.Handled = true; + MainWindow.Instance.JumpToReference(this.Member); + } + + public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) + { + foreach (LoadedAssembly asm in removedAssemblies) { + if (this.Member.Module.Assembly == asm.AssemblyDefinition) + return false; // remove this node + } + this.Children.RemoveAll( + delegate(SharpTreeNode n) { + AnalyzerTreeNode an = n as AnalyzerTreeNode; + return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); + }); + return true; + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs new file mode 100644 index 000000000..441c65ee6 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Threading; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + /// + /// Base class for analyzer nodes that perform a search. + /// + public abstract class AnalyzerSearchTreeNode : AnalyzerTreeNode + { + private readonly ThreadingSupport threading = new ThreadingSupport(); + + protected AnalyzerSearchTreeNode() + { + this.LazyLoading = true; + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected abstract IEnumerable FetchChildren(CancellationToken ct); + + protected override void OnIsVisibleChanged() + { + base.OnIsVisibleChanged(); + if (!this.IsVisible && threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) + { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + return true; + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs index 29e8e76f0..e6268def0 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs @@ -17,12 +17,14 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - public class AnalyzerTreeNode : SharpTreeNode + public abstract class AnalyzerTreeNode : SharpTreeNode { private Language language; @@ -54,7 +56,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer DeleteCore(); } - protected override void OnChildrenChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (AnalyzerTreeNode a in e.NewItems.OfType()) @@ -62,5 +64,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } base.OnChildrenChanged(e); } + + /// + /// Handles changes to the assembly list. + /// + public abstract bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies); } } diff --git a/ILSpy/TreeNodes/ThreadingSupport.cs b/ILSpy/TreeNodes/ThreadingSupport.cs index 737bc3724..139993354 100644 --- a/ILSpy/TreeNodes/ThreadingSupport.cs +++ b/ILSpy/TreeNodes/ThreadingSupport.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); public bool IsRunning { - get { return !loadChildrenTask.IsCompleted; } + get { return loadChildrenTask != null && !loadChildrenTask.IsCompleted; } } public void Cancel() diff --git a/SharpTreeView/SharpTreeNodeCollection.cs b/SharpTreeView/SharpTreeNodeCollection.cs index b49881304..3fcd25f83 100644 --- a/SharpTreeView/SharpTreeNodeCollection.cs +++ b/SharpTreeView/SharpTreeNodeCollection.cs @@ -99,6 +99,8 @@ namespace ICSharpCode.TreeView throw new ArgumentNullException("nodes"); ThrowOnReentrancy(); List newNodes = nodes.ToList(); + if (newNodes.Count == 0) + return; foreach (SharpTreeNode node in newNodes) { ThrowIfValueIsNullOrHasParent(node); } @@ -117,6 +119,8 @@ namespace ICSharpCode.TreeView public void RemoveRange(int index, int count) { ThrowOnReentrancy(); + if (count == 0) + return; var oldItems = list.GetRange(index, count); list.RemoveRange(index, count); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, index)); @@ -173,5 +177,34 @@ namespace ICSharpCode.TreeView { return list.GetEnumerator(); } + + public void RemoveAll(Predicate match) + { + if (match == null) + throw new ArgumentNullException("match"); + ThrowOnReentrancy(); + int firstToRemove = 0; + for (int i = 0; i < list.Count; i++) { + bool removeNode; + isRaisingEvent = true; + try { + removeNode = match(list[i]); + } finally { + isRaisingEvent = false; + } + if (!removeNode) { + if (firstToRemove < i) { + RemoveRange(firstToRemove, i - firstToRemove); + i = firstToRemove - 1; + } else { + firstToRemove = i + 1; + } + Debug.Assert(firstToRemove == i + 1); + } + } + if (firstToRemove < list.Count) { + RemoveRange(firstToRemove, list.Count - firstToRemove); + } + } } }