diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs index a17ba6e1e05..8105404ef82 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs @@ -114,29 +114,20 @@ public static void AddDiagnosticServices(this IServiceCollection services) services.AddSingleton(sp => new Lazy(sp.GetRequiredService)); } - public static void AddHoverServices(this IServiceCollection services, LanguageServerFeatureOptions featureOptions) + public static void AddHoverServices(this IServiceCollection services) { - // Hover services aren't needed in a cohosted world - if (featureOptions.UseRazorCohostServer) - { - return; - } - services.AddHandlerWithCapabilities(); services.AddSingleton(); } - public static void AddSemanticTokensServices(this IServiceCollection services, LanguageServerFeatureOptions featureOptions) + public static void AddSemanticTokensServices(this IServiceCollection services) { - if (!featureOptions.UseRazorCohostServer) - { - services.AddHandlerWithCapabilities(); - // Ensure that we don't add the default service if something else has added one. - services.TryAddSingleton(); + services.AddHandlerWithCapabilities(); + // Ensure that we don't add the default service if something else has added one. + services.TryAddSingleton(); - services.AddSingleton(); - } + services.AddSingleton(); services.AddHandler(); @@ -240,12 +231,7 @@ public static void AddDocumentManagementServices(this IServiceCollection service services.AddSingleton(); } - // Don't generate documents in the language server if cohost is enabled, let cohost do it. - if (!featureOptions.UseRazorCohostServer) - { - services.AddSingleton(); - } - + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/HoverEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/HoverEndpoint.cs index 2011939dc00..d9cf320da5f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/HoverEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/HoverEndpoint.cs @@ -2,7 +2,6 @@ // 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; @@ -29,7 +28,6 @@ public HoverEndpoint( : base(languageServerFeatureOptions, documentMappingService, clientConnection, loggerFactory.CreateLogger()) { _hoverService = hoverService ?? throw new ArgumentNullException(nameof(hoverService)); - Debug.Assert(languageServerFeatureOptions.UseRazorCohostServer == false, "This endpoint should not be registered when using the Razor Cohost server."); } public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs index 365d47cb2d6..1e0574d7f2d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs @@ -128,13 +128,13 @@ protected override ILspServices ConstructLspServices() services.AddLifeCycleServices(this, _clientConnection, _lspServerActivationTracker); services.AddDiagnosticServices(); - services.AddSemanticTokensServices(featureOptions); + services.AddSemanticTokensServices(); services.AddDocumentManagementServices(featureOptions); services.AddCompletionServices(featureOptions); services.AddFormattingServices(); services.AddCodeActionsServices(); services.AddOptionsServices(_lspOptions); - services.AddHoverServices(featureOptions); + services.AddHoverServices(); services.AddTextDocumentServices(); // Auto insert @@ -183,11 +183,8 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption services.AddHandler(); services.AddHandler(); - if (!featureOptions.UseRazorCohostServer) - { - services.AddHandlerWithCapabilities(); - services.AddSingleton(); - } + services.AddHandlerWithCapabilities(); + services.AddSingleton(); services.AddHandler(); services.AddHandlerWithCapabilities(); @@ -197,13 +194,10 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption services.AddHandlerWithCapabilities(); services.AddHandlerWithCapabilities(); - if (!featureOptions.UseRazorCohostServer) - { - services.AddSingleton(); + services.AddSingleton(); - services.AddHandlerWithCapabilities(); - services.AddHandler(); - } + services.AddHandlerWithCapabilities(); + services.AddHandler(); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostDocumentColorEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostDocumentColorEndpoint.cs deleted file mode 100644 index c515969c7cc..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostDocumentColorEndpoint.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.LanguageServer.DocumentColor; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.LanguageServer.Protocol; -using Microsoft.VisualStudio.LanguageServerClient.Razor.Extensions; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[RazorLanguageServerEndpoint(Methods.TextDocumentDocumentColorName)] -[ExportRazorStatelessLspService(typeof(CohostDocumentColorEndpoint))] -[Export(typeof(ICapabilitiesProvider))] -[method: ImportingConstructor] -internal sealed class CohostDocumentColorEndpoint( - IDocumentColorService documentColorService, - IRazorLoggerFactory loggerFactory) - : AbstractRazorCohostDocumentRequestHandler, ICapabilitiesProvider -{ - private readonly IDocumentColorService _documentColorService = documentColorService; - private readonly ILogger _logger = loggerFactory.CreateLogger(); - - protected override bool MutatesSolutionState => false; - protected override bool RequiresLSPSolution => true; - - protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(DocumentColorParams request) - => request.TextDocument.ToRazorTextDocumentIdentifier(); - - public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities _) - => serverCapabilities.EnableDocumentColorProvider(); - - protected override Task HandleRequestAsync(DocumentColorParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var documentContext = context.GetRequiredDocumentContext(); - - _logger.LogDebug("[Cohost] Received document color request for {requestPath} and got document {documentPath}", request.TextDocument.Uri, documentContext?.FilePath); - - var clientConnection = context.GetClientConnection(); - return _documentColorService.GetColorInformationAsync(clientConnection, request, documentContext, cancellationToken); - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostHoverEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostHoverEndpoint.cs deleted file mode 100644 index 35b74c07b9b..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostHoverEndpoint.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.LanguageServer.Hover; -using Microsoft.AspNetCore.Razor.LanguageServer.Protocol; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[RazorLanguageServerEndpoint(Methods.TextDocumentHoverName)] -[ExportRazorStatelessLspService(typeof(CohostHoverEndpoint))] -[Export(typeof(ICapabilitiesProvider))] -[method: ImportingConstructor] -internal sealed class CohostHoverEndpoint( - IHoverService hoverInfoService, - IRazorDocumentMappingService documentMappingService, - IRazorLoggerFactory loggerFactory) - : AbstractCohostDelegatingEndpoint(documentMappingService, loggerFactory.CreateLogger()), - ICapabilitiesProvider -{ - private readonly IHoverService _hoverInfoService = hoverInfoService; - - public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) - { - serverCapabilities.EnableHoverProvider(); - } - - protected override bool PreferCSharpOverHtmlIfPossible => true; - - protected override IDocumentPositionInfoStrategy DocumentPositionInfoStrategy => PreferAttributeNameDocumentPositionInfoStrategy.Instance; - - protected override string CustomMessageTarget => CustomMessageNames.RazorHoverEndpointName; - - protected override bool RequiresLSPSolution => true; - - protected override Task CreateDelegatedParamsAsync(TextDocumentPositionParams request, RazorCohostRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken) - { - var documentContext = requestContext.GetRequiredDocumentContext(); - return Task.FromResult(new DelegatedPositionParams( - documentContext.Identifier, - positionInfo.Position, - positionInfo.LanguageKind)); - } - - protected override Task TryHandleAsync(TextDocumentPositionParams request, RazorCohostRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken) - => _hoverInfoService.GetRazorHoverInfoAsync( - requestContext.GetRequiredDocumentContext(), - positionInfo, - request.Position, - cancellationToken); - - protected override Task HandleDelegatedResponseAsync(VSInternalHover? response, TextDocumentPositionParams originalRequest, RazorCohostRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken) - => _hoverInfoService.TranslateDelegatedResponseAsync( - response, - requestContext.GetRequiredDocumentContext(), - positionInfo, - cancellationToken); -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintEndpoint.cs deleted file mode 100644 index 85b3ade8e71..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintEndpoint.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.LanguageServer.InlayHints; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.LanguageServer.Protocol; -using Microsoft.VisualStudio.LanguageServerClient.Razor.Extensions; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[RazorLanguageServerEndpoint(Methods.TextDocumentInlayHintName)] -[ExportRazorStatelessLspService(typeof(CohostInlayHintEndpoint))] -[Export(typeof(ICapabilitiesProvider))] -[method: ImportingConstructor] -internal sealed class CohostInlayHintEndpoint( - IInlayHintService inlayHintService, - IRazorLoggerFactory loggerFactory) - : AbstractRazorCohostDocumentRequestHandler, ICapabilitiesProvider -{ - private readonly IInlayHintService _inlayHintService = inlayHintService; - private readonly ILogger _logger = loggerFactory.CreateLogger(); - - protected override bool MutatesSolutionState => false; - protected override bool RequiresLSPSolution => true; - - protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(InlayHintParams request) - => request.TextDocument.ToRazorTextDocumentIdentifier(); - - public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) - => serverCapabilities.EnableInlayHints(); - - protected override Task HandleRequestAsync(InlayHintParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var documentContext = context.GetRequiredDocumentContext(); - - _logger.LogDebug("[Cohost] Received inlay hint request for {requestPath} and got document {documentPath}", request.TextDocument.Uri, documentContext.FilePath); - - // TODO: We can't MEF import IRazorCohostClientLanguageServerManager in the constructor. We can make this work - // by having it implement a base class, RazorClientConnectionBase or something, that in turn implements - // AbstractRazorLspService (defined in Roslyn) and then move everything from importing IClientConnection - // to importing the new base class, so we can continue to share services. - // - // Until then we have to get the service from the request context. - var clientLanguageServerManager = context.GetRequiredService(); - var clientConnection = new RazorCohostClientConnection(clientLanguageServerManager); - - return _inlayHintService.GetInlayHintsAsync(clientConnection, documentContext, request.Range, cancellationToken); - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintResolveEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintResolveEndpoint.cs deleted file mode 100644 index 033581ee7ce..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostInlayHintResolveEndpoint.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.InlayHints; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[RazorLanguageServerEndpoint(Methods.InlayHintResolveName)] -[ExportRazorStatelessLspService(typeof(CohostInlayHintResolveEndpoint))] -[method: ImportingConstructor] -internal sealed class CohostInlayHintResolveEndpoint( - IInlayHintService inlayHintService) - : AbstractRazorCohostRequestHandler -{ - private readonly IInlayHintService _inlayHintService = inlayHintService; - - protected override bool MutatesSolutionState => false; - protected override bool RequiresLSPSolution => true; - - protected override Task HandleRequestAsync(InlayHint request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - // TODO: We can't MEF import IRazorCohostClientLanguageServerManager in the constructor. We can make this work - // by having it implement a base class, RazorClientConnectionBase or something, that in turn implements - // AbstractRazorLspService (defined in Roslyn) and then move everything from importing IClientConnection - // to importing the new base class, so we can continue to share services. - // - // Until then we have to get the service from the request context. - var clientLanguageServerManager = context.GetRequiredService(); - var clientConnection = new RazorCohostClientConnection(clientLanguageServerManager); - - return _inlayHintService.ResolveInlayHintAsync(clientConnection, request, cancellationToken); - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostSemanticTokensRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostSemanticTokensRangeEndpoint.cs deleted file mode 100644 index ab2c91819bf..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostSemanticTokensRangeEndpoint.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.LanguageServer.Semantic; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.Editor.Razor.Settings; -using Microsoft.VisualStudio.LanguageServer.Protocol; -using Microsoft.VisualStudio.LanguageServerClient.Razor.Extensions; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[RazorLanguageServerEndpoint(Methods.TextDocumentSemanticTokensRangeName)] -[ExportRazorStatelessLspService(typeof(CohostSemanticTokensRangeEndpoint))] -[Export(typeof(ICapabilitiesProvider))] -[method: ImportingConstructor] -internal sealed class CohostSemanticTokensRangeEndpoint( - IRazorSemanticTokensInfoService semanticTokensInfoService, - RazorSemanticTokensLegendService razorSemanticTokensLegendService, - IClientSettingsManager clientSettingsManager, - IRazorLoggerFactory loggerFactory) - : AbstractRazorCohostDocumentRequestHandler, ICapabilitiesProvider -{ - private readonly IRazorSemanticTokensInfoService _semanticTokensInfoService = semanticTokensInfoService; - private readonly RazorSemanticTokensLegendService _razorSemanticTokensLegendService = razorSemanticTokensLegendService; - private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager; - private readonly ILogger _logger = loggerFactory.CreateLogger(); - - protected override bool MutatesSolutionState => false; - protected override bool RequiresLSPSolution => true; - - protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SemanticTokensRangeParams request) - => request.TextDocument.ToRazorTextDocumentIdentifier(); - - public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) - { - serverCapabilities.EnableSemanticTokens(_razorSemanticTokensLegendService.Legend); - } - - protected override Task HandleRequestAsync(SemanticTokensRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var documentContext = context.GetRequiredDocumentContext(); - - _logger.LogDebug("[Cohost] Received semantic range request for {requestPath} and got document {documentPath}", request.TextDocument.Uri, documentContext.FilePath); - var clientConnection = context.GetClientConnection(); - - // TODO: This is currently using the "VS" client settings manager, since that's where we are running. In future - // we should create a hook into Roslyn's LSP options infra so we get the option values from the LSP client - var colorBackground = _clientSettingsManager.GetClientSettings().AdvancedSettings.ColorBackground; - - return _semanticTokensInfoService.GetSemanticTokensAsync(clientConnection, request.TextDocument, request.Range, documentContext, colorBackground, cancellationToken); - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostTextDocumentSyncHandler.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostTextDocumentSyncHandler.cs deleted file mode 100644 index 89c751a70e0..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/CohostTextDocumentSyncHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -// 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.Cohost; -using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Export(typeof(IRazorCohostTextDocumentSyncHandler)), Shared] -[method: ImportingConstructor] -internal class CohostTextDocumentSyncHandler( - ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, - IRazorProjectService razorProjectService, - DocumentSnapshotFactory documentSnapshotFactory, - OpenDocumentGenerator openDocumentGenerator, - IRazorLoggerFactory loggerFactory) : IRazorCohostTextDocumentSyncHandler -{ - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; - private readonly IRazorProjectService _razorProjectService = razorProjectService; - private readonly DocumentSnapshotFactory _documentSnapshotFactory = documentSnapshotFactory; - private readonly OpenDocumentGenerator _openDocumentGenerator = openDocumentGenerator; - private readonly ILogger _logger = loggerFactory.CreateLogger(); - - public async Task HandleAsync(int version, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var textDocument = context.TextDocument.AssumeNotNull(); - var textDocumentPath = context.TextDocument.FilePath.AssumeNotNull(); - - _logger.LogDebug("[Cohost] DidChange for '{document}' with version {version}.", textDocumentPath, version); - - var sourceText = await textDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); - - // TODO: This is to support the non-cohost server and should eventually be removed, and replaced with code that - // directly triggers creation/deletion of the invisible buffers we use for generated files, as necessary, - // rather than using the "project system" because we don't want the project system to actually exist! - await _projectSnapshotManagerDispatcher.RunAsync(() => - { - switch (context.Method) - { - case Methods.TextDocumentDidOpenName: - _razorProjectService.OpenDocument(textDocumentPath, sourceText, version); - break; - case Methods.TextDocumentDidChangeName: - _razorProjectService.UpdateDocument(textDocumentPath, sourceText, version); - break; - case Methods.TextDocumentDidCloseName: - _razorProjectService.CloseDocument(textDocumentPath); - break; - default: - throw new InvalidOperationException("Unsupported method: " + context.Method); - } - }, cancellationToken).ConfigureAwait(false); - - // To handle multi-targeting, whilst we get given a TextDocument, we have to actually find all of the linked documents - // it might have. - var solution = context.Solution.AssumeNotNull(); - var documentIds = solution.GetDocumentIdsWithFilePath(textDocumentPath); - - foreach (var documentId in documentIds) - { - var document = solution.GetAdditionalDocument(documentId); - if (document is null) - { - continue; - } - - var documentSnapshot = _documentSnapshotFactory.GetOrCreate(document); - _logger.LogDebug("[Cohost] Calling DocumentOpenedOrChangedAsync for '{document}' with version {version}.", textDocumentPath, version); - await _openDocumentGenerator.UpdateGeneratedDocumentsAsync(documentSnapshot, version, cancellationToken).ConfigureAwait(false); - } - - _logger.LogDebug("[Cohost] Exiting didChange for '{document}' with version {version}.", textDocumentPath, version); - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/OpenDocumentGenerator.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/OpenDocumentGenerator.cs deleted file mode 100644 index d1d17b6993c..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Cohost/OpenDocumentGenerator.cs +++ /dev/null @@ -1,146 +0,0 @@ -// 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.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Threading; - -namespace Microsoft.VisualStudio.LanguageServerClient.Razor.Cohost; - -[Shared] -[Export(typeof(OpenDocumentGenerator))] -[method: ImportingConstructor] -internal sealed class OpenDocumentGenerator( - LanguageServerFeatureOptions languageServerFeatureOptions, - LSPDocumentManager documentManager, - CSharpVirtualDocumentAddListener csharpVirtualDocumentAddListener, - ISnapshotResolver snapshotResolver, - JoinableTaskContext joinableTaskContext, - IRazorLoggerFactory loggerFactory) -{ - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentNullException(nameof(languageServerFeatureOptions)); - private readonly TrackingLSPDocumentManager _documentManager = documentManager as TrackingLSPDocumentManager ?? throw new ArgumentNullException(nameof(documentManager)); - private readonly CSharpVirtualDocumentAddListener _csharpVirtualDocumentAddListener = csharpVirtualDocumentAddListener ?? throw new ArgumentNullException(nameof(csharpVirtualDocumentAddListener)); - private readonly ISnapshotResolver _snapshotResolver = snapshotResolver ?? throw new ArgumentNullException(nameof(snapshotResolver)); - private readonly JoinableTaskFactory _joinableTaskFactory = joinableTaskContext.Factory; - private readonly ILogger _logger = loggerFactory.CreateLogger(); - - public async Task UpdateGeneratedDocumentsAsync(IDocumentSnapshot document, int version, CancellationToken cancellationToken) - { - // These flags exist to workaround things in VS Code, so bringing cohosting to VS Code without also fixing these flags, is very silly. - Debug.Assert(_languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath); - Debug.Assert(!_languageServerFeatureOptions.UpdateBuffersForClosedDocuments); - - // Actually do the generation - var generatedOutput = await document.GetGeneratedOutputAsync().ConfigureAwait(false); - - // Now we have to update the LSP buffer etc. - // Fortunate this code will be removed in time - var hostDocumentUri = new Uri(document.FilePath); - - _logger.LogDebug("[Cohost] Updating generated document buffers for {version} of {uri} in {projectKey}", version, hostDocumentUri, document.Project.Key); - - if (_documentManager.TryGetDocument(hostDocumentUri, out var documentSnapshot)) - { - // Html - var htmlVirtualDocumentSnapshot = TryGetHtmlSnapshot(documentSnapshot); - - // Buffer work has to be on the UI thread, and getting the C# buffers might result in a change to which buffers exist - await _joinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - - // CSharp - var csharpVirtualDocumentSnapshot = await TryGetCSharpSnapshotAsync(documentSnapshot, document.Project.Key, version, cancellationToken).ConfigureAwait(true); - - Debug.Assert(htmlVirtualDocumentSnapshot is not null && csharpVirtualDocumentSnapshot is not null || - htmlVirtualDocumentSnapshot is null && csharpVirtualDocumentSnapshot is null, "Found a Html XOR a C# document. Expected both or neither."); - - if (htmlVirtualDocumentSnapshot is not null) - { - _logger.LogDebug("Updating to version {version}: {virtualDocument}", version, htmlVirtualDocumentSnapshot.Uri); - _documentManager.UpdateVirtualDocument( - hostDocumentUri, - [new VisualStudioTextChange(0, htmlVirtualDocumentSnapshot.Snapshot.Length, generatedOutput.GetHtmlSourceText().ToString())], - version, - state: null); - } - - if (csharpVirtualDocumentSnapshot is not null) - { - _logger.LogDebug("Updating to version {version}: {virtualDocument}", version, csharpVirtualDocumentSnapshot.Uri); - _documentManager.UpdateVirtualDocument( - hostDocumentUri, - csharpVirtualDocumentSnapshot.Uri, - [new VisualStudioTextChange(0, csharpVirtualDocumentSnapshot.Snapshot.Length, generatedOutput.GetCSharpSourceText().ToString())], - version, - state: null); - return; - } - } - } - - private async Task TryGetCSharpSnapshotAsync(LSPDocumentSnapshot documentSnapshot, ProjectKey projectKey, int version, CancellationToken cancellationToken) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - if (documentSnapshot.TryGetAllVirtualDocuments(out var virtualDocuments)) - { - if (virtualDocuments is [{ ProjectKey.Id: null }]) - { - // If there is only a single virtual document, and its got a null id, then that means it's in our "misc files" project. - // That means its probably new, as Visual Studio opens a buffer for a document before we get the notifications about it - // being added to any projects. Lets try refreshing before we worry. - _logger.LogDebug("[Cohost] Refreshing virtual documents, and waiting for them, (for {hostDocumentUri})", documentSnapshot.Uri); - - var task = _csharpVirtualDocumentAddListener.WaitForDocumentAddAsync(cancellationToken); - _documentManager.RefreshVirtualDocuments(); - _ = await task.ConfigureAwait(true); - - // Since we're dealing with snapshots, we have to get the new ones after refreshing - if (!_documentManager.TryGetDocument(documentSnapshot.Uri, out var newDocumentSnapshot) || - !newDocumentSnapshot.TryGetAllVirtualDocuments(out virtualDocuments)) - { - // This should never happen. - // The server clearly wants to tell us about a document in a project, but we don't know which project it's in. - // Sadly there isn't anything we can do here to, we're just in a state where the server and client are out of - // sync with their understanding of the document contents, and since changes come in as a list of changes, - // the user experience is broken. All we can do is hope the user closes and re-opens the document. - _logger.LogError("[Cohost] Server wants to update {hostDocumentUri} in {projectKeyId} but we only know about that document in misc files. Server and client are now out of sync.", documentSnapshot.Uri, projectKey); - Debug.Fail($"Server wants to update {documentSnapshot.Uri} in {projectKey} but we don't know about the document being in any projects"); - return null; - } - } - - foreach (var virtualDocument in virtualDocuments) - { - if (virtualDocument.ProjectKey.Equals(projectKey)) - { - _logger.LogDebug("[Cohost] Found C# virtual doc for {version}: {uri}", version, virtualDocument.Uri); - - return virtualDocument; - } - } - - _logger.LogError("[Cohost] Couldn't find any virtual docs for {version} of {uri} in {projectKey}", version, documentSnapshot.Uri, projectKey); - Debug.Fail($"Couldn't find any virtual docs for {version} of {documentSnapshot.Uri} in {projectKey}"); - } - - return null; - } - - private static HtmlVirtualDocumentSnapshot? TryGetHtmlSnapshot(LSPDocumentSnapshot documentSnapshot) - { - _ = documentSnapshot.TryGetVirtualDocument(out var htmlVirtualDocumentSnapshot); - return htmlVirtualDocumentSnapshot; - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateCSharpBuffer.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateCSharpBuffer.cs index 61234728d3b..e622afd0c35 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateCSharpBuffer.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateCSharpBuffer.cs @@ -20,8 +20,6 @@ internal partial class RazorCustomMessageTarget [JsonRpcMethod(CustomMessageNames.RazorUpdateCSharpBufferEndpoint, UseSingleObjectParameterDeserialization = true)] public async Task UpdateCSharpBufferAsync(UpdateBufferRequest request, CancellationToken cancellationToken) { - Debug.Assert(!_languageServerFeatureOptions.UseRazorCohostServer); - if (request is null) { throw new ArgumentNullException(nameof(request)); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateHtmlBuffer.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateHtmlBuffer.cs index a85a5f3748e..eb38c1cc21c 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateHtmlBuffer.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/UpdateHtmlBuffer.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -19,8 +18,6 @@ internal partial class RazorCustomMessageTarget [JsonRpcMethod(CustomMessageNames.RazorUpdateHtmlBufferEndpoint, UseSingleObjectParameterDeserialization = true)] public async Task UpdateHtmlBufferAsync(UpdateBufferRequest request, CancellationToken cancellationToken) { - Debug.Assert(!_languageServerFeatureOptions.UseRazorCohostServer); - if (request is null) { throw new ArgumentNullException(nameof(request));