Skip to content

Commit a71697f

Browse files
Improves Razor formatting span handling
Refactors formatting visitor to use a ref struct SpanComputer for generating text spans, improving efficiency. Consolidates span creation logic and simplifies block management with a BlockSaver struct for cleaner code.
1 parent 3fba16d commit a71697f

File tree

3 files changed

+191
-95
lines changed

3 files changed

+191
-95
lines changed

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/ClassifiedSpanVisitor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,14 @@ public override void VisitMarkupAttributeBlock(MarkupAttributeBlockSyntax node)
211211
using (MarkupBlock(node))
212212
{
213213
// For attributes, we add a single span from the start of the name prefix to the end of the value prefix.
214-
var spanComputer = new SourceSpanComputer(_source);
214+
var spanComputer = new SpanComputer();
215215
spanComputer.Add(node.NamePrefix);
216216
spanComputer.Add(node.Name);
217217
spanComputer.Add(node.NameSuffix);
218218
spanComputer.Add(node.EqualsToken);
219219
spanComputer.Add(node.ValuePrefix);
220220

221-
var sourceSpan = spanComputer.ToSourceSpan();
221+
var sourceSpan = spanComputer.ToSourceSpan(_source);
222222

223223
AddSpan(sourceSpan, SpanKindInternal.Markup, AcceptedCharactersInternal.Any);
224224

@@ -251,11 +251,11 @@ public override void VisitMarkupMinimizedAttributeBlock(MarkupMinimizedAttribute
251251
using (MarkupBlock(node))
252252
{
253253
// For minimized attributes, we add a single span for the attribute name along with the name prefix.
254-
var spanComputer = new SourceSpanComputer(_source);
254+
var spanComputer = new SpanComputer();
255255
spanComputer.Add(node.NamePrefix);
256256
spanComputer.Add(node.Name);
257257

258-
var sourceSpan = spanComputer.ToSourceSpan();
258+
var sourceSpan = spanComputer.ToSourceSpan(_source);
259259

260260
AddSpan(sourceSpan, SpanKindInternal.Markup, AcceptedCharactersInternal.Any);
261261
}

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/SourceSpanComputer.cs renamed to src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/SpanComputer.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33

44
using System.Diagnostics;
55
using Microsoft.AspNetCore.Razor.Language.Syntax;
6+
using Microsoft.CodeAnalysis.Text;
67

78
namespace Microsoft.AspNetCore.Razor.Language;
89

910
/// <summary>
10-
/// Helper that can be used to efficiently build up a <see cref="SourceSpan"/> from a set of syntax tokens.
11+
/// Helper that can be used to efficiently build up a <see cref="SourceSpan"/> or
12+
/// <see cref="CodeAnalysis.Text.TextSpan"/> from a set of syntax tokens.
1113
/// </summary>
12-
internal ref struct SourceSpanComputer(RazorSourceDocument source)
14+
internal ref struct SpanComputer()
1315
{
14-
private readonly RazorSourceDocument _source = source;
15-
1616
private SyntaxToken _firstToken;
1717
private SyntaxToken _lastToken;
1818

@@ -91,7 +91,7 @@ public void Add(UnclassifiedTextLiteralSyntax? literal)
9191
Add(literal?.LiteralTokens);
9292
}
9393

94-
public readonly SourceSpan ToSourceSpan()
94+
public readonly SourceSpan ToSourceSpan(RazorSourceDocument source)
9595
{
9696
if (_firstToken.Kind == SyntaxKind.None)
9797
{
@@ -107,11 +107,28 @@ public readonly SourceSpan ToSourceSpan()
107107

108108
var length = end - start;
109109

110-
var text = _source.Text;
110+
var text = source.Text;
111111
var startLinePosition = text.Lines.GetLinePosition(start);
112112
var endLinePosition = text.Lines.GetLinePosition(end);
113113
var lineCount = endLinePosition.Line - startLinePosition.Line;
114114

115-
return new SourceSpan(_source.FilePath, absoluteIndex: start, startLinePosition.Line, startLinePosition.Character, length, lineCount, endLinePosition.Character);
115+
return new SourceSpan(source.FilePath, absoluteIndex: start, startLinePosition.Line, startLinePosition.Character, length, lineCount, endLinePosition.Character);
116+
}
117+
118+
public readonly TextSpan ToTextSpan()
119+
{
120+
if (_firstToken.Kind == SyntaxKind.None)
121+
{
122+
return default;
123+
}
124+
125+
Debug.Assert(_lastToken.Kind != SyntaxKind.None, "Last token should not be None when first token is set.");
126+
127+
var start = _firstToken.Span.Start;
128+
var end = _lastToken.Span.End;
129+
130+
Debug.Assert(start <= end, "Start position should not be greater than end position.");
131+
132+
return TextSpan.FromBounds(start, end);
116133
}
117134
}

0 commit comments

Comments
 (0)