From 0a0ca73d79d175ca902fd46ce470b933e52f5614 Mon Sep 17 00:00:00 2001
From: wuyangfan <1102042793@qq.com>
Date: Sun, 17 May 2026 22:29:07 +0800
Subject: [PATCH] feat(analyzer): syntax-highlight entity signatures in Analyze
panel
Render analyzer result entries with C# syntax coloring so type and member
names are easier to scan in long signature lists.
Also fix "assmbly" -> "assembly" in ilspycmd help text.
Fixes #2164
---
ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs | 4 ++--
ICSharpCode.ILSpyCmd/README.md | 4 ++--
ILSpy/Analyzers/AnalyzerEntityTreeNode.cs | 20 +++++++++++++++++++
.../TreeNodes/AnalyzedEventTreeNode.cs | 2 +-
.../TreeNodes/AnalyzedFieldTreeNode.cs | 2 +-
.../TreeNodes/AnalyzedMethodTreeNode.cs | 2 +-
.../TreeNodes/AnalyzedPropertyTreeNode.cs | 2 +-
.../TreeNodes/AnalyzedTypeTreeNode.cs | 2 +-
8 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs b/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs
index 36587d730d..4dcc350b3e 100644
--- a/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs
+++ b/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs
@@ -171,8 +171,8 @@ class ILSpyCmdProgram
public bool ReportExcludedTypes { get; set; }
[Option(generateDiagrammerCmd + "-docs", "The path or file:// URI of the XML file containing the target assembly's documentation comments." +
- " You only need to set this if a) you want your diagrams annotated with them and b) the file name differs from that of the assmbly." +
- " To enable XML documentation output for your assmbly, see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/#create-xml-documentation-output",
+ " You only need to set this if a) you want your diagrams annotated with them and b) the file name differs from that of the assembly." +
+ " To enable XML documentation output for your assembly, see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/#create-xml-documentation-output",
CommandOptionType.SingleValue)]
public string XmlDocs { get; set; }
diff --git a/ICSharpCode.ILSpyCmd/README.md b/ICSharpCode.ILSpyCmd/README.md
index e523fa1220..f4924eb3f3 100644
--- a/ICSharpCode.ILSpyCmd/README.md
+++ b/ICSharpCode.ILSpyCmd/README.md
@@ -70,8 +70,8 @@ Options:
your regular expressions.
--generate-diagrammer-docs The path or file:// URI of the XML file containing the target assembly's
documentation comments. You only need to set this if a) you want your diagrams
- annotated with them and b) the file name differs from that of the assmbly. To
- enable XML documentation output for your assmbly, see
+ annotated with them and b) the file name differs from that of the assembly. To
+ enable XML documentation output for your assembly, see
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/#create-xml-documentation-output
--generate-diagrammer-strip-namespaces Optional space-separated namespace names that are removed for brevity from XML
documentation comments. Note that the order matters: e.g. replace
diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
index c86dc1e808..25b0493746 100644
--- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
+++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
@@ -19,7 +19,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
+using System.Windows.Controls;
+using ICSharpCode.AvalonEdit.Document;
+using ICSharpCode.AvalonEdit.Highlighting;
+using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX;
@@ -57,6 +61,22 @@ public override void ActivateItem(IPlatformRoutedEventArgs e)
public override object? ToolTip => Member?.ParentModule?.MetadataFile?.FileName;
+ ///
+ /// Renders a member signature with C# syntax highlighting for the Analyze tree view.
+ ///
+ protected object CreateHighlightedSignatureText(string signature)
+ {
+ IHighlightingDefinition? highlighting = Language.SyntaxHighlighting;
+ if (highlighting == null)
+ return signature;
+
+ var document = new TextDocument(signature);
+ var richText = DocumentPrinter.ConvertTextDocumentToRichText(document, new DocumentHighlighter(document, highlighting)).ToRichTextModel();
+ var textBlock = new TextBlock();
+ textBlock.Inlines.AddRange(richText.CreateRuns(document));
+ return textBlock;
+ }
+
public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies)
{
if (Member == null)
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
index 9df55a0614..372cfbdd66 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
@@ -46,7 +46,7 @@ public AnalyzedEventTreeNode(IEvent analyzedEvent, IEntity? source, string prefi
public override object Icon => EventTreeNode.GetIcon(analyzedEvent);
// TODO: This way of formatting is not suitable for events which explicitly implement interfaces.
- public override object Text => prefix + Language.EntityToString(analyzedEvent, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
+ public override object Text => CreateHighlightedSignatureText(prefix + Language.EntityToString(analyzedEvent, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames));
protected override void LoadChildren()
{
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
index 64a508c57e..ef48f4cd76 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
@@ -40,7 +40,7 @@ public AnalyzedFieldTreeNode(IField analyzedField, IEntity? source)
public override object Icon => FieldTreeNode.GetIcon(analyzedField);
- public override object Text => Language.EntityToString(analyzedField, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
+ public override object Text => CreateHighlightedSignatureText(Language.EntityToString(analyzedField, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames));
protected override void LoadChildren()
{
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
index 2ce76fe51b..3f320f84fa 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
@@ -42,7 +42,7 @@ public AnalyzedMethodTreeNode(IMethod analyzedMethod, IEntity? source, string pr
public override object Icon => MethodTreeNode.GetIcon(analyzedMethod);
- public override object Text => prefix + Language.EntityToString(analyzedMethod, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
+ public override object Text => CreateHighlightedSignatureText(prefix + Language.EntityToString(analyzedMethod, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames));
protected override void LoadChildren()
{
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
index d6cb1df5e6..767e3ecf18 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
@@ -43,7 +43,7 @@ public AnalyzedPropertyTreeNode(IProperty analyzedProperty, IEntity? source, str
public override object Icon => PropertyTreeNode.GetIcon(analyzedProperty);
// TODO: This way of formatting is not suitable for properties which explicitly implement interfaces.
- public override object Text => prefix + Language.EntityToString(analyzedProperty, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
+ public override object Text => CreateHighlightedSignatureText(prefix + Language.EntityToString(analyzedProperty, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames));
protected override void LoadChildren()
{
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
index 67f37d6f98..3079172c6d 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
@@ -39,7 +39,7 @@ public AnalyzedTypeTreeNode(ITypeDefinition analyzedType, IEntity? source)
public override object Icon => TypeTreeNode.GetIcon(analyzedType);
- public override object Text => Language.TypeToString(analyzedType);
+ public override object Text => CreateHighlightedSignatureText(Language.TypeToString(analyzedType));
protected override void LoadChildren()
{