From 18d960e6b9306a541cbf1063b9131f5e026444c7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 11 Aug 2026 08:18:23 +0200 Subject: [PATCH] Say what the code does instead of which app did it first A comment that justifies behaviour by pointing at the WPF front-end means nothing to someone reading the file cold: the reason is either already stated beside it or is not stated anywhere. Each of these now names the constraint itself - why navigation waits for pointer-release, why a signature block wraps, why the tree filter ignores the search term. Comments citing an external product's documented behaviour as the source of a rule are left alone; there the reference is the reason, not a memory of how the code arrived. Assisted-by: Claude:claude-opus-5[1m]:Claude Code --- ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs | 10 ++++---- .../DocumentationRendererTooltipWidthTests.cs | 3 +-- ILSpy.Tests/Editor/ReferenceClickTests.cs | 6 ++--- ILSpy.Tests/Navigation/NavigationTests.cs | 2 +- ILSpy.Tests/Search/SearchTermFilterTests.cs | 23 +++++++++---------- ILSpy/Languages/CSharpLanguage.cs | 14 +++++------ ILSpy/TextView/DecompilerTextView.axaml.cs | 9 ++++---- ILSpy/TextView/DocumentationRenderer.cs | 5 ++-- ILSpy/TreeNodes/FieldTreeNode.cs | 2 +- 9 files changed, 34 insertions(+), 40 deletions(-) diff --git a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs index 01f2273b8..e4f9bc8e5 100644 --- a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs +++ b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs @@ -1604,12 +1604,10 @@ public class AssemblyTreeTests [AvaloniaTest] public async Task Active_Search_Term_Does_Not_Hide_Member_Tree_Nodes() { - // Pre-existing port misstep: commit 45461ddde wired the search-pane's term into - // LanguageSettings.SearchTerm and made SearchTermMatches gate visibility on it. - // WPF intentionally makes SearchTermMatches a no-op (returns true) so the assembly - // tree stays independent of the search pane. After fixing parity, FieldTreeNode.Filter - // must NOT return Hidden purely because the field's name doesn't contain the active - // SearchTerm — only ShowApiLevel + ShowMember remain valid hiding criteria. + // SearchTermMatches is deliberately a no-op (returns true) so the assembly tree stays + // independent of the search pane. FieldTreeNode.Filter must therefore NOT return + // Hidden purely because the field's name doesn't contain the active SearchTerm — + // only ShowApiLevel + ShowMember remain valid hiding criteria. var (_, vm) = await TestHarness.BootAsync(); diff --git a/ILSpy.Tests/Editor/DocumentationRendererTooltipWidthTests.cs b/ILSpy.Tests/Editor/DocumentationRendererTooltipWidthTests.cs index 0a7ae83c8..d2c230ca5 100644 --- a/ILSpy.Tests/Editor/DocumentationRendererTooltipWidthTests.cs +++ b/ILSpy.Tests/Editor/DocumentationRendererTooltipWidthTests.cs @@ -40,8 +40,7 @@ namespace ICSharpCode.ILSpy.Tests.TextView; /// Pins the rendering shape of method-signature tooltips so a long signature isn't clipped /// horizontally: the signature must wrap. Created with /// , text past the popup's MaxWidth is simply cut off, -/// because the outer ScrollViewer disables horizontal scrolling. WPF parity is -/// wrap-friendly, so we mirror that. +/// because the outer ScrollViewer disables horizontal scrolling. /// [TestFixture] public class DocumentationRendererTooltipWidthTests diff --git a/ILSpy.Tests/Editor/ReferenceClickTests.cs b/ILSpy.Tests/Editor/ReferenceClickTests.cs index 22e19de51..6321cb051 100644 --- a/ILSpy.Tests/Editor/ReferenceClickTests.cs +++ b/ILSpy.Tests/Editor/ReferenceClickTests.cs @@ -40,9 +40,9 @@ using NUnit.Framework; namespace ICSharpCode.ILSpy.Tests.TextView; /// -/// Pins the reference-link click gesture in the decompiled view (WPF parity): navigation -/// happens on mouse-UP and only when the pointer did not drag, so text that belongs to a -/// link can still be selected by press-and-drag. +/// Pins the reference-link click gesture in the decompiled view: navigation happens on +/// mouse-UP and only when the pointer did not drag, so text that belongs to a link can +/// still be selected by press-and-drag. /// [TestFixture] public class ReferenceClickTests diff --git a/ILSpy.Tests/Navigation/NavigationTests.cs b/ILSpy.Tests/Navigation/NavigationTests.cs index 83c19846e..993d172a8 100644 --- a/ILSpy.Tests/Navigation/NavigationTests.cs +++ b/ILSpy.Tests/Navigation/NavigationTests.cs @@ -197,6 +197,6 @@ public class NavigationTests ((string)baseTypesEntry.Header!).Should().Contain("Exception", "the dropdown header must disambiguate generic grouping nodes via NavigationText"); ((string)baseTypesEntry.Header!).Should().NotBe((string)baseTypes.Text, - "falling back to bare Text would reproduce the WPF parity gap"); + "falling back to bare Text would leave the grouping nodes indistinguishable"); } } diff --git a/ILSpy.Tests/Search/SearchTermFilterTests.cs b/ILSpy.Tests/Search/SearchTermFilterTests.cs index 7c0850d48..195f03b36 100644 --- a/ILSpy.Tests/Search/SearchTermFilterTests.cs +++ b/ILSpy.Tests/Search/SearchTermFilterTests.cs @@ -36,12 +36,12 @@ public class SearchTermFilterTests [AvaloniaTest] public Task SearchTermMatches_Is_A_No_Op_That_Always_Returns_True() { - // Pins the WPF-parity contract: the search pane drives its own results via the - // ILSpyX search strategies; LanguageSettings.SearchTermMatches deliberately ignores - // SearchTerm so the assembly-tree filter cascade stays independent of the search - // pane. Without this, typing a term into the search box would hide tree rows whose - // names don't match it — including member rows under a type whose own name DOES - // match — because the cascade only resets the match bit one level deep. + // The search pane drives its own results via the ILSpyX search strategies; + // LanguageSettings.SearchTermMatches deliberately ignores SearchTerm so the + // assembly-tree filter cascade stays independent of the search pane. Were it to + // honour the term, typing into the search box would hide tree rows whose names don't + // match it — including member rows under a type whose own name DOES match — because + // the cascade only resets the match bit one level deep. var settings = AppComposition.Current.GetExport().SessionSettings.LanguageSettings; try @@ -54,7 +54,7 @@ public class SearchTermFilterTests settings.SearchTerm = "enum"; settings.SearchTermMatches("IEnumerable").Should().BeTrue(); settings.SearchTermMatches("Object").Should().BeTrue( - "WPF parity: SearchTermMatches must NOT honour the SearchTerm — it's a no-op shim"); + "SearchTermMatches must NOT honour the SearchTerm — it's a no-op shim"); settings.SearchTerm = "ZZZ_NoMatchAnywhere"; settings.SearchTermMatches("Anything").Should().BeTrue(); @@ -69,11 +69,10 @@ public class SearchTermFilterTests [AvaloniaTest] public Task Typing_In_The_Search_Pane_Does_Not_Bleed_Into_LanguageSettings_SearchTerm() { - // The search pane is decoupled from the assembly-tree filter cascade. Earlier port - // commits pushed SearchPaneModel.SearchTerm into LanguageSettings.SearchTerm to drive - // a tree-filter cascade — that path hid member rows users expected to see (e.g. enum - // literals under their matched-by-name enum type). Reverted to WPF parity: typing in - // the search pane drives the orchestrator only. + // The search pane is decoupled from the assembly-tree filter cascade: typing in it + // drives the orchestrator only. Feeding SearchPaneModel.SearchTerm into + // LanguageSettings.SearchTerm instead would drive the cascade and hide member rows + // users expect to see — e.g. enum literals under their matched-by-name enum type. var search = AppComposition.Current.GetExport(); var settings = AppComposition.Current.GetExport().SessionSettings.LanguageSettings; diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index e5e70f0e6..2be32de77 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -112,18 +112,18 @@ namespace ICSharpCode.ILSpy.Languages public override void WriteCommentLine(ITextOutput output, string comment) => output.WriteLine("// " + comment); - // Parity with WPF's CSharpLanguage: map an IL member back to its C# source via the - // decompiler, so compiler-generated members (lambdas, async/iterator state machines) - // resolve to their declaring method/part rather than only the declaring type (the - // base Language fallback). Used by analyzers / navigation. + // Maps an IL member back to its C# source via the decompiler, so compiler-generated + // members (lambdas, async/iterator state machines) resolve to their declaring + // method/part rather than only the declaring type (the base Language fallback). + // Used by analyzers / navigation. public override CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { return CSharpDecompiler.GetCodeMappingInfo(module, member); } - // Parity with WPF's CSharpLanguage: produce C#-styled entity names (generics as - // , nested types joined with '.'). Without this the base Language emits IL-style - // names (`1 arity suffixes, escaped identifiers). + // Produces C#-styled entity names (generics as , nested types joined with '.'). + // Without this the base Language emits IL-style names (`1 arity suffixes, escaped + // identifiers). public override string GetEntityName(MetadataFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; diff --git a/ILSpy/TextView/DecompilerTextView.axaml.cs b/ILSpy/TextView/DecompilerTextView.axaml.cs index 75eb08293..fa776d7ac 100644 --- a/ILSpy/TextView/DecompilerTextView.axaml.cs +++ b/ILSpy/TextView/DecompilerTextView.axaml.cs @@ -193,11 +193,10 @@ namespace ICSharpCode.ILSpy.TextView uiElementGenerator = new UIElementGenerator(); Editor.TextArea.TextView.ElementGenerators.Add(uiElementGenerator); - // Reference navigation fires on pointer-RELEASE without drag (WPF parity: the WPF - // view used TextArea.PreviewMouseDown/Up the same way), so a press-and-drag over a - // link starts a text selection instead of navigating away. The press handler only - // records the start position, so tunnel routing (before AvaloniaEdit consumes the - // press) is fine. + // Reference navigation fires on pointer-RELEASE without drag, so a press-and-drag + // over a link starts a text selection instead of navigating away. The press handler + // only records the start position, so tunnel routing (before AvaloniaEdit consumes + // the press) is fine. Editor.TextArea.AddHandler(InputElement.PointerPressedEvent, OnTextAreaPointerPressedForReferenceClick, RoutingStrategies.Tunnel, diff --git a/ILSpy/TextView/DocumentationRenderer.cs b/ILSpy/TextView/DocumentationRenderer.cs index 462ee963a..f03aec8e4 100644 --- a/ILSpy/TextView/DocumentationRenderer.cs +++ b/ILSpy/TextView/DocumentationRenderer.cs @@ -136,9 +136,8 @@ namespace ICSharpCode.ILSpy.TextView // Wrap rather than NoWrap so a signature wider than the popup's MaxWidth folds // to multiple lines instead of being clipped at the right edge — the outer - // ScrollViewer disables horizontal scrolling, so NoWrap meant "the right half - // of long generic method signatures is invisible". WPF parity: the equivalent - // FlowDocument Paragraph wraps by default (Paragraph doesn't even support NoWrap). + // ScrollViewer disables horizontal scrolling, so NoWrap would leave the right + // half of long generic method signatures invisible. var block = new SelectableTextBlock { FontFamily = codeFont, FontSize = fontSize, diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index 523ad263e..10918b35a 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public override object Icon => GetIcon(FieldDefinition); - // Mirrors WPF's discriminator: enum value, const literal, readonly, plain field. + // Discriminated in this order: enum value, const literal, readonly, plain field. public static Avalonia.Media.IImage GetIcon(IField field) { // EnumValue: declaring type is an enum and the return type is the enum itself --