Skip to content

Commit

Permalink
Convert endpoint to dynamic registration
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwengier committed Mar 25, 2024
1 parent 6bea738 commit ba73960
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ public static void EnableDocumentColorProvider(this VSInternalServerCapabilities

public static void EnableSemanticTokens(this VSInternalServerCapabilities serverCapabilities, ISemanticTokensLegendService legend)
{
serverCapabilities.SemanticTokensOptions = new SemanticTokensOptions
serverCapabilities.SemanticTokensOptions = new SemanticTokensOptions().EnableSemanticTokens(legend);
}

public static SemanticTokensOptions EnableSemanticTokens(this SemanticTokensOptions options, ISemanticTokensLegendService legend)
{
options.Full = false;
options.Legend = new SemanticTokensLegend
{
Full = false,
Legend = new SemanticTokensLegend
{
TokenModifiers = legend.TokenModifiers.All,
TokenTypes = legend.TokenTypes.All
},
Range = true,
TokenModifiers = legend.TokenModifiers.All,
TokenTypes = legend.TokenTypes.All
};
options.Range = true;

return options;
}

public static void EnableHoverProvider(this VSInternalServerCapabilities serverCapabilities)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ internal class RemoteCSharpSemanticTokensProvider(IFilePathService filePathServi
// We have a razor document, lets find the generated C# document
var generatedDocument = GetGeneratedDocument(documentContext);

var csharpSourceText = await documentContext.GetCSharpSourceTextAsync(cancellationToken).ConfigureAwait(false);

// HACK: We're not in the same solution fork as the LSP server that provides content for this document
generatedDocument = generatedDocument.WithText(csharpSourceText);

var data = await SemanticTokensRange.GetSemanticTokensAsync(
generatedDocument,
csharpRanges,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
using Microsoft.CommonLanguageServerProtocol.Framework;

namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost;

internal class CohostEndpointAttribute : LanguageServerEndpointAttribute
{
public CohostEndpointAttribute(string method)
: base(method, Constants.RazorLanguageName)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.LanguageServer;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
using Microsoft.CodeAnalysis.Razor.Logging;
Expand All @@ -20,16 +18,15 @@
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost;

[Shared]
[RazorLanguageServerEndpoint(Methods.TextDocumentSemanticTokensRangeName)]
[ExportRazorStatelessLspService(typeof(CohostSemanticTokensRangeEndpoint))]
[Export(typeof(ICapabilitiesProvider))]
[CohostEndpoint(Methods.TextDocumentSemanticTokensRangeName)]
[ExportCohostStatelessLspService(typeof(CohostSemanticTokensRangeEndpoint))]
[method: ImportingConstructor]
internal sealed class CohostSemanticTokensRangeEndpoint(
IOutOfProcSemanticTokensService semanticTokensInfoService,
ISemanticTokensLegendService semanticTokensLegendService,
ITelemetryReporter telemetryReporter,
IRazorLoggerFactory loggerFactory)
: AbstractRazorCohostDocumentRequestHandler<SemanticTokensRangeParams, SemanticTokens?>, ICapabilitiesProvider
: AbstractRazorCohostDocumentRequestHandler<SemanticTokensRangeParams, SemanticTokens?>
{
private readonly IOutOfProcSemanticTokensService _semanticTokensInfoService = semanticTokensInfoService;
private readonly ISemanticTokensLegendService _semanticTokensLegendService = semanticTokensLegendService;
Expand All @@ -42,11 +39,6 @@ internal sealed class CohostSemanticTokensRangeEndpoint(
protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SemanticTokensRangeParams request)
=> request.TextDocument.ToRazorTextDocumentIdentifier();

public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
{
serverCapabilities.EnableSemanticTokens(_semanticTokensLegendService);
}

protected override async Task<SemanticTokens?> HandleRequestAsync(SemanticTokensRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken)
{
var correlationId = Guid.NewGuid();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 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.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Newtonsoft.Json;

namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost;

[Shared]
[Export(typeof(IRazorCohostDynamicRegistrationService))]
[Export(typeof(IClientCapabilitiesService))]
[method: ImportingConstructor]
internal class RazorCohostDynamicRegistrationService(LanguageServerFeatureOptions languageServerFeatureOptions, Lazy<ISemanticTokensLegendService> semanticTokensLegendService, IRazorLoggerFactory loggerFactory) : IRazorCohostDynamicRegistrationService, IClientCapabilitiesService
{
private readonly string _id = Guid.NewGuid().ToString();
private readonly DocumentFilter[] _filter = [new DocumentFilter()
{
Language = Constants.RazorLanguageName,
Pattern = "**/*.{razor,cshtml}"
}];

private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions;
private readonly Lazy<ISemanticTokensLegendService> _semanticTokensLegendService = semanticTokensLegendService;
private readonly ILogger _logger = loggerFactory.CreateLogger<RazorCohostDynamicRegistrationService>();

private VSInternalClientCapabilities? _clientCapabilities;

public bool CanGetClientCapabilities => _clientCapabilities is not null;

public VSInternalClientCapabilities ClientCapabilities => _clientCapabilities.AssumeNotNull();

public async Task RegisterAsync(string clientCapabilities, IRazorCohostClientLanguageServerManager razorCohostClientLanguageServerManager, CancellationToken cancellationToken)
{
if (!_languageServerFeatureOptions.UseRazorCohostServer)
{
return;
}

_clientCapabilities = JsonConvert.DeserializeObject<VSInternalClientCapabilities>(clientCapabilities) ?? new();

// TODO: Get the options from the from the endpoints somehow
if (_clientCapabilities.TextDocument?.SemanticTokens?.DynamicRegistration == true)
{
await razorCohostClientLanguageServerManager.SendRequestAsync(
Methods.ClientRegisterCapabilityName,
new RegistrationParams()
{
Registrations = [
new Registration()
{
Id = _id,
Method = Methods.TextDocumentSemanticTokensRangeName,
RegisterOptions = new SemanticTokensRegistrationOptions()
{
DocumentSelector = _filter,
}.EnableSemanticTokens(_semanticTokensLegendService.Value)
}
]
},
cancellationToken).ConfigureAwait(false);
}
}
}

This file was deleted.

0 comments on commit ba73960

Please sign in to comment.