Skip to content

Commit b2cbdc2

Browse files
committed
Init semantic token refresh, and queue on request
1 parent 73622b7 commit b2cbdc2

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.ComponentModel.Composition;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
8+
using Microsoft.CodeAnalysis.Razor.Workspaces;
9+
10+
namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
11+
12+
[Export(typeof(IRazorCohostStartupService))]
13+
[method: ImportingConstructor]
14+
internal class CohostSemanticTokensInitializeService(
15+
LanguageServerFeatureOptions languageServerFeatureOptions) : IRazorCohostStartupService
16+
{
17+
private readonly LanguageServerFeatureOptions _options = languageServerFeatureOptions;
18+
19+
public int Order => WellKnownStartupOrder.Default;
20+
21+
public Task StartupAsync(VSInternalClientCapabilities clientCapabilities, RazorCohostRequestContext requestContext, CancellationToken cancellationToken)
22+
{
23+
if (_options.UseRazorCohostServer)
24+
{
25+
// Normally, Roslyn triggers semantic tokens refreshes for additional document changes, but not for Razor documents.
26+
// In cohosting, we want it to consider Razor documents too.
27+
CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers.SemanticTokensRange.RegisterRefresh(requestContext);
28+
}
29+
30+
return Task.CompletedTask;
31+
}
32+
}

src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/SemanticTokens/CohostSemanticTokensRangeEndpoint.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ internal sealed class CohostSemanticTokensRangeEndpoint(
3939
protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SemanticTokensRangeParams request)
4040
=> request.TextDocument.ToRazorTextDocumentIdentifier();
4141

42+
protected override async Task<SemanticTokens?> HandleRequestAsync(SemanticTokensRangeParams request, RazorCohostRequestContext context, TextDocument razorDocument, CancellationToken cancellationToken)
43+
{
44+
var result = await HandleRequestAsync(request, razorDocument, cancellationToken).ConfigureAwait(false);
45+
46+
if (result is not null)
47+
{
48+
// Roslyn uses frozen semantics for semantic tokens, so it could return results from an older project state.
49+
// Every time they get a request they queue up a refresh, which will check the project checksums, and if there
50+
// hasn't been any changes, will no-op. We call into that same logic here to ensure everything is up to date.
51+
// See: https://github.com/dotnet/roslyn/blob/bb57f4643bb3d52eb7626f9863da177d9e219f1e/src/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs#L48-L52
52+
await CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers.SemanticTokensRange.TryEnqueueRefreshComputationAsync(context, razorDocument.Project, cancellationToken).ConfigureAwait(false);
53+
}
54+
55+
return result;
56+
}
57+
4258
protected override Task<SemanticTokens?> HandleRequestAsync(SemanticTokensRangeParams request, TextDocument razorDocument, CancellationToken cancellationToken)
4359
=> HandleRequestAsync(razorDocument, request.Range.ToLinePositionSpan(), cancellationToken);
4460

0 commit comments

Comments
 (0)