Browse Source

Wrap the highlighting span guard in a using scope

WriteKeyword/WritePrimitiveType/WriteIdentifier/WritePrimitiveValue each
ended with the same begin-span / base-write / end-span guard. Replace it
with `using (Colored(color)) base.WriteX(...)`, backed by an allocation-free
ref-struct scope so the per-token hot path takes no closure.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3755/head
Siegfried Pammer 4 weeks ago
parent
commit
979d7a9393
  1. 60
      ILSpy/Languages/CSharpHighlightingTokenWriter.cs

60
ILSpy/Languages/CSharpHighlightingTokenWriter.cs

@ -291,15 +291,8 @@ namespace ILSpy.Languages
} }
if (nodeStack.PeekOrDefault() is AttributeSection) if (nodeStack.PeekOrDefault() is AttributeSection)
color = attributeKeywordsColor; color = attributeKeywordsColor;
if (color != null) using (Colored(color))
{ base.WriteKeyword(role, keyword);
BeginSpan(color);
}
base.WriteKeyword(role, keyword);
if (color != null)
{
EndSpan();
}
} }
public override void WritePrimitiveType(string type) public override void WritePrimitiveType(string type)
@ -340,15 +333,8 @@ namespace ILSpy.Languages
color = referenceTypeKeywordsColor; color = referenceTypeKeywordsColor;
break; break;
} }
if (color != null) using (Colored(color))
{ base.WritePrimitiveType(type);
BeginSpan(color);
}
base.WritePrimitiveType(type);
if (color != null)
{
EndSpan();
}
} }
public override void WriteIdentifier(Identifier identifier) public override void WriteIdentifier(Identifier identifier)
@ -424,15 +410,8 @@ namespace ILSpy.Languages
color = eventAccessColor; color = eventAccessColor;
break; break;
} }
if (color != null) using (Colored(color))
{ base.WriteIdentifier(identifier);
BeginSpan(color);
}
base.WriteIdentifier(identifier);
if (color != null)
{
EndSpan();
}
} }
void ApplyTypeColor(IType? type, ref HighlightingColor? color) void ApplyTypeColor(IType? type, ref HighlightingColor? color)
@ -468,15 +447,8 @@ namespace ILSpy.Languages
{ {
color = trueKeywordColor; color = trueKeywordColor;
} }
if (color != null) using (Colored(color))
{ base.WritePrimitiveValue(value, format);
BeginSpan(color);
}
base.WritePrimitiveValue(value, format);
if (color != null)
{
EndSpan();
}
} }
ISymbol? GetCurrentDefinition() ISymbol? GetCurrentDefinition()
@ -539,6 +511,22 @@ namespace ILSpy.Languages
readonly ILocatable? locatable; readonly ILocatable? locatable;
readonly ISmartTextOutput? textOutput; readonly ISmartTextOutput? textOutput;
// Wraps a base WriteX call so its output lands inside a highlighting span for the given colour
// (or no span when null) -- replacing the begin/end guard each WriteX override used to repeat.
// A ref struct + the using pattern keeps this allocation-free on the per-token hot path.
ColorScope Colored(HighlightingColor? color)
{
if (color == null)
return default;
BeginSpan(color);
return new ColorScope(this);
}
ref struct ColorScope(CSharpHighlightingTokenWriter? writer)
{
public void Dispose() => writer?.EndSpan();
}
private void BeginSpan(HighlightingColor highlightingColor) private void BeginSpan(HighlightingColor highlightingColor)
{ {
if (textOutput != null) if (textOutput != null)

Loading…
Cancel
Save