diff --git a/src/LanguageServer/Protocol/WellKnownLspServerKinds.cs b/src/LanguageServer/Protocol/WellKnownLspServerKinds.cs index a837cd105e93a..a99f84b743393 100644 --- a/src/LanguageServer/Protocol/WellKnownLspServerKinds.cs +++ b/src/LanguageServer/Protocol/WellKnownLspServerKinds.cs @@ -8,11 +8,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal enum WellKnownLspServerKinds { - /// - /// Razor LSP server for Razor document requests (.razor and .cshtml files) - /// - RazorCohostServer, - /// /// Roslyn LSP server for razor c# requests. /// diff --git a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorRequestHandler.cs b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorRequestHandler.cs index 33492c7b05fa7..df0a5899bb4fe 100644 --- a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorRequestHandler.cs +++ b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorRequestHandler.cs @@ -17,12 +17,6 @@ internal abstract class AbstractRazorCohostRequestHandler IRequestHandler.HandleRequestAsync(TRequestType request, RequestContext context, CancellationToken cancellationToken) { - // We have to wrap the RequestContext in order to expose it to Roslyn. We could create our own (by exporting - // and IRequestContextFactory) but that would not be possible if/when we live in the same server as Roslyn - // so may as well deal with it now. - // This does mean we can't nicely pass through the original Uri, which would have ProjectContext info, but - // we get the Project so that will have to do. - var razorRequestContext = new RazorCohostRequestContext(context); return HandleRequestAsync(request, razorRequestContext, cancellationToken); } diff --git a/src/Tools/ExternalAccess/Razor/AbstractRazorLanguageServerFactoryWrapper.cs b/src/Tools/ExternalAccess/Razor/Testing/AbstractRazorLanguageServerFactoryWrapper.cs similarity index 100% rename from src/Tools/ExternalAccess/Razor/AbstractRazorLanguageServerFactoryWrapper.cs rename to src/Tools/ExternalAccess/Razor/Testing/AbstractRazorLanguageServerFactoryWrapper.cs diff --git a/src/Tools/ExternalAccess/Razor/IRazorTestCapabilitiesProvider.cs b/src/Tools/ExternalAccess/Razor/Testing/IRazorTestCapabilitiesProvider.cs similarity index 100% rename from src/Tools/ExternalAccess/Razor/IRazorTestCapabilitiesProvider.cs rename to src/Tools/ExternalAccess/Razor/Testing/IRazorTestCapabilitiesProvider.cs diff --git a/src/Tools/ExternalAccess/Razor/RazorTestAnalyzerLoader.cs b/src/Tools/ExternalAccess/Razor/Testing/RazorTestAnalyzerLoader.cs similarity index 100% rename from src/Tools/ExternalAccess/Razor/RazorTestAnalyzerLoader.cs rename to src/Tools/ExternalAccess/Razor/Testing/RazorTestAnalyzerLoader.cs diff --git a/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs b/src/Tools/ExternalAccess/Razor/Testing/RazorTestLanguageServerFactory.cs similarity index 76% rename from src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs rename to src/Tools/ExternalAccess/Razor/Testing/RazorTestLanguageServerFactory.cs index 78104699f3f69..1d034b72bdbdb 100644 --- a/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs +++ b/src/Tools/ExternalAccess/Razor/Testing/RazorTestLanguageServerFactory.cs @@ -15,28 +15,29 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor { - [Export(typeof(AbstractRazorLanguageServerFactoryWrapper))] [Shared] - internal class RazorLanguageServerFactoryWrapper : AbstractRazorLanguageServerFactoryWrapper + [Export(typeof(RazorTestLanguageServerFactory))] + [Export(typeof(AbstractRazorLanguageServerFactoryWrapper))] + [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + [method: ImportingConstructor] + internal class RazorTestLanguageServerFactory(ILanguageServerFactory languageServerFactory) : AbstractRazorLanguageServerFactoryWrapper { - private readonly ILanguageServerFactory _languageServerFactory; + private readonly ILanguageServerFactory _languageServerFactory = languageServerFactory; - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - [ImportingConstructor] - public RazorLanguageServerFactoryWrapper(ILanguageServerFactory languageServerFactory) + internal override IRazorLanguageServerTarget CreateLanguageServer(JsonRpc jsonRpc, JsonSerializerOptions options, IRazorTestCapabilitiesProvider razorCapabilitiesProvider, HostServices hostServices) { - if (languageServerFactory is null) - { - throw new ArgumentNullException(nameof(languageServerFactory)); - } + return CreateLanguageServerCore(jsonRpc, options, razorCapabilitiesProvider, hostServices, WellKnownLspServerKinds.RazorLspServer); + } - _languageServerFactory = languageServerFactory; + internal IRazorLanguageServerTarget CreateAlwaysActiveVSLanguageServer(JsonRpc jsonRpc, JsonSerializerOptions options, IRazorTestCapabilitiesProvider razorCapabilitiesProvider, HostServices hostServices) + { + return CreateLanguageServerCore(jsonRpc, options, razorCapabilitiesProvider, hostServices, WellKnownLspServerKinds.AlwaysActiveVSLspServer); } - internal override IRazorLanguageServerTarget CreateLanguageServer(JsonRpc jsonRpc, JsonSerializerOptions options, IRazorTestCapabilitiesProvider razorCapabilitiesProvider, HostServices hostServices) + private IRazorLanguageServerTarget CreateLanguageServerCore(JsonRpc jsonRpc, JsonSerializerOptions options, IRazorTestCapabilitiesProvider razorCapabilitiesProvider, HostServices hostServices, WellKnownLspServerKinds serverKind) { var capabilitiesProvider = new RazorCapabilitiesProvider(razorCapabilitiesProvider, options); - var languageServer = _languageServerFactory.Create(jsonRpc, options, capabilitiesProvider, WellKnownLspServerKinds.RazorLspServer, NoOpLspLogger.Instance, hostServices); + var languageServer = _languageServerFactory.Create(jsonRpc, options, capabilitiesProvider, serverKind, NoOpLspLogger.Instance, hostServices); return new RazorLanguageServerTargetWrapper(languageServer); } diff --git a/src/Tools/ExternalAccess/Razor/RazorTestWorkspaceRegistrationService.cs b/src/Tools/ExternalAccess/Razor/Testing/RazorTestWorkspaceRegistrationService.cs similarity index 100% rename from src/Tools/ExternalAccess/Razor/RazorTestWorkspaceRegistrationService.cs rename to src/Tools/ExternalAccess/Razor/Testing/RazorTestWorkspaceRegistrationService.cs diff --git a/src/Tools/ExternalAccess/Razor/Testing/TestSolutionStore.cs b/src/Tools/ExternalAccess/Razor/Testing/TestSolutionStore.cs new file mode 100644 index 0000000000000..bd8f3f35b61e3 --- /dev/null +++ b/src/Tools/ExternalAccess/Razor/Testing/TestSolutionStore.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.ExternalAccess.Razor; + +internal sealed class TestSolutionStore +{ + private readonly Dictionary _solutions = []; + + internal async Task AddAsync(Solution solution, CancellationToken cancellationToken) + { + // Using compilation state, since that is what is used in the real SolutionAssetStorage class + // Compilation state is the SolutionState checksum, plus source generator info, which seems pretty relevant :) + var checksum = await solution.CompilationState.GetChecksumAsync(cancellationToken).ConfigureAwait(false); + + lock (_solutions) + { + if (_solutions.TryGetValue(checksum, out var existingSolution)) + { + return checksum; + } + + _solutions.Add(checksum, solution); + } + + return checksum; + } + + internal Solution? Get(RazorPinnedSolutionInfoWrapper solutionInfo) + { + lock (_solutions) + { + _solutions.TryGetValue(solutionInfo.UnderlyingObject, out var solution); + + return solution; + } + } +}