From 0ff17e5b8a6473e66f21b92d73d081c510dd146f Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 7 Aug 2026 14:48:38 +0200 Subject: [PATCH] Write IL-with-C# comment slices as spans The "IL with C#" view cut up to four substrings (prefix, trimmed prefix, highlighted range, suffix) out of every source line emitted alongside an IL instruction. ISmartTextOutput now accepts a ReadOnlySpan - as a default interface method falling back to Write(text.ToString()) so existing implementers keep working - and AvaloniaEditTextOutput appends the span straight into its StringBuilder. The overload lives on ISmartTextOutput rather than ITextOutput because the latter is netstandard2.0 (no default interface methods there), where a new member would break every external implementer of the decompiler library; the highlighted-comment path is typed against ISmartTextOutput already. Assisted-by: Claude:claude-fable-5:Claude Code --- ILSpy/Languages/CSharpILMixedLanguage.cs | 8 ++++---- ILSpy/TextView/AvaloniaEditTextOutput.cs | 7 +++++++ ILSpy/TextView/ISmartTextOutput.cs | 7 +++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index 1aec1b9a3..6386d63dc 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -181,13 +181,13 @@ namespace ICSharpCode.ILSpy.Languages output.Write("// "); output.BeginSpan(gray); if (isSingleLine) - output.Write(text.Substring(0, startColumn).TrimStart()); + output.Write(text.AsSpan(0, startColumn).TrimStart()); else - output.Write(text.Substring(0, startColumn)); + output.Write(text.AsSpan(0, startColumn)); output.EndSpan(); - output.Write(text.Substring(startColumn, endColumn - startColumn)); + output.Write(text.AsSpan(startColumn, endColumn - startColumn)); output.BeginSpan(gray); - output.Write(text.Substring(endColumn)); + output.Write(text.AsSpan(endColumn)); output.EndSpan(); output.WriteLine(); } diff --git a/ILSpy/TextView/AvaloniaEditTextOutput.cs b/ILSpy/TextView/AvaloniaEditTextOutput.cs index 71e076651..58132a54f 100644 --- a/ILSpy/TextView/AvaloniaEditTextOutput.cs +++ b/ILSpy/TextView/AvaloniaEditTextOutput.cs @@ -186,6 +186,13 @@ namespace ICSharpCode.ILSpy.TextView CheckLength(); } + public void Write(ReadOnlySpan text) + { + WriteIndentIfNeeded(); + builder.Append(text); + CheckLength(); + } + public void WriteLine() { if (IgnoreNewLineAndIndent) diff --git a/ILSpy/TextView/ISmartTextOutput.cs b/ILSpy/TextView/ISmartTextOutput.cs index f69acbb8c..a84ebded9 100644 --- a/ILSpy/TextView/ISmartTextOutput.cs +++ b/ILSpy/TextView/ISmartTextOutput.cs @@ -48,6 +48,13 @@ namespace ICSharpCode.ILSpy.TextView void BeginSpan(HighlightingColor highlightingColor); void EndSpan(); + /// + /// Writes a slice of text without requiring the caller to allocate an intermediate + /// string. Implementations that buffer internally should override the default, + /// which falls back to . + /// + void Write(ReadOnlySpan text) => Write(text.ToString()); + /// /// Title displayed in the document tab's header. ///