diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
index 8e37d22fb..6b1e3ee63 100644
--- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
+++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
@@ -31,15 +31,17 @@ namespace ICSharpCode.ILSpy.Analyzers
private readonly ThreadingSupport threading = new ThreadingSupport();
readonly ISymbol symbol;
readonly IAnalyzer analyzer;
+ readonly string analyzerHeader;
- public AnalyzerSearchTreeNode(ISymbol symbol, IAnalyzer analyzer)
+ public AnalyzerSearchTreeNode(ISymbol symbol, IAnalyzer analyzer, string analyzerHeader)
{
this.symbol = symbol;
this.analyzer = analyzer ?? throw new ArgumentNullException(nameof(analyzer));
this.LazyLoading = true;
+ this.analyzerHeader = analyzerHeader;
}
- public override object Text => analyzer.Text + (Children.Count > 0 ? " (" + Children.Count + ")" : "");
+ public override object Text => analyzerHeader + (Children.Count > 0 ? " (" + Children.Count + ")" : "");
public override object Icon => Images.Search;
diff --git a/ILSpy/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs
index 144f6e1e3..c6efcd98f 100644
--- a/ILSpy/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs
@@ -27,11 +27,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows events that implement an interface event.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Implemented By", Order = 10)]
class EventImplementsInterfaceAnalyzer : IAnalyzer
{
- public string Text => "Implemented By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IEvent);
diff --git a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
index 7a66292f9..2688f72c3 100644
--- a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
@@ -27,11 +27,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows events that override an event.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Overridden By", Order = 20)]
class EventOverriddenByAnalyzer : IAnalyzer
{
- public string Text => "Overridden By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IEvent);
diff --git a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs
index 37ee16e2b..e3b414423 100644
--- a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs
@@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Finds methods where this field is read.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Assigned By", Order = 20)]
class AssignedByFieldAccessAnalyzer : FieldAccessAnalyzer
{
public AssignedByFieldAccessAnalyzer() : base(true) { }
@@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Finds methods where this field is written.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Read By", Order = 10)]
class ReadByFieldAccessAnalyzer : FieldAccessAnalyzer
{
public ReadByFieldAccessAnalyzer() : base(false) { }
@@ -61,8 +61,6 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
readonly bool showWrites; // true: show writes; false: show read access
- public string Text => showWrites ? "Assigned By" : "Read By";
-
public FieldAccessAnalyzer(bool showWrites)
{
this.showWrites = showWrites;
diff --git a/ILSpy/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs
index 0b5013328..75c8c4e6a 100644
--- a/ILSpy/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs
@@ -30,11 +30,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows methods that implement an interface method.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Implemented By", Order = 40)]
class MethodImplementsInterfaceAnalyzer : IAnalyzer
{
- public string Text => "Implemented By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IMethod);
diff --git a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
index 2c8f25e97..95004dff6 100644
--- a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
@@ -27,13 +27,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows methods that override a method.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Overridden By", Order = 30)]
class MethodOverriddenByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
- public string Text => "Overridden By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IMethod);
diff --git a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs
index 1b2bd1d21..c89424c05 100644
--- a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs
@@ -31,13 +31,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows entities that are used by a method.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Used By", Order = 20)]
class MethodUsedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
- public string Text => "Used By";
-
public bool Show(ISymbol symbol) => symbol is IMethod method && !method.IsVirtual;
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
diff --git a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs
index 01c00bbd3..8c6436890 100644
--- a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs
@@ -33,12 +33,10 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows entities that are used by a method.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Uses", Order = 10)]
class MethodUsesAnalyzer : IAnalyzer
{
- public string Text => "Uses";
-
- public bool Show(ISymbol symbol) => symbol is IMethod method && !method.IsVirtual;
+ public bool Show(ISymbol symbol) => symbol is IMethod method && method.HasBody;
public IEnumerable Analyze(ISymbol symbol, AnalyzerContext context)
{
diff --git a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
index 06fb4f4c2..8bdc3aee5 100644
--- a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
@@ -31,13 +31,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows entities that are used by a method.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Used By", Order = 20)]
class MethodVirtualUsedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
- public string Text => "Used By";
-
public bool Show(ISymbol symbol) => symbol is IMethod method && method.IsVirtual;
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
diff --git a/ILSpy/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs
index af58769e9..938e0e4e2 100644
--- a/ILSpy/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs
@@ -27,11 +27,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows properties that implement an interface property.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Implemented By", Order = 10)]
class PropertyImplementsInterfaceAnalyzer : IAnalyzer
{
- public string Text => "Implemented By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IProperty);
diff --git a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
index df26da28f..b253a447d 100644
--- a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
@@ -30,11 +30,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows properties that override a property.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Overridden By", Order = 20)]
class PropertyOverriddenByAnalyzer : IAnalyzer
{
- public string Text => "Overridden By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IProperty);
diff --git a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs
index c48275cbc..87bd95e01 100644
--- a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs
@@ -30,11 +30,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Finds all entities that expose a type.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Exposed By", Order = 40)]
class TypeExposedByAnalyzer : IAnalyzer
{
- public string Text => "Exposed By";
-
public bool Show(ISymbol entity) => entity is ITypeDefinition;
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
diff --git a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
index b51a7a5a5..1d2a1d960 100644
--- a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
@@ -8,11 +8,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Finds all extension methods defined for a type.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Extension Methods", Order = 50)]
class TypeExtensionMethodsAnalyzer : IAnalyzer
{
- public string Text => "Extension Methods";
-
public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic;
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
diff --git a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
index 31c0c1819..cfb9252d6 100644
--- a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
@@ -34,13 +34,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows methods that instantiate a type.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Instantiated By", Order = 20)]
class TypeInstantiatedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
- public string Text => "Instantiated By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is ITypeDefinition);
diff --git a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs
index d45ec521e..862bc162f 100644
--- a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs
+++ b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs
@@ -32,11 +32,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
///
/// Shows entities that use a type.
///
- [Export(typeof(IAnalyzer))]
+ [ExportAnalyzer(Header = "Used By", Order = 30)]
class TypeUsedByAnalyzer : IAnalyzer
{
- public string Text => "Used By";
-
public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is ITypeDefinition);
diff --git a/ILSpy/Analyzers/IAnalyzer.cs b/ILSpy/Analyzers/IAnalyzer.cs
index c1281f8fa..c9a6db526 100644
--- a/ILSpy/Analyzers/IAnalyzer.cs
+++ b/ILSpy/Analyzers/IAnalyzer.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
@@ -33,11 +34,6 @@ namespace ICSharpCode.ILSpy.Analyzers
///
public interface IAnalyzer
{
- ///
- /// The caption used in the analyzer tree view.
- ///
- string Text { get; }
-
///
/// Returns true, if the analyzer should be shown for a symbol, otherwise false.
///
@@ -80,4 +76,22 @@ namespace ICSharpCode.ILSpy.Analyzers
return new AnalyzerScope(AssemblyList, entity);
}
}
+
+ [MetadataAttribute]
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class ExportAnalyzerAttribute : ExportAttribute, IAnalyzerMetadata
+ {
+ public ExportAnalyzerAttribute() : base("Analyzer", typeof(IAnalyzer))
+ { }
+
+ public string Header { get; set; }
+
+ public int Order { get; set; }
+ }
+
+ public interface IAnalyzerMetadata
+ {
+ string Header { get; }
+ int Order { get; }
+ }
}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
index 02c7f71bc..07e73c157 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
@@ -54,10 +54,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
//foreach (var accessor in analyzedEvent.OtherMethods)
// this.Children.Add(new AnalyzedAccessorTreeNode(accessor, null));
- foreach (var lazy in App.ExportProvider.GetExports()) {
+ var analyzers = App.ExportProvider.GetExports("Analyzer");
+ foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) {
var analyzer = lazy.Value;
if (analyzer.Show(analyzedEvent)) {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedEvent, analyzer));
+ this.Children.Add(new AnalyzerSearchTreeNode(analyzedEvent, analyzer, lazy.Metadata.Header));
}
}
}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
index c89a77313..c429e14ab 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -38,10 +39,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
protected override void LoadChildren()
{
- foreach (var lazy in App.ExportProvider.GetExports()) {
+ var analyzers = App.ExportProvider.GetExports("Analyzer");
+ foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) {
var analyzer = lazy.Value;
if (analyzer.Show(analyzedField)) {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedField, analyzer));
+ this.Children.Add(new AnalyzerSearchTreeNode(analyzedField, analyzer, lazy.Metadata.Header));
}
}
}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
index 53c2790b4..783427b16 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -40,10 +41,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
protected override void LoadChildren()
{
- foreach (var lazy in App.ExportProvider.GetExports()) {
+ var analyzers = App.ExportProvider.GetExports("Analyzer");
+ foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) {
var analyzer = lazy.Value;
if (analyzer.Show(analyzedMethod)) {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer));
+ this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer, lazy.Metadata.Header));
}
}
}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
index b230ed789..c1c81541e 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -48,10 +49,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
//foreach (var accessor in analyzedProperty.OtherMethods)
// this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null));
- foreach (var lazy in App.ExportProvider.GetExports()) {
+ var analyzers = App.ExportProvider.GetExports("Analyzer");
+ foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) {
var analyzer = lazy.Value;
if (analyzer.Show(analyzedProperty)) {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer));
+ this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer, lazy.Metadata.Header));
}
}
}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
index 497de3bd5..6c9622d7b 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -38,10 +39,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
protected override void LoadChildren()
{
- foreach (var lazy in App.ExportProvider.GetExports()) {
+ var analyzers = App.ExportProvider.GetExports("Analyzer");
+ foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) {
var analyzer = lazy.Value;
if (analyzer.Show(analyzedType)) {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer));
+ this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer, lazy.Metadata.Header));
}
}
}