Skip to content

Commit a6a95d9

Browse files
Improves classified span generation performance
Changes span creation to only compute the current block's span when it is first needed. This avoids redundant computations, improving performance.
1 parent 7beb9bd commit a6a95d9

File tree

1 file changed

+36
-28
lines changed

1 file changed

+36
-28
lines changed

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

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Immutable;
@@ -17,8 +17,9 @@ internal class ClassifiedSpanVisitor : SyntaxWalker
1717
private readonly RazorSourceDocument _source;
1818
private readonly ImmutableArray<ClassifiedSpanInternal>.Builder _spans;
1919

20-
private BlockKindInternal _currentBlockKind;
2120
private SyntaxNode? _currentBlock;
21+
private SourceSpan? _currentBlockSpan;
22+
private BlockKindInternal _currentBlockKind;
2223

2324
private ClassifiedSpanVisitor(RazorSourceDocument source, ImmutableArray<ClassifiedSpanInternal>.Builder spans)
2425
{
@@ -42,8 +43,8 @@ public override void VisitRazorCommentBlock(RazorCommentBlockSyntax node)
4243
{
4344
using (CommentBlock(node))
4445
{
45-
WriteSpan(node.StartCommentTransition, SpanKindInternal.Transition, AcceptedCharactersInternal.None);
46-
WriteSpan(node.StartCommentStar, SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
46+
AddSpan(node.StartCommentTransition, SpanKindInternal.Transition, AcceptedCharactersInternal.None);
47+
AddSpan(node.StartCommentStar, SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
4748

4849
var comment = node.Comment;
4950

@@ -53,10 +54,10 @@ public override void VisitRazorCommentBlock(RazorCommentBlockSyntax node)
5354
comment = SyntaxFactory.Token(SyntaxKind.Marker, parent: node, position: node.StartCommentStar.EndPosition);
5455
}
5556

56-
WriteSpan(comment, SpanKindInternal.Comment, AcceptedCharactersInternal.Any);
57+
AddSpan(comment, SpanKindInternal.Comment, AcceptedCharactersInternal.Any);
5758

58-
WriteSpan(node.EndCommentStar, SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
59-
WriteSpan(node.EndCommentTransition, SpanKindInternal.Transition, AcceptedCharactersInternal.None);
59+
AddSpan(node.EndCommentStar, SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
60+
AddSpan(node.EndCommentTransition, SpanKindInternal.Transition, AcceptedCharactersInternal.None);
6061
}
6162
}
6263

@@ -257,49 +258,49 @@ public override void VisitMarkupDynamicAttributeValue(MarkupDynamicAttributeValu
257258

258259
public override void VisitRazorMetaCode(RazorMetaCodeSyntax node)
259260
{
260-
WriteSpan(node, SpanKindInternal.MetaCode);
261+
AddSpan(node, SpanKindInternal.MetaCode);
261262
base.VisitRazorMetaCode(node);
262263
}
263264

264265
public override void VisitCSharpTransition(CSharpTransitionSyntax node)
265266
{
266-
WriteSpan(node, SpanKindInternal.Transition);
267+
AddSpan(node, SpanKindInternal.Transition);
267268
base.VisitCSharpTransition(node);
268269
}
269270

270271
public override void VisitMarkupTransition(MarkupTransitionSyntax node)
271272
{
272-
WriteSpan(node, SpanKindInternal.Transition);
273+
AddSpan(node, SpanKindInternal.Transition);
273274
base.VisitMarkupTransition(node);
274275
}
275276

276277
public override void VisitCSharpStatementLiteral(CSharpStatementLiteralSyntax node)
277278
{
278-
WriteSpan(node, SpanKindInternal.Code);
279+
AddSpan(node, SpanKindInternal.Code);
279280
base.VisitCSharpStatementLiteral(node);
280281
}
281282

282283
public override void VisitCSharpExpressionLiteral(CSharpExpressionLiteralSyntax node)
283284
{
284-
WriteSpan(node, SpanKindInternal.Code);
285+
AddSpan(node, SpanKindInternal.Code);
285286
base.VisitCSharpExpressionLiteral(node);
286287
}
287288

288289
public override void VisitCSharpEphemeralTextLiteral(CSharpEphemeralTextLiteralSyntax node)
289290
{
290-
WriteSpan(node, SpanKindInternal.Code);
291+
AddSpan(node, SpanKindInternal.Code);
291292
base.VisitCSharpEphemeralTextLiteral(node);
292293
}
293294

294295
public override void VisitUnclassifiedTextLiteral(UnclassifiedTextLiteralSyntax node)
295296
{
296-
WriteSpan(node, SpanKindInternal.None);
297+
AddSpan(node, SpanKindInternal.None);
297298
base.VisitUnclassifiedTextLiteral(node);
298299
}
299300

300301
public override void VisitMarkupLiteralAttributeValue(MarkupLiteralAttributeValueSyntax node)
301302
{
302-
WriteSpan(node, SpanKindInternal.Markup);
303+
AddSpan(node, SpanKindInternal.Markup);
303304
base.VisitMarkupLiteralAttributeValue(node);
304305
}
305306

@@ -311,13 +312,13 @@ public override void VisitMarkupTextLiteral(MarkupTextLiteralSyntax node)
311312
return;
312313
}
313314

314-
WriteSpan(node, SpanKindInternal.Markup);
315+
AddSpan(node, SpanKindInternal.Markup);
315316
base.VisitMarkupTextLiteral(node);
316317
}
317318

318319
public override void VisitMarkupEphemeralTextLiteral(MarkupEphemeralTextLiteralSyntax node)
319320
{
320-
WriteSpan(node, SpanKindInternal.Markup);
321+
AddSpan(node, SpanKindInternal.Markup);
321322
base.VisitMarkupEphemeralTextLiteral(node);
322323
}
323324

@@ -352,22 +353,31 @@ private BlockSaver Block(SyntaxNode node, BlockKindInternal kind)
352353
_currentBlock = node;
353354
_currentBlockKind = kind;
354355

356+
// This is a new block, so we reset the current block span.
357+
// It will be computed when the first span is written.
358+
_currentBlockSpan = null;
359+
355360
return saver;
356361
}
357362

358363
private readonly ref struct BlockSaver(ClassifiedSpanVisitor visitor)
359364
{
360365
private readonly SyntaxNode? _previousBlock = visitor._currentBlock;
366+
private readonly SourceSpan? _previousBlockSpan = visitor._currentBlockSpan;
361367
private readonly BlockKindInternal _previousKind = visitor._currentBlockKind;
362368

363369
public void Dispose()
364370
{
365371
visitor._currentBlock = _previousBlock;
372+
visitor._currentBlockSpan = _previousBlockSpan;
366373
visitor._currentBlockKind = _previousKind;
367374
}
368375
}
369376

370-
private void WriteSpan(SyntaxNode node, SpanKindInternal kind)
377+
private SourceSpan CurrentBlockSpan
378+
=> _currentBlockSpan ??= _currentBlock.AssumeNotNull().GetSourceSpan(_source);
379+
380+
private void AddSpan(SyntaxNode node, SpanKindInternal kind)
371381
{
372382
if (node.IsMissing)
373383
{
@@ -376,19 +386,16 @@ private void WriteSpan(SyntaxNode node, SpanKindInternal kind)
376386

377387
Debug.Assert(_currentBlock != null, "Current block should not be null when writing a span for a node.");
378388

379-
var spanSource = node.GetSourceSpan(_source);
380-
var blockSource = _currentBlock.GetSourceSpan(_source);
389+
var nodeSpan = node.GetSourceSpan(_source);
381390

382391
var acceptedCharacters = node.GetEditHandler() is { } context
383392
? context.AcceptedCharacters
384393
: AcceptedCharactersInternal.Any;
385394

386-
var span = new ClassifiedSpanInternal(spanSource, blockSource, kind, _currentBlockKind, acceptedCharacters);
387-
388-
_spans.Add(span);
395+
AddSpan(nodeSpan, kind, acceptedCharacters);
389396
}
390397

391-
private void WriteSpan(SyntaxToken token, SpanKindInternal kind, AcceptedCharactersInternal acceptedCharacters)
398+
private void AddSpan(SyntaxToken token, SpanKindInternal kind, AcceptedCharactersInternal acceptedCharacters)
392399
{
393400
if (token.IsMissing)
394401
{
@@ -397,13 +404,14 @@ private void WriteSpan(SyntaxToken token, SpanKindInternal kind, AcceptedCharact
397404

398405
Debug.Assert(_currentBlock != null, "Current block should not be null when writing a span for a token.");
399406

400-
var spanSource = token.GetSourceSpan(_source);
401-
var blockSource = _currentBlock.GetSourceSpan(_source);
402-
var span = new ClassifiedSpanInternal(spanSource, blockSource, kind, _currentBlockKind, acceptedCharacters);
407+
var tokenSpan = token.GetSourceSpan(_source);
403408

404-
_spans.Add(span);
409+
AddSpan(tokenSpan, kind, acceptedCharacters);
405410
}
406411

412+
private void AddSpan(SourceSpan span, SpanKindInternal kind, AcceptedCharactersInternal acceptedCharacters)
413+
=> _spans.Add(new(span, CurrentBlockSpan, kind, _currentBlockKind, acceptedCharacters));
414+
407415
private sealed class Policy : IPooledObjectPolicy<ImmutableArray<ClassifiedSpanInternal>.Builder>
408416
{
409417
public static readonly Policy Instance = new();

0 commit comments

Comments
 (0)