-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port semantic tokens range endpoint to cohost server #9761
Changes from all commits
5819e8c
93f886d
c44a260
de081ab
0755188
d216f26
0e6bd17
16615ce
0e9d0b3
7f258ab
bf504f3
ad2fe27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,30 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Razor.LanguageServer.Common; | ||
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts; | ||
using Microsoft.AspNetCore.Razor.Telemetry; | ||
using Microsoft.CommonLanguageServerProtocol.Framework; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.VisualStudio.LanguageServer.Protocol; | ||
|
||
namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic; | ||
|
||
[LanguageServerEndpoint(LspEndpointName)] | ||
internal sealed class SemanticTokensRangeEndpoint : IRazorRequestHandler<SemanticTokensRangeParams, SemanticTokens?>, ICapabilitiesProvider | ||
[LanguageServerEndpoint(Methods.TextDocumentSemanticTokensRangeName)] | ||
internal sealed class SemanticTokensRangeEndpoint( | ||
IRazorSemanticTokensInfoService semanticTokensInfoService, | ||
RazorLSPOptionsMonitor razorLSPOptionsMonitor, | ||
IClientConnection clientConnection) | ||
: IRazorRequestHandler<SemanticTokensRangeParams, SemanticTokens?>, ICapabilitiesProvider | ||
{ | ||
public const string LspEndpointName = Methods.TextDocumentSemanticTokensRangeName; | ||
private RazorSemanticTokensLegend? _razorSemanticTokensLegend; | ||
private readonly ITelemetryReporter? _telemetryReporter; | ||
|
||
public SemanticTokensRangeEndpoint(ITelemetryReporter? telemetryReporter) | ||
{ | ||
_telemetryReporter = telemetryReporter; | ||
} | ||
private readonly IRazorSemanticTokensInfoService _semanticTokensInfoService = semanticTokensInfoService; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See reply above, but TL;DR I like the underscore :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the underscores too :) Also see my response above. I don't have strong feeling either way, other than - do the primary constructors even make sense then? |
||
private readonly RazorLSPOptionsMonitor _razorLSPOptionsMonitor = razorLSPOptionsMonitor; | ||
private readonly IClientConnection _clientConnection = clientConnection; | ||
|
||
public bool MutatesSolutionState { get; } = false; | ||
|
||
public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) | ||
{ | ||
_razorSemanticTokensLegend = new RazorSemanticTokensLegend(clientCapabilities); | ||
|
||
serverCapabilities.SemanticTokensOptions = new SemanticTokensOptions | ||
{ | ||
Full = false, | ||
Legend = _razorSemanticTokensLegend.Legend, | ||
Range = true, | ||
}; | ||
_semanticTokensInfoService.ApplyCapabilities(serverCapabilities, clientCapabilities); | ||
} | ||
|
||
public TextDocumentIdentifier GetTextDocumentIdentifier(SemanticTokensRangeParams request) | ||
|
@@ -47,26 +34,10 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(SemanticTokensRangeParam | |
|
||
public async Task<SemanticTokens?> HandleRequestAsync(SemanticTokensRangeParams request, RazorRequestContext requestContext, CancellationToken cancellationToken) | ||
{ | ||
if (request is null) | ||
{ | ||
throw new ArgumentNullException(nameof(request)); | ||
} | ||
|
||
var documentContext = requestContext.GetRequiredDocumentContext(); | ||
var semanticTokensInfoService = requestContext.GetRequiredService<IRazorSemanticTokensInfoService>(); | ||
|
||
var correlationId = Guid.NewGuid(); | ||
using var _ = _telemetryReporter?.TrackLspRequest(LspEndpointName, LanguageServerConstants.RazorLanguageServerName, correlationId); | ||
var semanticTokens = await semanticTokensInfoService.GetSemanticTokensAsync(request.TextDocument, request.Range, documentContext, _razorSemanticTokensLegend.AssumeNotNull(), correlationId, cancellationToken).ConfigureAwait(false); | ||
var amount = semanticTokens is null ? "no" : (semanticTokens.Data.Length / 5).ToString(Thread.CurrentThread.CurrentCulture); | ||
|
||
requestContext.Logger.LogInformation("Returned {amount} semantic tokens for range ({startLine},{startChar})-({endLine},{endChar}) in {request.TextDocument.Uri}.", amount, request.Range.Start.Line, request.Range.Start.Character, request.Range.End.Line, request.Range.End.Character, request.TextDocument.Uri); | ||
var colorBackground = _razorLSPOptionsMonitor.CurrentValue.ColorBackground; | ||
|
||
if (semanticTokens is not null) | ||
{ | ||
Debug.Assert(semanticTokens.Data.Length % 5 == 0, $"Number of semantic token-ints should be divisible by 5. Actual number: {semanticTokens.Data.Length}"); | ||
Debug.Assert(semanticTokens.Data.Length == 0 || semanticTokens.Data[0] >= 0, $"Line offset should not be negative."); | ||
} | ||
var semanticTokens = await _semanticTokensInfoService.GetSemanticTokensAsync(_clientConnection, request.TextDocument, request.Range, documentContext, colorBackground, cancellationToken).ConfigureAwait(false); | ||
|
||
return semanticTokens; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,13 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.VisualStudio.LanguageServer.Protocol; | ||
|
||
namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic; | ||
|
||
internal interface IRazorSemanticTokensInfoService | ||
internal interface IRazorSemanticTokensInfoService : ICapabilitiesProvider | ||
{ | ||
Task<SemanticTokens?> GetSemanticTokensAsync(TextDocumentIdentifier textDocumentIdentifier, Range range, VersionedDocumentContext documentContext, RazorSemanticTokensLegend razorSemanticTokensLegend, Guid correlationId, CancellationToken cancellationToken); | ||
Task<SemanticTokens?> GetSemanticTokensAsync(IClientConnection clientConnection, TextDocumentIdentifier textDocumentIdentifier, Range range, VersionedDocumentContext documentContext, bool colorBackground, CancellationToken cancellationToken); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that there is no else case for this
if (!featureOptions.UseRazorCohostServer)
condition,I wonder where is the cohost setup happening and why we don't add
IRazorSemanticTokensInfoService
for whenUseRazorCohostServer
is set totrue
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cohosting uses MEF for DI, so the setup is all done via attributes and not by manually adding things to service collections