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;
+ }
+ }
+}