From 0e9f422a989ef50c1955b5473f2a504bdb99029d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 29 May 2026 01:03:16 +0200 Subject: [PATCH] Route extension-block methods through DecompileExtension on click When the C# 14 extension members tree feature is on, the marker methods inside a static extension container surface as children of the dedicated ExtensionTreeNode rather than as plain methods on the outer class. Clicking one was running DecompileMethod, which renders the lowered static method body, not the source-faithful `extension(T) { ... }` block the user expects. Match the WPF behaviour: when MethodTreeNode.Parent is an ExtensionTreeNode and the active language is C#, dispatch to CSharpLanguage.DecompileExtension(IMethod) so the whole declaration emits as it was written. Other languages and non-extension methods keep the existing DecompileMethod path. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy/TreeNodes/MethodTreeNode.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index 494c668ff..f82576152 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -79,7 +79,17 @@ namespace ILSpy.TreeNodes public override bool ShowExpander => false; public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) - => language.DecompileMethod(MethodDefinition, output, options); + { + // When the user clicks a method that lives under an ExtensionTreeNode (the C# 14 + // extension-block container), emit the whole extension declaration via the + // dedicated DecompileExtension path so the output reads as source-faithful + // `extension(T) { ... }` syntax, not the lowered static method we'd get from + // DecompileMethod. Falls through to the regular method path for everything else. + if (Parent is ExtensionTreeNode && language is CSharpLanguage cs) + cs.DecompileExtension(MethodDefinition, output, options); + else + language.DecompileMethod(MethodDefinition, output, options); + } public override bool IsPublicAPI => MethodDefinition.Accessibility switch { Accessibility.Public or Accessibility.Protected or Accessibility.ProtectedOrInternal => true,