Skip to content

Commit 4d36789

Browse files
authored
Merge pull request #22686 from dotnet/dev/toddgrun/expand_cached_tokens
Expand the SyntaxTokenCache to contain more than just whitespace tokens.
2 parents 40e0649 + 837c639 commit 4d36789

File tree

3 files changed

+76
-48
lines changed

3 files changed

+76
-48
lines changed

src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/InternalSyntax/SyntaxFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ internal static partial class SyntaxFactory
99
{
1010
internal static SyntaxToken Token(SyntaxKind kind, string content, params RazorDiagnostic[] diagnostics)
1111
{
12-
if (kind == SyntaxKind.Whitespace && diagnostics.Length == 0)
12+
if (SyntaxTokenCache.CanBeCached(kind, diagnostics))
1313
{
14-
return WhitespaceTokenCache.GetToken(content);
14+
return SyntaxTokenCache.GetCachedToken(kind, content);
1515
}
1616

1717
return new SyntaxToken(kind, content, diagnostics);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.Extensions.Internal;
6+
7+
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
8+
{
9+
// Simplified version of Roslyn's SyntaxNodeCache
10+
internal static class SyntaxTokenCache
11+
{
12+
private const int CacheSizeBits = 16;
13+
private const int CacheSize = 1 << CacheSizeBits;
14+
private const int CacheMask = CacheSize - 1;
15+
private static readonly Entry[] s_cache = new Entry[CacheSize];
16+
17+
private struct Entry
18+
{
19+
public int Hash { get; }
20+
public SyntaxToken Token { get; }
21+
22+
internal Entry(int hash, SyntaxToken token)
23+
{
24+
Hash = hash;
25+
Token = token;
26+
}
27+
}
28+
29+
public static bool CanBeCached(SyntaxKind kind, params RazorDiagnostic[] diagnostics)
30+
{
31+
if (diagnostics.Length == 0)
32+
{
33+
switch (kind)
34+
{
35+
case SyntaxKind.CharacterLiteral:
36+
case SyntaxKind.Dot:
37+
case SyntaxKind.Identifier:
38+
case SyntaxKind.IntegerLiteral:
39+
case SyntaxKind.Keyword:
40+
case SyntaxKind.NewLine:
41+
case SyntaxKind.RazorCommentStar:
42+
case SyntaxKind.RazorCommentTransition:
43+
case SyntaxKind.StringLiteral:
44+
case SyntaxKind.Transition:
45+
case SyntaxKind.Whitespace:
46+
return true;
47+
}
48+
}
49+
50+
return false;
51+
}
52+
53+
public static SyntaxToken GetCachedToken(SyntaxKind kind, string content)
54+
{
55+
var hash = (kind, content).GetHashCode();
56+
57+
// Allow the upper 16 bits to contribute to the index
58+
var indexableHash = hash ^ (hash >> 16);
59+
60+
var idx = indexableHash & CacheMask;
61+
var e = s_cache[idx];
62+
63+
if (e.Hash == hash && e.Token.Kind == kind && e.Token.Content == content)
64+
{
65+
return e.Token;
66+
}
67+
68+
var token = new SyntaxToken(kind, content, Array.Empty<RazorDiagnostic>());
69+
s_cache[idx] = new Entry(hash, token);
70+
71+
return token;
72+
}
73+
}
74+
}

src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/InternalSyntax/WhitespaceTokenCache.cs

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)