From 89eb60fe3d292504905ece358c40a8b853ec5d0c Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Apr 2024 11:06:33 +1000 Subject: [PATCH 1/5] Don't break the Razor build if a using directive is unnecessary --- .../contentFiles/.editorconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/contentFiles/.editorconfig b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/contentFiles/.editorconfig index 43cb3d22d6e6b..e10491047f54c 100644 --- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/contentFiles/.editorconfig +++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/contentFiles/.editorconfig @@ -11,4 +11,8 @@ generated_code = true # The above configurations don't apply to compiler warnings. Requiring all params to be documented # is not something we require for this project, so suppressing it directly here. -dotnet_diagnostic.CS1573.severity = none \ No newline at end of file +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file From bf94e5f2be0e1203d4f500f4644bd0fff619f89c Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Apr 2024 11:06:41 +1000 Subject: [PATCH 2/5] Remove unused using --- .../RequestExecutionQueue.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestExecutionQueue.cs b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestExecutionQueue.cs index b24ca7e75352d..d2fda0db2d436 100644 --- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestExecutionQueue.cs +++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/RequestExecutionQueue.cs @@ -12,7 +12,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Threading; -using Newtonsoft.Json.Linq; namespace Microsoft.CommonLanguageServerProtocol.Framework; From e71f1c6105a41e20c90f85923128cee11be73c7d Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Apr 2024 11:12:41 +1000 Subject: [PATCH 3/5] Remove everything unnecessary now that there isn't a Cohost specific server --- .../Protocol/WellKnownLspServerKinds.cs | 4 - .../Razor/Cohost/AbstractRazorLspService.cs | 2 +- .../ExternalAccess/Razor/Cohost/Constants.cs | 7 - .../ExportRazorLspServiceFactoryAttribute.cs | 14 -- ...ExportRazorStatelessLspServiceAttribute.cs | 14 -- .../IRazorCohostCapabilitiesProvider.cs | 10 - ...orCohostLanguageClientActivationService.cs | 13 - .../IRazorCohostTextDocumentSyncHandler.cs | 47 ---- .../Razor/Cohost/IRazorCustomMessageTarget.cs | 9 - .../Cohost/RazorCohostDidChangeEndpoint.cs | 55 ---- .../Cohost/RazorCohostDidCloseEndpoint.cs | 45 ---- .../Cohost/RazorCohostDidOpenEndpoint.cs | 48 ---- .../Razor/Cohost/RazorCohostLanguageClient.cs | 85 ------- .../RazorCohostProjectContextEndpoint.cs | 17 -- ...erverClientLanguageServerManagerFactory.cs | 27 -- .../Razor/Cohost/RazorLspServiceProvider.cs | 21 -- .../Cohost/RazorLspWorkspaceManagerFactory.cs | 17 -- .../RazorRequestExecutionQueueProvider.cs | 25 -- .../RazorRequestTelemetryLoggerFactory.cs | 17 -- .../RazorTest/Cohost/RazorCohostTests.cs | 237 ------------------ 20 files changed, 1 insertion(+), 713 deletions(-) delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/ExportRazorLspServiceFactoryAttribute.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/ExportRazorStatelessLspServiceAttribute.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostCapabilitiesProvider.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostLanguageClientActivationService.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostTextDocumentSyncHandler.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidChangeEndpoint.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidCloseEndpoint.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidOpenEndpoint.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostLanguageClient.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostProjectContextEndpoint.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorCohostServerClientLanguageServerManagerFactory.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorLspServiceProvider.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorLspWorkspaceManagerFactory.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorRequestExecutionQueueProvider.cs delete mode 100644 src/Tools/ExternalAccess/Razor/Cohost/RazorRequestTelemetryLoggerFactory.cs delete mode 100644 src/Tools/ExternalAccess/RazorTest/Cohost/RazorCohostTests.cs diff --git a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs index da3f8390d0ac8..a837cd105e93a 100644 --- a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs +++ b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs @@ -57,7 +57,6 @@ public static string ToUserVisibleString(this WellKnownLspServerKinds server) { return server switch { - WellKnownLspServerKinds.RazorCohostServer => "Razor Cohost Language Server Client", WellKnownLspServerKinds.RazorLspServer => "Razor C# Language Server Client", WellKnownLspServerKinds.LiveShareLspServer => "Live Share C#/Visual Basic Language Server Client", WellKnownLspServerKinds.AlwaysActiveVSLspServer => "Roslyn Language Server Client", @@ -75,8 +74,6 @@ public static string ToTelemetryString(this WellKnownLspServerKinds server) { return server switch { - WellKnownLspServerKinds.RazorCohostServer => "RazorCohostLanguageClient", - // Telemetry was previously reported as RazorInProcLanguageClient.GetType().Name WellKnownLspServerKinds.RazorLspServer => "RazorInProcLanguageClient", @@ -104,7 +101,6 @@ public static string GetContractName(this WellKnownLspServerKinds server) { return server switch { - WellKnownLspServerKinds.RazorCohostServer => ProtocolConstants.RazorCohostContract, WellKnownLspServerKinds.RazorLspServer => ProtocolConstants.RoslynLspLanguagesContract, WellKnownLspServerKinds.LiveShareLspServer => ProtocolConstants.RoslynLspLanguagesContract, WellKnownLspServerKinds.AlwaysActiveVSLspServer => ProtocolConstants.RoslynLspLanguagesContract, diff --git a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs index fe2161116ec4b..f3acf7c019ae9 100644 --- a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs +++ b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs @@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; /// -/// Base class for services that need to live in Razor but be exported using +/// Base class for services that need to live in Razor cannot but be exported using /// since those services must implement but the Razor code doesn't have IVT to it. /// internal abstract class AbstractRazorLspService : ILspService diff --git a/src/Tools/ExternalAccess/Razor/Cohost/Constants.cs b/src/Tools/ExternalAccess/Razor/Cohost/Constants.cs index 1c361a9fc7003..e49cae6e73562 100644 --- a/src/Tools/ExternalAccess/Razor/Cohost/Constants.cs +++ b/src/Tools/ExternalAccess/Razor/Cohost/Constants.cs @@ -2,7 +2,6 @@ // 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.Immutable; using Microsoft.CodeAnalysis.LanguageServer; namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; @@ -10,10 +9,4 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; internal static class Constants { public const string RazorLanguageName = LanguageInfoProvider.RazorLanguageName; - - public const string RazorLSPContentType = "Razor"; - - public const string RazorLanguageContract = ProtocolConstants.RazorCohostContract; - - public static readonly ImmutableArray RazorLanguage = ImmutableArray.Create("Razor"); } diff --git a/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorLspServiceFactoryAttribute.cs b/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorLspServiceFactoryAttribute.cs deleted file mode 100644 index 8c23bcce2509c..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorLspServiceFactoryAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.LanguageServer; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[AttributeUsage(AttributeTargets.Class), MetadataAttribute] -internal class ExportRazorLspServiceFactoryAttribute(Type handlerType) : ExportLspServiceFactoryAttribute(handlerType, Constants.RazorLanguageContract, WellKnownLspServerKinds.RazorCohostServer) -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorStatelessLspServiceAttribute.cs b/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorStatelessLspServiceAttribute.cs deleted file mode 100644 index 3728932cce877..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/ExportRazorStatelessLspServiceAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.LanguageServer; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[AttributeUsage(AttributeTargets.Class), MetadataAttribute] -internal class ExportRazorStatelessLspServiceAttribute(Type handlerType) : ExportStatelessLspServiceAttribute(handlerType, Constants.RazorLanguageContract, WellKnownLspServerKinds.RazorCohostServer) -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostCapabilitiesProvider.cs b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostCapabilitiesProvider.cs deleted file mode 100644 index 1679c16c61651..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostCapabilitiesProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -// 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. - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -internal interface IRazorCohostCapabilitiesProvider -{ - string GetCapabilities(string clientCapabilities); -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostLanguageClientActivationService.cs b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostLanguageClientActivationService.cs deleted file mode 100644 index 4b1a3fc34067e..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostLanguageClientActivationService.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -internal interface IRazorCohostLanguageClientActivationService -{ - /// - /// Returns whether the Razor cohost server should activate - /// - bool ShouldActivateCohostServer(); -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostTextDocumentSyncHandler.cs b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostTextDocumentSyncHandler.cs deleted file mode 100644 index 7c897daaae639..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCohostTextDocumentSyncHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -// 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; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CommonLanguageServerProtocol.Framework; -using Roslyn.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -internal interface IRazorCohostTextDocumentSyncHandler -{ - Task HandleAsync(int version, RazorCohostRequestContext context, CancellationToken cancellationToken); -} - -internal static class IRazorCohostTextDocumentSyncHandlerExtensions -{ - public static async Task NotifyRazorAsync(this IRazorCohostTextDocumentSyncHandler? openOrChangeHandler, Uri uri, int version, RequestContext context, CancellationToken cancellationToken) - { - if (openOrChangeHandler is null) - return; - - // Razor is a little special here, because when a .razor or .cshtml document is opened/changed, which is what this request is for, - // they need to generate a C# and/or Html document. To do this they use the Razor Source Generator, but to run the generator they - // need a TextDocument for the Razor file that this request is for. To facilitate that need we create a RequestContext here - // and pass it to Razor, which is essentially the same as the RequestContext they would get on the next request, but by providing it - // early here, they can do their generation before the didOpen/didChange/didClose mutating request is finished. - // This is a little hacky, but it's the best we can do for now. In future hopefully we can switch to a pull model where the source - // generator just provides C# source to the project/compilation as normal. Whether we need to maintain this system for the Html - // generated documents remains to be seen. - var clientCapabilitiesManager = context.GetRequiredService(); - var clientCapabilities = clientCapabilitiesManager.TryGetClientCapabilities(); - var logger = context.GetRequiredService(); - var serverInfoProvider = context.GetRequiredService(); - var supportedLanguages = serverInfoProvider.SupportedLanguages; - var lspServices = context.GetRequiredService(); - - var newContext = await RequestContext.CreateAsync(false, true, new TextDocumentIdentifier() { Uri = uri }, LanguageServer.WellKnownLspServerKinds.RazorCohostServer, clientCapabilities, supportedLanguages, lspServices, logger, context.Method, cancellationToken).ConfigureAwait(false); - - var razorContext = new RazorCohostRequestContext(newContext); - - await openOrChangeHandler.HandleAsync(version, razorContext, cancellationToken).ConfigureAwait(false); - } -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs deleted file mode 100644 index 28e11a4a5cad4..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -internal interface IRazorCustomMessageTarget -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidChangeEndpoint.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidChangeEndpoint.cs deleted file mode 100644 index c700b9b2d155f..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidChangeEndpoint.cs +++ /dev/null @@ -1,55 +0,0 @@ -// 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; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CodeAnalysis.Text; -using Roslyn.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[RazorMethod(Methods.TextDocumentDidChangeName)] -[ExportRazorStatelessLspService(typeof(RazorCohostDidChangeEndpoint)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorCohostDidChangeEndpoint( - [Import(AllowDefault = true)] IRazorCohostTextDocumentSyncHandler? razorDocSyncHandler) - : ILspServiceDocumentRequestHandler -{ - public bool MutatesSolutionState => true; - public bool RequiresLSPSolution => false; - - public TextDocumentIdentifier GetTextDocumentIdentifier(DidChangeTextDocumentParams request) - => request.TextDocument; - - public async Task HandleRequestAsync(DidChangeTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) - { - var text = context.GetTrackedDocumentSourceText(request.TextDocument.Uri); - - // Per the LSP spec, each text change builds upon the previous, so we don't need to translate any text - // positions between changes, which makes this quite easy. See - // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#didChangeTextDocumentParams - // for more details. - foreach (var change in request.ContentChanges) - text = text.WithChanges(ProtocolConversions.ContentChangeEventToTextChange(change, text)); - - context.UpdateTrackedDocument(request.TextDocument.Uri, text); - - // Razor can't handle this request because they don't have access to the RequestContext, but they might want to do something with it - await razorDocSyncHandler.NotifyRazorAsync(request.TextDocument.Uri, request.TextDocument.Version, context, cancellationToken).ConfigureAwait(false); - - return null; - } -} - -[Obsolete("This API is made of regret, no longer functions, and will be removed very soon")] -internal interface IRazorCohostDidChangeHandler -{ - Task HandleAsync(Uri uri, int version, SourceText sourceText, CancellationToken cancellationToken); -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidCloseEndpoint.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidCloseEndpoint.cs deleted file mode 100644 index 734a915f07257..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidCloseEndpoint.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CommonLanguageServerProtocol.Framework; -using Roslyn.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[RazorMethod(Methods.TextDocumentDidCloseName)] -[ExportRazorStatelessLspService(typeof(RazorCohostDidCloseEndpoint)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorCohostDidCloseEndpoint( - [Import(AllowDefault = true)] IRazorCohostTextDocumentSyncHandler? razorDocSyncHandler) - : ILspServiceNotificationHandler, ITextDocumentIdentifierHandler -{ - public bool MutatesSolutionState => true; - public bool RequiresLSPSolution => false; - - public TextDocumentIdentifier GetTextDocumentIdentifier(DidCloseTextDocumentParams request) - => request.TextDocument; - - public async Task HandleNotificationAsync(DidCloseTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) - { - context.TraceInformation($"didClose for {request.TextDocument.Uri}"); - - await context.StopTrackingAsync(request.TextDocument.Uri, cancellationToken).ConfigureAwait(false); - - // Razor can't handle this request because they don't have access to the RequestContext, but they might want to do something with it - await razorDocSyncHandler.NotifyRazorAsync(request.TextDocument.Uri, version: -1, context, cancellationToken).ConfigureAwait(false); - } -} - -[Obsolete("This API is made of regret, no longer functions, and will be removed very soon")] -internal interface IRazorCohostDidCloseHandler -{ - Task HandleAsync(Uri uri, CancellationToken cancellationToken); -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidOpenEndpoint.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidOpenEndpoint.cs deleted file mode 100644 index 3aa6bcff2bdd2..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostDidOpenEndpoint.cs +++ /dev/null @@ -1,48 +0,0 @@ -// 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; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CodeAnalysis.Text; -using Microsoft.CommonLanguageServerProtocol.Framework; -using Roslyn.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[RazorMethod(Methods.TextDocumentDidOpenName)] -[ExportRazorStatelessLspService(typeof(RazorCohostDidOpenEndpoint)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorCohostDidOpenEndpoint( - [Import(AllowDefault = true)] IRazorCohostTextDocumentSyncHandler? razorDocSyncHandler) - : ILspServiceNotificationHandler, ITextDocumentIdentifierHandler -{ - public bool MutatesSolutionState => true; - public bool RequiresLSPSolution => false; - - public Uri GetTextDocumentIdentifier(DidOpenTextDocumentParams request) - => request.TextDocument.Uri; - - public async Task HandleNotificationAsync(DidOpenTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) - { - context.TraceInformation($"didOpen for {request.TextDocument.Uri}"); - - var sourceText = SourceText.From(request.TextDocument.Text, System.Text.Encoding.UTF8, SourceHashAlgorithms.OpenDocumentChecksumAlgorithm); - - await context.StartTrackingAsync(request.TextDocument.Uri, sourceText, request.TextDocument.LanguageId, cancellationToken).ConfigureAwait(false); - - // Razor can't handle this request directly because they don't have access to the RequestContext, but they might want to do something with it - await razorDocSyncHandler.NotifyRazorAsync(request.TextDocument.Uri, request.TextDocument.Version, context, cancellationToken).ConfigureAwait(false); - } -} - -[Obsolete("This API is made of regret, no longer functions, and will be removed very soon")] -internal interface IRazorCohostDidOpenHandler -{ - Task HandleAsync(Uri uri, int version, SourceText sourceText, CancellationToken cancellationToken); -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostLanguageClient.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostLanguageClient.cs deleted file mode 100644 index cdd0c54d93525..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostLanguageClient.cs +++ /dev/null @@ -1,85 +0,0 @@ -// 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; -using System.Collections.Immutable; -using System.ComponentModel.Composition; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Editor.Implementation.LanguageClient; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.Options; -using Microsoft.VisualStudio.Composition; -using Microsoft.VisualStudio.LanguageServer.Client; -using Microsoft.VisualStudio.Utilities; -using Newtonsoft.Json; -using Roslyn.LanguageServer.Protocol; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -/// -/// A language server that handles requests .razor and .cshtml files. Endpoints and required services are supplied -/// by the Razor tooling team in the Razor tooling repo. -/// -[ContentType(Constants.RazorLSPContentType)] -[Export(typeof(ILanguageClient))] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorCohostLanguageClient( - RazorLspServiceProvider lspServiceProvider, - IGlobalOptionService globalOptions, - IThreadingContext threadingContext, - ILspServiceLoggerFactory lspLoggerFactory, - ExportProvider exportProvider, - [Import(AllowDefault = true)] IRazorCohostCapabilitiesProvider? razorCapabilitiesProvider = null, - [Import(AllowDefault = true)] IRazorCustomMessageTarget? razorCustomMessageTarget = null, - [Import(AllowDefault = true)] IRazorCohostLanguageClientActivationService? razorCohostLanguageClientActivationService = null) - : AbstractInProcLanguageClient(lspServiceProvider, globalOptions, lspLoggerFactory, threadingContext, exportProvider, middleLayer: null) -{ - protected override ImmutableArray SupportedLanguages => Constants.RazorLanguage; - - public override object? CustomMessageTarget => razorCustomMessageTarget; - - public override Task OnLoadedAsync() - { - if (razorCohostLanguageClientActivationService?.ShouldActivateCohostServer() != true) - { - // By not calling the base implementation, we avoid firing the StartAsync event, which means - // the platform will never trigger the creation of an instance of the language server. - return Task.CompletedTask; - } - - return base.OnLoadedAsync(); - } - - public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) - { - Contract.ThrowIfNull(razorCapabilitiesProvider); - - // We use a string to pass capabilities to/from Razor to avoid version issues with the Protocol DLL - var serializedClientCapabilities = JsonConvert.SerializeObject(clientCapabilities); - var serializedServerCapabilities = razorCapabilitiesProvider.GetCapabilities(serializedClientCapabilities); - var razorCapabilities = JsonConvert.DeserializeObject(serializedServerCapabilities); - Contract.ThrowIfNull(razorCapabilities); - - // We support a few things on this side, so lets make sure they're set - razorCapabilities.ProjectContextProvider = true; - razorCapabilities.TextDocumentSync = new TextDocumentSyncOptions - { - OpenClose = true, - Change = TextDocumentSyncKind.Incremental - }; - - return razorCapabilities; - } - - /// - /// If the cohost server is expected to activate then any failures are catastrophic as no razor features will work. - /// - public override bool ShowNotificationOnInitializeFailed => true; - - public override WellKnownLspServerKinds ServerKind => WellKnownLspServerKinds.RazorCohostServer; -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostProjectContextEndpoint.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostProjectContextEndpoint.cs deleted file mode 100644 index 8c2606a48cdf6..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostProjectContextEndpoint.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[ExportRazorStatelessLspService(typeof(RazorCohostProjectContextEndpoint)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorCohostProjectContextEndpoint() : GetTextDocumentWithContextHandler -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostServerClientLanguageServerManagerFactory.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostServerClientLanguageServerManagerFactory.cs deleted file mode 100644 index 5fa2a36d1daf6..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorCohostServerClientLanguageServerManagerFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -// This will be removed in future when the cohost server is removed, and we move to dynamic registration. -// It's already marked as Obsolete though, because Roslyn MEF rules :) - -[Shared] -[ExportRazorLspServiceFactory(typeof(IRazorCohostClientLanguageServerManager))] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal class RazorCohostServerClientLanguageServerManagerFactory() : ILspServiceFactory -{ - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - { - var notificationManager = lspServices.GetRequiredService(); - - return new RazorCohostClientLanguageServerManager(notificationManager); - } -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorLspServiceProvider.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorLspServiceProvider.cs deleted file mode 100644 index dcf4b2487dab8..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorLspServiceProvider.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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; -using System.Collections.Generic; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[Export(typeof(RazorLspServiceProvider)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorLspServiceProvider( - [ImportMany(Constants.RazorLanguageContract)] IEnumerable> lspServices, - [ImportMany(Constants.RazorLanguageContract)] IEnumerable> lspServiceFactories) - : AbstractLspServiceProvider(lspServices, lspServiceFactories) -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorLspWorkspaceManagerFactory.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorLspWorkspaceManagerFactory.cs deleted file mode 100644 index 2f74e31c45fca..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorLspWorkspaceManagerFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[ExportRazorLspServiceFactory(typeof(LspWorkspaceManager)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorLspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) : LspWorkspaceManagerFactory(lspWorkspaceRegistrationService) -{ -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestExecutionQueueProvider.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestExecutionQueueProvider.cs deleted file mode 100644 index 8d8d28a5c72d0..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestExecutionQueueProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CommonLanguageServerProtocol.Framework; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[ExportRazorStatelessLspService(typeof(IRequestExecutionQueueProvider)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal sealed class RazorRequestExecutionQueueProvider() : IRequestExecutionQueueProvider -{ - public IRequestExecutionQueue CreateRequestExecutionQueue(AbstractLanguageServer languageServer, ILspLogger logger, AbstractHandlerProvider handlerProvider) - { - var queue = new RoslynRequestExecutionQueue(languageServer, logger, handlerProvider); - queue.Start(); - return queue; - } -} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestTelemetryLoggerFactory.cs b/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestTelemetryLoggerFactory.cs deleted file mode 100644 index 9c761d6da9ef6..0000000000000 --- a/src/Tools/ExternalAccess/Razor/Cohost/RazorRequestTelemetryLoggerFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; - -[ExportRazorLspServiceFactory(typeof(RequestTelemetryLogger)), Shared] -[method: ImportingConstructor] -[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] -internal class RazorRequestTelemetryLoggerFactory() : RequestTelemetryLoggerFactory() -{ -} diff --git a/src/Tools/ExternalAccess/RazorTest/Cohost/RazorCohostTests.cs b/src/Tools/ExternalAccess/RazorTest/Cohost/RazorCohostTests.cs deleted file mode 100644 index 0ee0abd4523d6..0000000000000 --- a/src/Tools/ExternalAccess/RazorTest/Cohost/RazorCohostTests.cs +++ /dev/null @@ -1,237 +0,0 @@ -// 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; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.CommonLanguageServerProtocol.Framework; -using Microsoft.VisualStudio.LanguageServer.Client; -using Roslyn.LanguageServer.Protocol; -using Roslyn.Test.Utilities; -using StreamJsonRpc; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.UnitTests; - -public class RazorCohostTests(ITestOutputHelper testOutputHelper) : AbstractLanguageServerProtocolTests(testOutputHelper) -{ - protected override TestComposition Composition => base.Composition - .AddAssemblies(typeof(RazorCohostLanguageClient).Assembly) - .AddParts( - typeof(RazorHandler), - typeof(RazorCohostCapabilitiesProvider), - typeof(RazorCohostLanguageClientActivationService), - typeof(NoOpLspLoggerFactory)); - - [WpfFact] - public async Task TestExternalAccessRazorHandlerInvoked() - { - var workspaceXml = """ - - - - - - """; - var testWorkspace = CreateWorkspace(workspaceXml); - var server = await InitializeLanguageServerAsync(testWorkspace); - - var document = testWorkspace.CurrentSolution.Projects.Single().AdditionalDocuments.Single(); - var request = new TextDocumentPositionParams - { - TextDocument = new VSTextDocumentIdentifier - { - Uri = document.GetURI(), - ProjectContext = new VSProjectContext - { - Id = document.Project.Id.Id.ToString() - } - } - }; - - var response = await server.GetTestAccessor().ExecuteRequestAsync(RazorHandler.MethodName, LanguageServerConstants.DefaultLanguageName, request, CancellationToken.None); - - Assert.NotNull(response); - Assert.Equal(document.GetURI(), response.DocumentUri); - Assert.Equal(document.Project.Id.Id, response.ProjectId); - } - - [WpfFact] - public async Task TestProjectContextHandler() - { - var workspaceXml = """ - - - - - - """; - var testWorkspace = CreateWorkspace(workspaceXml); - var server = await InitializeLanguageServerAsync(testWorkspace); - - var document = testWorkspace.CurrentSolution.Projects.Single().AdditionalDocuments.Single(); - var request = new VSGetProjectContextsParams - { - TextDocument = new TextDocumentItem - { - Uri = document.GetURI(), - } - }; - - var response = await server.GetTestAccessor().ExecuteRequestAsync(VSMethods.GetProjectContextsName, LanguageServerConstants.DefaultLanguageName, request, CancellationToken.None); - - Assert.NotNull(response); - var projectContext = Assert.Single(response?.ProjectContexts); - Assert.Equal(ProtocolConversions.ProjectIdToProjectContextId(document.Project.Id), projectContext.Id); - } - - [WpfFact] - public async Task TestDocumentSync() - { - var workspaceXml = """ - - - - - - """; - var testWorkspace = CreateWorkspace(workspaceXml); - var server = await InitializeLanguageServerAsync(testWorkspace); - - var document = testWorkspace.CurrentSolution.Projects.Single().AdditionalDocuments.Single(); - var didOpenRequest = new DidOpenTextDocumentParams - { - TextDocument = new TextDocumentItem - { - Uri = document.GetURI(), - Text = "Original text" - } - }; - - await server.GetTestAccessor().ExecuteRequestAsync(Methods.TextDocumentDidOpenName, LanguageServerConstants.DefaultLanguageName, didOpenRequest, CancellationToken.None); - - var workspaceManager = server.GetLspServices().GetRequiredService(); - Assert.True(workspaceManager.GetTrackedLspText().TryGetValue(document.GetURI(), out var trackedText)); - Assert.Equal("Original text", trackedText.Text.ToString()); - - var didChangeRequest = new DidChangeTextDocumentParams - { - TextDocument = new VersionedTextDocumentIdentifier - { - Uri = document.GetURI() - }, - ContentChanges = - [ - new TextDocumentContentChangeEvent - { - Range = new Roslyn.LanguageServer.Protocol.Range - { - Start = new Position(0, 0), - End = new Position(0, 0) - }, - Text = "Not The " - } - ] - }; - - await server.GetTestAccessor().ExecuteRequestAsync(Methods.TextDocumentDidChangeName, LanguageServerConstants.DefaultLanguageName, didChangeRequest, CancellationToken.None); - - Assert.True(workspaceManager.GetTrackedLspText().TryGetValue(document.GetURI(), out trackedText)); - Assert.Equal("Not The Original text", trackedText.Text.ToString()); - } - - private EditorTestWorkspace CreateWorkspace(string workspaceXml) - { - var testWorkspace = CreateWorkspace(options: null, mutatingLspWorkspace: false, workspaceKind: null); - testWorkspace.InitializeDocuments(XElement.Parse(workspaceXml), openDocuments: false); - return testWorkspace; - } - - private static async Task> InitializeLanguageServerAsync(EditorTestWorkspace testWorkspace) - { - var languageClient = testWorkspace.ExportProvider.GetExportedValues().OfType().Single(); - await languageClient.ActivateAsync(CancellationToken.None); - - var server = languageClient.GetTestAccessor().LanguageServer; - Assert.NotNull(server); - - var serverAccessor = server!.GetTestAccessor(); - - await serverAccessor.ExecuteRequestAsync(Methods.InitializeName, LanguageServerConstants.DefaultLanguageName, new InitializeParams { Capabilities = new() }, CancellationToken.None); - - return server; - } - - internal class TestRequest(Uri documentUri, Guid projectId) - { - public Uri DocumentUri => documentUri; - public Guid ProjectId => projectId; - } - - [PartNotDiscoverable] - [RazorMethod(MethodName)] - [ExportRazorStatelessLspService(typeof(RazorHandler)), Shared] - [method: ImportingConstructor] - [method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - internal class RazorHandler() : AbstractRazorCohostDocumentRequestHandler - { - internal const string MethodName = "testMethod"; - - protected override bool MutatesSolutionState => false; - - protected override bool RequiresLSPSolution => true; - - protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(TextDocumentPositionParams request) - { - return new RazorTextDocumentIdentifier(request.TextDocument.Uri, (request.TextDocument as VSTextDocumentIdentifier)?.ProjectContext?.Id); - } - - protected override Task HandleRequestAsync(TextDocumentPositionParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - Assert.NotNull(context.Solution); - AssertEx.NotNull(context.TextDocument); - return Task.FromResult(new TestRequest(context.TextDocument.GetURI(), context.TextDocument.Project.Id.Id)); - } - } - - [PartNotDiscoverable] - [Export(typeof(ILspServiceLoggerFactory)), Shared] - [method: ImportingConstructor] - [method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - private class NoOpLspLoggerFactory() : ILspServiceLoggerFactory - { - public Task CreateLoggerAsync(string serverTypeName, JsonRpc jsonRpc, CancellationToken cancellationToken) - => Task.FromResult((AbstractLspLogger)NoOpLspLogger.Instance); - } - - [PartNotDiscoverable] - [Export(typeof(IRazorCohostCapabilitiesProvider)), Shared] - [method: ImportingConstructor] - [method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - private class RazorCohostCapabilitiesProvider() : IRazorCohostCapabilitiesProvider - { - public string GetCapabilities(string clientCapabilities) - { - return "{ }"; - } - } - - [PartNotDiscoverable] - [Export(typeof(IRazorCohostLanguageClientActivationService)), Shared] - [method: ImportingConstructor] - [method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - private class RazorCohostLanguageClientActivationService() : IRazorCohostLanguageClientActivationService - { - public bool ShouldActivateCohostServer() => true; - } -} From a28b97a2f7dfe9124acf92550a90e9d5afe3f2af Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Apr 2024 20:58:33 +1000 Subject: [PATCH 4/5] Update src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs Co-authored-by: ady109 <149323961+ady109@users.noreply.github.com> --- .../ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs index f3acf7c019ae9..0b5225952f94f 100644 --- a/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs +++ b/src/Tools/ExternalAccess/Razor/Cohost/AbstractRazorLspService.cs @@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; /// -/// Base class for services that need to live in Razor cannot but be exported using +/// Base class for services that need to live in Razor but cannot be exported using /// since those services must implement but the Razor code doesn't have IVT to it. /// internal abstract class AbstractRazorLspService : ILspService From c4dcbac841826a1b66a12a2ccc2852e1507f8384 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 23 May 2024 08:55:46 +1000 Subject: [PATCH 5/5] Add back missing interface --- .../Razor/Cohost/IRazorCustomMessageTarget.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs diff --git a/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs new file mode 100644 index 0000000000000..0f2a881500ed1 --- /dev/null +++ b/src/Tools/ExternalAccess/Razor/Cohost/IRazorCustomMessageTarget.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; + +[Obsolete("This should no longer be used")] +internal interface IRazorCustomMessageTarget +{ +}