From 2b0016ae5a292c1e212ca8f877c35a4985ecc7e6 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 15 May 2026 00:07:27 +0200 Subject: [PATCH] MethodTreeNode hides extension-block impl methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pair to ea56a80cd. When DecompilerSettings.ExtensionMembers is on and the active language is C#, methods that the decompiler identifies as implementation methods for an extension block are filtered out of the outer static class — they surface as ExtensionTreeNode children of the containing static class instead. Without this gate the user would see each extension member twice: once as a regular method on the static container, once under the extension block. Mirrors WPF MethodTreeNode.Filter lines 95-104 verbatim. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy/TreeNodes/MethodTreeNode.cs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index 14d1b37f4..f7317e355 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -69,15 +69,38 @@ namespace ILSpy.TreeNodes { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; - // WPF additionally hides extension-block implementation methods when the - // ExtensionMembers decompiler setting is on; tracked as `methodtreenode-extension-gate` - // in the parity TODO and reinstated when the DecompilerSettings UI lands. + // Hide implementation methods of C# 14 extension blocks when ExtensionMembers is on + // — those land as ExtensionTreeNode children of the static container instead, so + // surfacing them on the outer class would be duplicate UI. Pair to the + // `extension-methods-tree` work in ea56a80cd. + if (LanguageService.CurrentLanguage is Languages.CSharpLanguage + && MethodDefinition.DeclaringTypeDefinition?.ExtensionInfo is { } extInfo) + { + var decompilerSettings = TryGetDecompilerSettings(); + if (decompilerSettings?.ExtensionMembers == true + && extInfo.InfoOfImplementationMember((IMethod)MethodDefinition.MemberDefinition).HasValue) + { + return FilterResult.Hidden; + } + } if (settings.SearchTermMatches(MethodDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || LanguageService.CurrentLanguage.ShowMember(MethodDefinition))) return FilterResult.Match; else return FilterResult.Hidden; } + static ICSharpCode.Decompiler.DecompilerSettings? TryGetDecompilerSettings() + { + try + { + return AppEnv.AppComposition.Current.GetExport().DecompilerSettings.Clone(); + } + catch + { + return null; + } + } + // Stable identity for SessionSettings.ActiveTreeViewPath; format must round-trip // across launches so the saved path can be restored. public override string ToString()