Browse Source

Fix #230: Search and Analyze window don't update

pull/252/merge
Daniel Grunwald 14 years ago
parent
commit
fe121acdb9
  1. 34
      ILSpy/AnalyzerTreeView.cs
  2. 2
      ILSpy/ILSpy.csproj
  3. 17
      ILSpy/MainWindow.xaml.cs
  4. 22
      ILSpy/SearchPane.cs
  5. 28
      ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs
  6. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  7. 12
      ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs
  8. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs
  9. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs
  10. 31
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs
  11. 31
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs
  12. 31
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs
  13. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  14. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs
  15. 30
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  16. 19
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  17. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  18. 12
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  19. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  20. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs
  21. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  22. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs
  23. 30
      ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs
  24. 53
      ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs
  25. 67
      ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs
  26. 11
      ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs
  27. 2
      ILSpy/TreeNodes/ThreadingSupport.cs
  28. 33
      SharpTreeView/SharpTreeNodeCollection.cs

34
ILSpy/AnalyzerTreeView.cs

@ -17,6 +17,9 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.TreeNodes.Analyzer; using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
@ -44,8 +47,24 @@ namespace ICSharpCode.ILSpy
private AnalyzerTreeView() private AnalyzerTreeView()
{ {
this.ShowRoot = false; this.ShowRoot = false;
this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage }; this.Root = new AnalyzerRootNode { Language = MainWindow.Instance.CurrentLanguage };
ContextMenuProvider.Add(this); 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<LoadedAssembly> removedAssemblies = new List<LoadedAssembly>();
if (e.OldItems != null)
removedAssemblies.AddRange(e.OldItems.Cast<LoadedAssembly>());
List<LoadedAssembly> addedAssemblies = new List<LoadedAssembly>();
if (e.NewItems != null)
addedAssemblies.AddRange(e.NewItems.Cast<LoadedAssembly>());
((AnalyzerRootNode)this.Root).HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
}
} }
public void Show() public void Show()
@ -68,5 +87,18 @@ namespace ICSharpCode.ILSpy
{ {
this.Root.Children.Clear(); this.Root.Children.Clear();
} }
sealed class AnalyzerRootNode : AnalyzerTreeNode
{
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)
{
this.Children.RemoveAll(
delegate(SharpTreeNode n) {
AnalyzerTreeNode an = n as AnalyzerTreeNode;
return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
});
return true;
}
}
} }
} }

2
ILSpy/ILSpy.csproj

@ -166,6 +166,8 @@
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" /> <Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventAccessorTreeNode.cs" /> <Compile Include="TreeNodes\Analyzer\AnalyzedEventAccessorTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedVirtualMethodUsedByTreeNode.cs" /> <Compile Include="TreeNodes\Analyzer\AnalyzedVirtualMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerEntityTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerSearchTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" /> <Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" /> <Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" />
<Compile Include="TreeNodes\BaseTypesEntryNode.cs" /> <Compile Include="TreeNodes\BaseTypesEntryNode.cs" />

17
ILSpy/MainWindow.xaml.cs

@ -33,7 +33,6 @@ using System.Windows.Media.Imaging;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using ICSharpCode.ILSpy.XmlDoc; using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
@ -214,6 +213,8 @@ namespace ICSharpCode.ILSpy
get { return assemblyList; } get { return assemblyList; }
} }
public event NotifyCollectionChangedEventHandler CurrentAssemblyListChanged;
List<LoadedAssembly> commandLineLoadedAssemblies = new List<LoadedAssembly>(); List<LoadedAssembly> commandLineLoadedAssemblies = new List<LoadedAssembly>();
bool HandleCommandLineArguments(CommandLineArguments args) bool HandleCommandLineArguments(CommandLineArguments args)
@ -331,9 +332,17 @@ namespace ICSharpCode.ILSpy
void assemblyList_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) void assemblyList_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{ {
if (e.OldItems != null) if (e.Action == NotifyCollectionChangedAction.Reset) {
foreach (LoadedAssembly asm in e.OldItems) history.RemoveAll(_ => true);
history.RemoveAll(n => n.TreeNodes.Any(nd => nd.AncestorsAndSelf().OfType<AssemblyTreeNode>().Any(a => a.LoadedAssembly == asm))); }
if (e.OldItems != null) {
var oldAssemblies = new HashSet<LoadedAssembly>(e.OldItems.Cast<LoadedAssembly>());
history.RemoveAll(n => n.TreeNodes.Any(
nd => nd.AncestorsAndSelf().OfType<AssemblyTreeNode>().Any(
a => oldAssemblies.Contains(a.LoadedAssembly))));
}
if (CurrentAssemblyListChanged != null)
CurrentAssemblyListChanged(this, e);
} }
void LoadInitialAssemblies() void LoadInitialAssemblies()

22
ILSpy/SearchPane.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; 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.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" }); searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.SelectedIndex = SearchMode_Type; 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() public void Show()
{ {
if (!IsVisible) if (!IsVisible) {
MainWindow.Instance.ShowInTopPane("Search", this); MainWindow.Instance.ShowInTopPane("Search", this);
if (runSearchOnNextShow) {
runSearchOnNextShow = false;
StartSearch(this.SearchTerm);
}
}
Dispatcher.BeginInvoke( Dispatcher.BeginInvoke(
DispatcherPriority.Background, DispatcherPriority.Background,
new Func<bool>(searchBox.Focus)); new Func<bool>(searchBox.Focus));

28
ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs

@ -27,13 +27,12 @@ using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedEventFiredByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedEventFiredByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly EventDefinition analyzedEvent; private readonly EventDefinition analyzedEvent;
private readonly FieldDefinition eventBackingField; private readonly FieldDefinition eventBackingField;
private readonly MethodDefinition eventFiringMethod; private readonly MethodDefinition eventFiringMethod;
private readonly ThreadingSupport threading;
private ConcurrentDictionary<MethodDefinition, int> foundMethods; private ConcurrentDictionary<MethodDefinition, int> foundMethods;
public AnalyzedEventFiredByTreeNode(EventDefinition analyzedEvent) public AnalyzedEventFiredByTreeNode(EventDefinition analyzedEvent)
@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedEvent"); throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent; this.analyzedEvent = analyzedEvent;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
this.eventBackingField = GetBackingField(analyzedEvent); this.eventBackingField = GetBackingField(analyzedEvent);
this.eventFiringMethod = analyzedEvent.EventType.Resolve().Methods.First(md => md.Name == "Invoke"); this.eventFiringMethod = analyzedEvent.EventType.Resolve().Methods.First(md => md.Name == "Invoke");
@ -54,26 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Raised By"; } get { return "Raised By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> 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<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
foundMethods = new ConcurrentDictionary<MethodDefinition, int>(); foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
@ -84,7 +62,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foundMethods = null; foundMethods = null;
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
// HACK: in lieu of proper flow analysis, I'm going to use a simple heuristic // 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 // If the method accesses the event's backing field, and calls invoke on a delegate

32
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -27,10 +27,9 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerSearchTreeNode
{ {
private readonly EventDefinition analyzedEvent; private readonly EventDefinition analyzedEvent;
private readonly ThreadingSupport threading;
public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent) public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent)
{ {
@ -38,8 +37,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedEvent"); throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent; this.analyzedEvent = analyzedEvent;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -47,36 +44,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Overridden By"; } get { return "Overridden By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedEvent, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedEvent, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string name = analyzedEvent.Name; string name = analyzedEvent.Name;
string declTypeName = analyzedEvent.DeclaringType.FullName; string declTypeName = analyzedEvent.DeclaringType.FullName;

12
ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs

@ -21,7 +21,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedEventTreeNode : AnalyzerTreeNode internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode
{ {
private readonly EventDefinition analyzedEvent; private readonly EventDefinition analyzedEvent;
private readonly string prefix; private readonly string prefix;
@ -35,6 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.LazyLoading = true; this.LazyLoading = true;
} }
public override MemberReference Member {
get { return analyzedEvent; }
}
public override object Icon public override object Icon
{ {
get { return EventTreeNode.GetIcon(analyzedEvent); } 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() protected override void LoadChildren()
{ {
if (analyzedEvent.AddMethod != null) if (analyzedEvent.AddMethod != null)

32
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs

@ -27,13 +27,12 @@ using System.Collections;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer 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 bool showWrites; // true: show writes; false: show read access
private readonly FieldDefinition analyzedField; private readonly FieldDefinition analyzedField;
private readonly ThreadingSupport threading;
private Lazy<Hashtable> foundMethods; private Lazy<Hashtable> foundMethods;
private object hashLock = new object(); private readonly object hashLock = new object();
public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites) public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites)
{ {
@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.analyzedField = analyzedField; this.analyzedField = analyzedField;
this.showWrites = showWrites; this.showWrites = showWrites;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -51,30 +48,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return showWrites ? "Assigned By" : "Read By"; } get { return showWrites ? "Assigned By" : "Read By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> 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<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
foundMethods = new Lazy<Hashtable>(LazyThreadSafetyMode.ExecutionAndPublication); foundMethods = new Lazy<Hashtable>(LazyThreadSafetyMode.ExecutionAndPublication);
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedField, FindReferencesInType); var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedField, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
@ -82,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foundMethods = null; foundMethods = null;
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string name = analyzedField.Name; string name = analyzedField.Name;
string declTypeName = analyzedField.DeclaringType.FullName; string declTypeName = analyzedField.DeclaringType.FullName;

11
ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs

@ -21,7 +21,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal class AnalyzedFieldTreeNode : AnalyzerTreeNode, IMemberTreeNode internal class AnalyzedFieldTreeNode : AnalyzerEntityTreeNode
{ {
private readonly FieldDefinition analyzedField; 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() protected override void LoadChildren()
{ {
this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, false)); this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, false));
@ -60,8 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true)); this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true));
} }
MemberReference IMemberTreeNode.Member public override MemberReference Member {
{
get { return analyzedField; } get { return analyzedField; }
} }
} }

31
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs

@ -26,11 +26,10 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly EventDefinition analyzedEvent; private readonly EventDefinition analyzedEvent;
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent) public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent)
{ {
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.analyzedEvent = analyzedEvent; this.analyzedEvent = analyzedEvent;
this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod; this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -48,35 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Implemented By"; } get { return "Implemented By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!type.HasInterfaces) if (!type.HasInterfaces)
yield break; yield break;

31
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs

@ -26,10 +26,9 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod) public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod)
{ {
@ -37,8 +36,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedMethod"); throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -46,35 +43,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Implemented By"; } get { return "Implemented By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!type.HasInterfaces) if (!type.HasInterfaces)
yield break; yield break;

31
ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs

@ -26,11 +26,10 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly PropertyDefinition analyzedProperty; private readonly PropertyDefinition analyzedProperty;
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty) public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty)
{ {
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.analyzedProperty = analyzedProperty; this.analyzedProperty = analyzedProperty;
this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod; this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -48,35 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Implemented By"; } get { return "Implemented By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!type.HasInterfaces) if (!type.HasInterfaces)
yield break; yield break;

32
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -32,10 +32,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// <summary> /// <summary>
/// Searches for overrides of the analyzed method. /// Searches for overrides of the analyzed method.
/// </summary> /// </summary>
internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerSearchTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod) public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod)
{ {
@ -43,8 +42,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedMethod"); throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -52,36 +49,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Overridden By"; } get { return "Overridden By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
AnalyzerTreeNode newNode = null; AnalyzerTreeNode newNode = null;
try { try {

11
ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs

@ -21,7 +21,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode internal class AnalyzedMethodTreeNode : AnalyzerEntityTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly string prefix; 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() protected override void LoadChildren()
{ {
if (analyzedMethod.HasBody) if (analyzedMethod.HasBody)
@ -71,8 +65,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod));
} }
MemberReference IMemberTreeNode.Member public override MemberReference Member {
{
get { return analyzedMethod; } get { return analyzedMethod; }
} }
} }

30
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -27,10 +27,9 @@ using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
private ConcurrentDictionary<MethodDefinition, int> foundMethods; private ConcurrentDictionary<MethodDefinition, int> foundMethods;
public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod)
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedMethod"); throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -48,30 +45,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Used By"; } get { return "Used By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> 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<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
foundMethods = new ConcurrentDictionary<MethodDefinition, int>(); foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType); var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
@ -79,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foundMethods = null; foundMethods = null;
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string name = analyzedMethod.Name; string name = analyzedMethod.Name;
foreach (MethodDefinition method in type.Methods) { foreach (MethodDefinition method in type.Methods) {

19
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
@ -27,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// <summary> /// <summary>
/// Shows the methods that are used by this method. /// Shows the methods that are used by this method.
/// </summary> /// </summary>
internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerTreeNode internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerSearchTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
@ -37,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedMethod"); throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -45,20 +45,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Uses"; } get { return "Uses"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
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<AnalyzerTreeNode> GetChildren()
{ {
foreach (var f in GetUsedFields().Distinct()) { foreach (var f in GetUsedFields().Distinct()) {
var node = new AnalyzedFieldTreeNode(f); var node = new AnalyzedFieldTreeNode(f);

32
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -28,10 +28,9 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerSearchTreeNode
{ {
private readonly PropertyDefinition analyzedProperty; private readonly PropertyDefinition analyzedProperty;
private readonly ThreadingSupport threading;
public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty) public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty)
{ {
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedProperty"); throw new ArgumentNullException("analyzedProperty");
this.analyzedProperty = analyzedProperty; this.analyzedProperty = analyzedProperty;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -48,36 +45,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Overridden By"; } get { return "Overridden By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedProperty, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedProperty, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string name = analyzedProperty.Name; string name = analyzedProperty.Name;
string declTypeName = analyzedProperty.DeclaringType.FullName; string declTypeName = analyzedProperty.DeclaringType.FullName;

12
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -22,7 +22,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedPropertyTreeNode : AnalyzerTreeNode internal sealed class AnalyzedPropertyTreeNode : AnalyzerEntityTreeNode
{ {
private readonly PropertyDefinition analyzedProperty; private readonly PropertyDefinition analyzedProperty;
private readonly bool isIndexer; 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() protected override void LoadChildren()
{ {
if (analyzedProperty.GetMethod != null) if (analyzedProperty.GetMethod != null)
@ -90,5 +84,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod) return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod)
|| AnalyzedPropertyOverridesTreeNode.CanShow(property); || AnalyzedPropertyOverridesTreeNode.CanShow(property);
} }
public override MemberReference Member {
get { return analyzedProperty; }
}
} }
} }

32
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -25,10 +25,9 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly TypeDefinition analyzedType; private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType) public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType)
{ {
@ -36,8 +35,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedType"); throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -45,36 +42,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Exposed By"; } get { return "Exposed By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (analyzedType.IsEnum && type == analyzedType) if (analyzedType.IsEnum && type == analyzedType)
yield break; yield break;

32
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs

@ -25,10 +25,9 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerSearchTreeNode
{ {
private readonly TypeDefinition analyzedType; private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType) public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType)
{ {
@ -36,8 +35,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedType"); throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -45,36 +42,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Extension Methods"; } get { return "Extension Methods"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!HasExtensionAttribute(type)) if (!HasExtensionAttribute(type))
yield break; yield break;

32
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -27,10 +27,9 @@ using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerSearchTreeNode
{ {
private readonly TypeDefinition analyzedType; private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
private readonly bool isSystemObject; private readonly bool isSystemObject;
public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType) public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType)
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedType"); throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
this.isSystemObject = (analyzedType.FullName == "System.Object"); this.isSystemObject = (analyzedType.FullName == "System.Object");
} }
@ -50,36 +47,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Instantiated By"; } get { return "Instantiated By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{ {
get { return Images.Search; } var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindReferencesInType);
}
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<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
foreach (MethodDefinition method in type.Methods) { foreach (MethodDefinition method in type.Methods) {
bool found = false; bool found = false;

11
ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs

@ -21,7 +21,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode internal class AnalyzedTypeTreeNode : AnalyzerEntityTreeNode
{ {
private readonly TypeDefinition analyzedType; 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() protected override void LoadChildren()
{ {
if (AnalyzedTypeInstantiationsTreeNode.CanShow(analyzedType)) if (AnalyzedTypeInstantiationsTreeNode.CanShow(analyzedType))
@ -64,8 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType)); this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType));
} }
MemberReference IMemberTreeNode.Member public override MemberReference Member {
{
get { return analyzedType; } get { return analyzedType; }
} }
} }

30
ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

@ -28,10 +28,9 @@ using ICSharpCode.Decompiler.Ast;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerTreeNode internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerSearchTreeNode
{ {
private readonly MethodDefinition analyzedMethod; private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
private ConcurrentDictionary<MethodDefinition, int> foundMethods; private ConcurrentDictionary<MethodDefinition, int> foundMethods;
private MethodDefinition baseMethod; private MethodDefinition baseMethod;
private List<TypeReference> possibleTypes; private List<TypeReference> possibleTypes;
@ -42,8 +41,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
throw new ArgumentNullException("analyzedMethod"); throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
} }
public override object Text public override object Text
@ -51,30 +48,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
get { return "Used By"; } get { return "Used By"; }
} }
public override object Icon protected override IEnumerable<AnalyzerTreeNode> 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<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
InitializeAnalyzer(); InitializeAnalyzer();
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType); var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child; yield return child;
} }
@ -107,7 +85,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
baseMethod = null; baseMethod = null;
} }
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string name = analyzedMethod.Name; string name = analyzedMethod.Name;
foreach (MethodDefinition method in type.Methods) { foreach (MethodDefinition method in type.Methods) {

53
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
{
/// <summary>
/// Base class for entity nodes.
/// </summary>
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<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> 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;
}
}
}

67
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
{
/// <summary>
/// Base class for analyzer nodes that perform a search.
/// </summary>
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<AnalyzerTreeNode> 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<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)
{
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
return true;
}
}
}

11
ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs

@ -17,12 +17,14 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq; using System.Linq;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
public class AnalyzerTreeNode : SharpTreeNode public abstract class AnalyzerTreeNode : SharpTreeNode
{ {
private Language language; private Language language;
@ -54,7 +56,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
DeleteCore(); DeleteCore();
} }
protected override void OnChildrenChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
{ {
if (e.NewItems != null) { if (e.NewItems != null) {
foreach (AnalyzerTreeNode a in e.NewItems.OfType<AnalyzerTreeNode>()) foreach (AnalyzerTreeNode a in e.NewItems.OfType<AnalyzerTreeNode>())
@ -62,5 +64,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
base.OnChildrenChanged(e); base.OnChildrenChanged(e);
} }
/// <summary>
/// Handles changes to the assembly list.
/// </summary>
public abstract bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies);
} }
} }

2
ILSpy/TreeNodes/ThreadingSupport.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
public bool IsRunning { public bool IsRunning {
get { return !loadChildrenTask.IsCompleted; } get { return loadChildrenTask != null && !loadChildrenTask.IsCompleted; }
} }
public void Cancel() public void Cancel()

33
SharpTreeView/SharpTreeNodeCollection.cs

@ -99,6 +99,8 @@ namespace ICSharpCode.TreeView
throw new ArgumentNullException("nodes"); throw new ArgumentNullException("nodes");
ThrowOnReentrancy(); ThrowOnReentrancy();
List<SharpTreeNode> newNodes = nodes.ToList(); List<SharpTreeNode> newNodes = nodes.ToList();
if (newNodes.Count == 0)
return;
foreach (SharpTreeNode node in newNodes) { foreach (SharpTreeNode node in newNodes) {
ThrowIfValueIsNullOrHasParent(node); ThrowIfValueIsNullOrHasParent(node);
} }
@ -117,6 +119,8 @@ namespace ICSharpCode.TreeView
public void RemoveRange(int index, int count) public void RemoveRange(int index, int count)
{ {
ThrowOnReentrancy(); ThrowOnReentrancy();
if (count == 0)
return;
var oldItems = list.GetRange(index, count); var oldItems = list.GetRange(index, count);
list.RemoveRange(index, count); list.RemoveRange(index, count);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, index)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, index));
@ -173,5 +177,34 @@ namespace ICSharpCode.TreeView
{ {
return list.GetEnumerator(); return list.GetEnumerator();
} }
public void RemoveAll(Predicate<SharpTreeNode> 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);
}
}
} }
} }

Loading…
Cancel
Save