Skip to content

Commit d51064b

Browse files
Uses pooled array builder for formatting spans
Improves performance by utilizing a pooled array builder to avoid allocations when collecting formatting spans. This change reduces memory pressure and improves the efficiency of the formatting process.
1 parent d7a4515 commit d51064b

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingContext.cs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Threading.Tasks;
1212
using Microsoft.AspNetCore.Razor.Language;
1313
using Microsoft.AspNetCore.Razor.Language.Syntax;
14+
using Microsoft.AspNetCore.Razor.PooledObjects;
1415
using Microsoft.CodeAnalysis;
1516
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
1617
using Microsoft.CodeAnalysis.Text;
@@ -19,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Razor.Formatting;
1920

2021
internal sealed class FormattingContext
2122
{
22-
private IReadOnlyList<FormattingSpan>? _formattingSpans;
23+
private ImmutableArray<FormattingSpan>? _formattingSpans;
2324
private IReadOnlyDictionary<int, IndentationContext>? _indentations;
2425
private readonly bool _useNewFormattingEngine;
2526

@@ -143,25 +144,27 @@ public IReadOnlyDictionary<int, IndentationContext> GetIndentations()
143144
return _indentations;
144145
}
145146

146-
private IReadOnlyList<FormattingSpan> GetFormattingSpans()
147+
private ImmutableArray<FormattingSpan> GetFormattingSpans()
147148
{
148-
if (_formattingSpans is null)
149+
return _formattingSpans ??= ComputeFormattingSpans(CodeDocument);
150+
151+
static ImmutableArray<FormattingSpan> ComputeFormattingSpans(RazorCodeDocument codeDocument)
149152
{
150-
var syntaxTree = CodeDocument.GetRequiredSyntaxTree();
151-
var inGlobalNamespace = CodeDocument.TryGetNamespace(fallbackToRootNamespace: true, out var @namespace) &&
153+
var syntaxTree = codeDocument.GetRequiredSyntaxTree();
154+
var inGlobalNamespace = codeDocument.TryGetNamespace(fallbackToRootNamespace: true, out var @namespace) &&
152155
string.IsNullOrEmpty(@namespace);
153-
_formattingSpans = GetFormattingSpans(syntaxTree, inGlobalNamespace: inGlobalNamespace);
154-
}
155156

156-
return _formattingSpans;
157+
return GetFormattingSpans(syntaxTree, inGlobalNamespace: inGlobalNamespace);
158+
}
157159
}
158160

159-
private static IReadOnlyList<FormattingSpan> GetFormattingSpans(RazorSyntaxTree syntaxTree, bool inGlobalNamespace)
161+
private static ImmutableArray<FormattingSpan> GetFormattingSpans(RazorSyntaxTree syntaxTree, bool inGlobalNamespace)
160162
{
161-
var visitor = new FormattingVisitor(inGlobalNamespace: inGlobalNamespace);
162-
visitor.Visit(syntaxTree.Root);
163+
using var _ = ArrayBuilderPool<FormattingSpan>.GetPooledObject(out var formattingSpans);
164+
165+
FormattingVisitor.VisitRoot(syntaxTree, formattingSpans, inGlobalNamespace);
163166

164-
return visitor.FormattingSpans;
167+
return formattingSpans.ToImmutableAndClear();
165168
}
166169

167170
/// <summary>

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingVisitor.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Collections.Immutable;
67
using System.Diagnostics;
78
using System.Linq;
89
using Microsoft.AspNetCore.Razor.Language;
@@ -13,27 +14,32 @@ namespace Microsoft.CodeAnalysis.Razor.Formatting;
1314

1415
using Microsoft.AspNetCore.Razor.Language.Syntax;
1516

16-
internal class FormattingVisitor : SyntaxWalker
17+
internal sealed class FormattingVisitor : SyntaxWalker
1718
{
1819
private const string HtmlTag = "html";
1920

21+
private readonly ImmutableArray<FormattingSpan>.Builder _spans;
2022
private readonly bool _inGlobalNamespace;
21-
private readonly List<FormattingSpan> _spans;
2223
private FormattingBlockKind _currentBlockKind;
2324
private SyntaxNode? _currentBlock;
2425
private int _currentHtmlIndentationLevel = 0;
2526
private int _currentRazorIndentationLevel = 0;
2627
private int _currentComponentIndentationLevel = 0;
2728
private bool _isInClassBody = false;
2829

29-
public FormattingVisitor(bool inGlobalNamespace)
30+
private FormattingVisitor(ImmutableArray<FormattingSpan>.Builder spans, bool inGlobalNamespace)
3031
{
3132
_inGlobalNamespace = inGlobalNamespace;
32-
_spans = new List<FormattingSpan>();
33+
_spans = spans;
3334
_currentBlockKind = FormattingBlockKind.Markup;
3435
}
3536

36-
public IReadOnlyList<FormattingSpan> FormattingSpans => _spans;
37+
public static void VisitRoot(
38+
RazorSyntaxTree syntaxTree, ImmutableArray<FormattingSpan>.Builder spans, bool inGlobalNamespace)
39+
{
40+
var visitor = new FormattingVisitor(spans, inGlobalNamespace);
41+
visitor.Visit(syntaxTree.Root);
42+
}
3743

3844
public override void VisitRazorCommentBlock(RazorCommentBlockSyntax node)
3945
{

0 commit comments

Comments
 (0)