From 2f40b9aca98dba2ff1aad015296f65b04ca39d3e Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 5 May 2022 16:37:03 -0700 Subject: [PATCH 1/8] Add support for exporting services that are created for each server instance. --- .../AbstactVSTypeScriptLspServiceFactory.cs | 19 ++ .../Api/AbstractVSTypeScriptRequestHandler.cs | 3 +- ...tractVSTypeScriptRequestHandlerProvider.cs | 19 -- ...criptLspRequestHandlerProviderAttribute.cs | 4 +- .../VSTypeScriptDidChangeHandler.cs | 3 +- .../VSTypeScriptDidCloseHandler.cs | 3 +- .../VSTypeScriptDidOpenHandler.cs | 3 +- .../VSTypeScriptInProcLanguageClient.cs | 5 +- .../VSTypeScript/VSTypeScriptLspFactories.cs | 42 ++++ ...y.cs => VSTypeScriptLspServiceProvider.cs} | 16 +- ...TypeScriptPullDiagnosticHandlerProvider.cs | 38 ++- .../AbstractInProcLanguageClient.cs | 14 +- .../AlwaysActivateInProcLanguageClient.cs | 5 +- .../CodeActions/CodeActionResolveHandler.cs | 11 +- .../Handlers/CodeActions/CodeActionsCache.cs | 18 +- .../CodeActions/CodeActionsHandler.cs | 25 +- .../CodeActions/CodeActionsHandlerProvider.cs | 53 ---- .../CodeActions/RunCodeActionHandler.cs | 12 +- .../Handlers/Completion/CompletionHandler.cs | 34 +-- .../Completion/CompletionHandlerProvider.cs | 41 ---- .../Completion/CompletionListCache.cs | 18 +- .../Completion/CompletionResolveHandler.cs | 22 ++ .../Handlers/Hover/HoverHandler.cs | 12 +- .../References/FindAllReferencesHandler.cs | 12 +- .../References/FindImplementationsHandler.cs | 12 +- .../Handlers/Rename/RenameHandler.cs | 12 +- .../Symbols/DocumentSymbolsHandler.cs | 12 +- .../Symbols/WorkspaceSymbolsHandler.cs | 12 +- .../LiveShareInProcLanguageClient.cs | 5 +- .../RazorInProcLanguageClient.cs | 5 +- .../AbstractLanguageServerProtocolTests.cs | 21 +- .../AbstractRequestDispatcherFactory.cs | 33 --- .../CSharpVisualBasicLanguageServerFactory.cs | 22 +- .../Handler/AbstractRequestHandlerProvider.cs | 25 -- .../AbstractStatelessRequestHandler.cs | 30 --- .../ValidateBreakableRangeHandler.cs | 12 +- .../AbstractGoToDefinitionHandler.cs | 11 +- .../Definitions/GoToDefinitionHandler.cs | 2 +- .../Definitions/GoToTypeDefinitionHandler.cs | 2 +- .../AbstractPullDiagnosticHandler.cs | 7 +- .../DocumentPullDiagnosticHandler.cs | 33 ++- ...alDocumentPullDiagnosticHandlerProvider.cs | 37 --- ...erimentalDocumentPullDiagnosticsHandler.cs | 33 ++- ...lWorkspacePullDiagnosticHandlerProvider.cs | 37 --- ...rimentalWorkspacePullDiagnosticsHandler.cs | 33 ++- .../PullDiagnosticHandlerProvider.cs | 41 ---- .../WorkspacePullDiagnosticHandler.cs | 32 ++- .../DocumentChanges/DidChangeHandler.cs | 12 +- .../DocumentChanges/DidCloseHandler.cs | 12 +- .../Handler/DocumentChanges/DidOpenHandler.cs | 12 +- ...xportLspRequestHandlerProviderAttribute.cs | 56 ----- .../FoldingRanges/FoldingRangesHandler.cs | 12 +- .../AbstractFormatDocumentHandlerBase.cs | 10 +- .../Formatting/FormatDocumentHandler.cs | 2 +- .../Formatting/FormatDocumentOnTypeHandler.cs | 12 +- .../Formatting/FormatDocumentRangeHandler.cs | 2 +- .../Highlights/DocumentHighlightHandler.cs | 12 +- .../Handler/IDocumentChangeTracker.cs | 37 +++ .../Protocol/Handler/IRequestHandler.cs | 2 +- .../InlineCompletionsHandler.cs | 12 +- .../OnAutoInsert/OnAutoInsertHandler.cs | 12 +- .../GetTextDocumentWithContextHandler.cs | 12 +- .../Protocol/Handler/RequestContext.cs | 34 +-- ...estExecutionQueue.DocumentChangeTracker.cs | 89 ------- .../RequestExecutionQueue.QueueItem.cs | 4 +- ...stExecutionQueue.RequestTelemetryLogger.cs | 213 ----------------- .../Protocol/Handler/RequestExecutionQueue.cs | 74 ++++-- .../RequestHandlerProviderMetadataView.cs | 26 -- .../Handler/RequestTelemetryLogger.cs | 226 ++++++++++++++++++ .../SemanticTokens/SemanticTokensHelpers.cs | 2 +- .../SemanticTokensRangeHandler.cs | 118 ++++----- .../SignatureHelp/SignatureHelpHandler.cs | 12 +- .../SpellCheck/DocumentSpellCheckHandler.cs | 20 ++ .../DocumentSpellCheckHandlerProvider.cs | 24 -- .../SpellCheck/WorkspaceSpellCheckHandler.cs | 16 ++ .../WorkspaceSpellCheckHandlerProvider.cs | 24 -- .../ILanguageServerNotificationManager.cs | 2 +- .../LanguageServer/Protocol/ILspLogger.cs | 2 +- .../Protocol/LanguageServerTarget.cs | 67 +++--- .../LspServices/AbstractLspServiceProvider.cs | 29 +++ .../ExportLspServiceFactoryAttribute.cs | 39 +++ .../ExportRoslynLspServiceFactoryAttribute.cs | 30 +++ .../ExportStatelessLspServiceAttribute.cs | 38 +++ .../Protocol/LspServices/ILspService.cs | 11 + .../LspServices/ILspServiceFactory.cs | 17 ++ .../LspServices/LspServiceMetadataView.cs | 33 +++ .../Protocol/LspServices/LspServices.cs | 108 +++++++++ .../LspServices/RoslynLspServiceProvider.cs | 23 ++ .../Protocol/RequestDispatcher.cs | 61 ++--- .../Protocol/RequestDispatcherFactory.cs | 19 +- .../Protocol/WellKnownLspServerKinds.cs | 21 ++ .../LspMiscellaneousFilesWorkspace.cs | 27 ++- .../Workspaces/LspWorkspaceManager.cs | 7 +- .../Workspaces/LspWorkspaceManagerFactory.cs | 31 +++ .../CodeActions/CodeActionsTests.cs | 7 +- .../Completion/CompletionTests.cs | 7 +- .../DocumentChangesTests.LinkedDocuments.cs | 8 +- ...umentChangesTests.WithFindAllReferences.cs | 2 +- .../DocumentChanges/DocumentChangesTests.cs | 20 +- .../LanguageServerTargetTests.cs | 78 ++++++ .../LspMiscellaneousFilesWorkspaceTests.cs | 43 +++- .../Ordering/FailingMutatingRequestHandler.cs | 12 +- .../Ordering/FailingRequestHandler.cs | 12 +- .../LongRunningNonMutatingRequestHandler.cs | 12 +- .../Ordering/MutatingRequestHandler.cs | 12 +- .../NonLSPSolutionRequestHandlerProvider.cs | 12 +- .../Ordering/NonMutatingRequestHandler.cs | 12 +- .../VSTypeScriptHandlerTests.cs | 43 ++-- .../Workspaces/LspWorkspaceManagerTests.cs | 4 +- .../XamlInProcLanguageClient.cs | 5 +- .../XamlInProcLanguageClientDisableUX.cs | 5 +- .../CodeActions/CodeActionsHandlerProvider.cs | 55 +++-- .../Commands/CreateEventCommandHandler.cs | 13 +- .../CreateEventCommandHandlerProvider.cs | 31 --- .../Handler/Completion/CompletionHandler.cs | 12 +- .../Completion/CompletionResolveHandler.cs | 12 +- .../Definitions/GoToDefinitionHandler.cs | 12 +- .../AbstractPullDiagnosticHandler.cs | 10 +- .../DocumentPullDiagnosticHandler.cs | 2 +- .../WorkspacePullDiagnosticHandler.cs | 2 +- .../FoldingRanges/FoldingRangesHandler.cs | 13 +- .../AbstractFormatDocumentHandlerBase.cs | 10 +- .../Formatting/FormatDocumentHandler.cs | 2 +- .../Formatting/FormatDocumentOnTypeHandler.cs | 12 +- .../Formatting/FormatDocumentRangeHandler.cs | 2 +- .../Handler/Hover/HoverHandler.cs | 12 +- .../OnAutoInsert/OnAutoInsertHandler.cs | 12 +- .../OnTypeRename/OnTypeRenameHandler.cs | 12 +- .../XamlRequestDispatcherFactory.cs | 51 +++- 129 files changed, 1706 insertions(+), 1428 deletions(-) create mode 100644 src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstactVSTypeScriptLspServiceFactory.cs delete mode 100644 src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandlerProvider.cs create mode 100644 src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs rename src/EditorFeatures/Core/ExternalAccess/VSTypeScript/{VSTypeScriptRequestDispatcherFactory.cs => VSTypeScriptLspServiceProvider.cs} (52%) delete mode 100644 src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandlerProvider.cs delete mode 100644 src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/AbstractRequestDispatcherFactory.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/AbstractRequestHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/AbstractStatelessRequestHandler.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/ExportLspRequestHandlerProviderAttribute.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.RequestTelemetryLogger.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/RequestHandlerProviderMetadataView.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerProvider.cs delete mode 100644 src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerProvider.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/AbstractLspServiceProvider.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ILspService.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/LspServices.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs create mode 100644 src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs delete mode 100644 src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandlerProvider.cs diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstactVSTypeScriptLspServiceFactory.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstactVSTypeScriptLspServiceFactory.cs new file mode 100644 index 0000000000000..ed93a504254e9 --- /dev/null +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstactVSTypeScriptLspServiceFactory.cs @@ -0,0 +1,19 @@ +// 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.Text; +using Microsoft.CodeAnalysis.LanguageServer; + +namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript.Api; +internal abstract class AbstractVSTypeScriptRequestHandlerFactory : ILspServiceFactory +{ + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + return CreateRequestHandler(); + } + + protected abstract IVSTypeScriptRequestHandler CreateRequestHandler(); +} diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandler.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandler.cs index 22f2cdd727a38..4bed4034d44e6 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandler.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandler.cs @@ -6,6 +6,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -65,6 +66,6 @@ internal record struct TypeScriptRequestContext(Solution? Solution, Document? Do /// internal record struct TypeScriptTextDocumentIdentifier(Uri Uri, string? ProjectId); -internal interface IVSTypeScriptRequestHandler +internal interface IVSTypeScriptRequestHandler : ILspService { } diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandlerProvider.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandlerProvider.cs deleted file mode 100644 index 26e89a3598404..0000000000000 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/AbstractVSTypeScriptRequestHandlerProvider.cs +++ /dev/null @@ -1,19 +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.Collections.Immutable; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; - -namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript.Api; - -internal abstract class AbstractVSTypeScriptRequestHandlerProvider : IRequestHandlerProvider -{ - ImmutableArray IRequestHandlerProvider.CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return CreateRequestHandlers().SelectAsArray(tsHandler => (IRequestHandler)tsHandler); - } - - protected abstract ImmutableArray CreateRequestHandlers(); -} diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/ExportTypeScriptLspRequestHandlerProviderAttribute.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/ExportTypeScriptLspRequestHandlerProviderAttribute.cs index 46766f86e28b4..0774206c91562 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/ExportTypeScriptLspRequestHandlerProviderAttribute.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/ExportTypeScriptLspRequestHandlerProviderAttribute.cs @@ -10,9 +10,9 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript.Api; [AttributeUsage(AttributeTargets.Class), MetadataAttribute] -internal class ExportTypeScriptLspRequestHandlerProviderAttribute : ExportLspRequestHandlerProviderAttribute +internal class ExportTypeScriptLspServiceFactoryAttribute : ExportLspServiceFactoryAttribute { - public ExportTypeScriptLspRequestHandlerProviderAttribute(Type firstHandlerType, params Type[] additionalHandlerTypes) : base(ProtocolConstants.TypeScriptLanguageContract, firstHandlerType, additionalHandlerTypes) + public ExportTypeScriptLspServiceFactoryAttribute(Type handlerType) : base(handlerType, ProtocolConstants.TypeScriptLanguageContract) { } } diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidChangeHandler.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidChangeHandler.cs index 9a2005ad38764..ca81a40088f20 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidChangeHandler.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidChangeHandler.cs @@ -11,8 +11,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[Shared] -[ExportLspRequestHandlerProvider(ProtocolConstants.TypeScriptLanguageContract, typeof(DidChangeHandler))] +[ExportStatelessLspService(typeof(DidChangeHandler), ProtocolConstants.TypeScriptLanguageContract), Shared] internal class VSTypeScriptDidChangeHandler : DidChangeHandler { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidCloseHandler.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidCloseHandler.cs index 4e0b394fa2204..39115e8421f45 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidCloseHandler.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidCloseHandler.cs @@ -11,8 +11,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[Shared] -[ExportLspRequestHandlerProvider(ProtocolConstants.TypeScriptLanguageContract, typeof(DidCloseHandler))] +[ExportStatelessLspService(typeof(DidCloseHandler), ProtocolConstants.TypeScriptLanguageContract), Shared] internal class VSTypeScriptDidCloseHandler : DidCloseHandler { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidOpenHandler.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidOpenHandler.cs index bc622c4983e55..aba27df0d413c 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidOpenHandler.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptDidOpenHandler.cs @@ -11,8 +11,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[Shared] -[ExportLspRequestHandlerProvider(ProtocolConstants.TypeScriptLanguageContract, typeof(DidOpenHandler))] +[ExportStatelessLspService(typeof(DidOpenHandler), ProtocolConstants.TypeScriptLanguageContract), Shared] internal class VSTypeScriptDidOpenHandler : DidOpenHandler { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs index abaab663d4662..f80266f7904ab 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptInProcLanguageClient.cs @@ -38,14 +38,13 @@ internal class VSTypeScriptInProcLanguageClient : AbstractInProcLanguageClient [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public VSTypeScriptInProcLanguageClient( [Import(AllowDefault = true)] IVSTypeScriptCapabilitiesProvider? typeScriptCapabilitiesProvider, - VSTypeScriptRequestDispatcherFactory requestDispatcherFactory, + VSTypeScriptLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(requestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext) { _typeScriptCapabilitiesProvider = typeScriptCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs new file mode 100644 index 0000000000000..7417cf97b3084 --- /dev/null +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs @@ -0,0 +1,42 @@ +// 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; +using Microsoft.CodeAnalysis.LanguageServer.Handler; + +namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; + +[ExportLspServiceFactory(typeof(RequestDispatcher), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptRequestDispatcherFactory : RequestDispatcherFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptRequestDispatcherFactory() + { + } +} + +[ExportLspServiceFactory(typeof(LspWorkspaceManager), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptLspWorkspaceManagerFactory : LspWorkspaceManagerFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptLspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) : base(lspWorkspaceRegistrationService) + { + } +} + +[ExportLspServiceFactory(typeof(RequestTelemetryLogger), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptRequestTelemetryLoggerFactory() + { + } +} diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs similarity index 52% rename from src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs rename to src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs index 81a4ec9d86145..6f0ddc0d0db63 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs @@ -7,23 +7,17 @@ using System.Composition; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[Shared] -[Export(typeof(VSTypeScriptRequestDispatcherFactory))] -internal class VSTypeScriptRequestDispatcherFactory : AbstractRequestDispatcherFactory +[Export, Shared] +internal class VSTypeScriptLspServiceProvider : AbstractLspServiceProvider { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSTypeScriptRequestDispatcherFactory( - [ImportMany(ProtocolConstants.TypeScriptLanguageContract)] IEnumerable> requestHandlerProviders) : base(requestHandlerProviders) + public VSTypeScriptLspServiceProvider( + [ImportMany(ProtocolConstants.TypeScriptLanguageContract)] IEnumerable> lspServices, + [ImportMany(ProtocolConstants.TypeScriptLanguageContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) { } - - public override RequestDispatcher CreateRequestDispatcher(WellKnownLspServerKinds serverKind) - { - return base.CreateRequestDispatcher(serverKind); - } } diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptPullDiagnosticHandlerProvider.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptPullDiagnosticHandlerProvider.cs index 2b1faa56cff7d..98077bc2ff19b 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptPullDiagnosticHandlerProvider.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptPullDiagnosticHandlerProvider.cs @@ -11,20 +11,34 @@ using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.LanguageServer.Protocol; -namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript +namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; + +[ExportLspServiceFactory(typeof(DocumentPullDiagnosticHandler), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptDocumentPullDiagnosticHandlerFactory : DocumentPullDiagnosticHandlerFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptDocumentPullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) : base(diagnosticService, analyzerService, editAndContinueDiagnosticUpdateSource, globalOptions) + { + } +} + +[ExportLspServiceFactory(typeof(WorkspacePullDiagnosticHandler), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptWorkspacePullDiagnosticHandler : WorkspacePullDiagnosticHandlerFactory { - [Shared] - [ExportLspRequestHandlerProvider(ProtocolConstants.TypeScriptLanguageContract, typeof(DocumentPullDiagnosticHandler), typeof(WorkspacePullDiagnosticHandler))] - internal class VSTypeScriptPullDiagnosticHandlerProvider : PullDiagnosticHandlerProvider + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptWorkspacePullDiagnosticHandler( + IDiagnosticService diagnosticService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) : base(diagnosticService, editAndContinueDiagnosticUpdateSource, globalOptions) { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSTypeScriptPullDiagnosticHandlerProvider( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) : base(diagnosticService, analyzerService, editAndContinueDiagnosticUpdateSource) - { - } } } diff --git a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs index fdbe161808131..cf3016dc52a72 100644 --- a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs @@ -29,8 +29,7 @@ internal abstract partial class AbstractInProcLanguageClient : ILanguageClient, private readonly ILspLoggerFactory _lspLoggerFactory; private readonly IAsynchronousOperationListenerProvider _listenerProvider; - private readonly AbstractRequestDispatcherFactory _requestDispatcherFactory; - private readonly LspWorkspaceRegistrationService _lspWorkspaceRegistrationService; + private readonly AbstractLspServiceProvider _lspServiceProvider; protected readonly IGlobalOptionService GlobalOptions; @@ -100,18 +99,16 @@ internal abstract partial class AbstractInProcLanguageClient : ILanguageClient, public event AsyncEventHandler? StopAsync { add { } remove { } } public AbstractInProcLanguageClient( - AbstractRequestDispatcherFactory requestDispatcherFactory, + AbstractLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext, AbstractLanguageClientMiddleLayer? middleLayer = null) { - _requestDispatcherFactory = requestDispatcherFactory; + _lspServiceProvider = lspServiceProvider; GlobalOptions = globalOptions; _listenerProvider = listenerProvider; - _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; _lspLoggerFactory = lspLoggerFactory; _threadingContext = threadingContext; _middleLayer = middleLayer; @@ -227,12 +224,9 @@ public ILanguageServerTarget Create( ILspLogger logger) { return new LanguageServerTarget( - _requestDispatcherFactory, + _lspServiceProvider, jsonRpc, capabilitiesProvider, - _lspWorkspaceRegistrationService, - lspMiscellaneousFilesWorkspace: null, - GlobalOptions, _listenerProvider, logger, SupportedLanguages, diff --git a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs index abefca2bfdebe..b96d266812b55 100644 --- a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs @@ -36,14 +36,13 @@ internal class AlwaysActivateInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public AlwaysActivateInProcLanguageClient( - RequestDispatcherFactory csharpVBRequestDispatcherFactory, + RoslynLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs index a6f1aee4fb089..5dbcef1f44c0b 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs @@ -4,12 +4,14 @@ using System; using System.Collections.Generic; +using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; @@ -32,21 +34,21 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// EditorFeatures references in are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// + [ExportRoslynStatelessLspService(typeof(CodeActionResolveHandler)), Shared] [Method(LSP.Methods.CodeActionResolveName)] internal class CodeActionResolveHandler : IRequestHandler { - private readonly CodeActionsCache _codeActionsCache; private readonly ICodeFixService _codeFixService; private readonly ICodeRefactoringService _codeRefactoringService; private readonly IGlobalOptionService _globalOptions; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CodeActionResolveHandler( - CodeActionsCache codeActionsCache, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IGlobalOptionService globalOptions) { - _codeActionsCache = codeActionsCache; _codeFixService = codeFixService; _codeRefactoringService = codeRefactoringService; _globalOptions = globalOptions; @@ -68,8 +70,9 @@ public CodeActionResolveHandler( var options = _globalOptions.GetCodeActionOptionsProvider(); + var codeActionsCache = context.GetRequiredLspService(); var codeActions = await CodeActionHelpers.GetCodeActionsAsync( - _codeActionsCache, + codeActionsCache, document, data.Range, options, diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs index aadab26daa50d..b033277a6a8a9 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs @@ -2,22 +2,38 @@ // 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.Collections.Immutable; +using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.UnifiedSuggestions; using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions { + [ExportRoslynLspServiceFactory(typeof(CodeActionsCache)), Shared] + internal class CodeActionsCacheFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CodeActionsCacheFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CodeActionsCache(); + } + /// /// Caches suggested action sets between calls to and /// . /// - internal class CodeActionsCache + internal class CodeActionsCache : ILspService { /// /// Ensures we aren't making concurrent modifications to the list of cached items. diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs index 065082667a321..9193ecc94b7d1 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs @@ -3,11 +3,13 @@ // 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.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -25,10 +27,10 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// EditorFeatures references in are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// + [ExportRoslynStatelessLspService(typeof(CodeActionsHandler)), Shared] [Method(LSP.Methods.TextDocumentCodeActionName)] internal class CodeActionsHandler : IRequestHandler { - private readonly CodeActionsCache _codeActionsCache; private readonly ICodeFixService _codeFixService; private readonly ICodeRefactoringService _codeRefactoringService; private readonly IGlobalOptionService _globalOptions; @@ -38,13 +40,13 @@ internal class CodeActionsHandler : IRequestHandler false; public bool RequiresLSPSolution => true; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CodeActionsHandler( - CodeActionsCache codeActionsCache, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IGlobalOptionService globalOptions) { - _codeActionsCache = codeActionsCache; _codeFixService = codeFixService; _codeRefactoringService = codeRefactoringService; _globalOptions = globalOptions; @@ -59,24 +61,11 @@ public CodeActionsHandler( var options = _globalOptions.GetCodeActionOptionsProvider(); + var codeActionsCache = context.GetRequiredLspService(); var codeActions = await CodeActionHelpers.GetVSCodeActionsAsync( - request, _codeActionsCache, document, options, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false); + request, codeActionsCache, document, options, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false); return codeActions; } - - internal TestAccessor GetTestAccessor() - => new TestAccessor(this); - - internal readonly struct TestAccessor - { - private readonly CodeActionsHandler _codeActionsHandler; - - public TestAccessor(CodeActionsHandler codeActionsHandler) - => _codeActionsHandler = codeActionsHandler; - - public CodeActionsCache GetCache() - => _codeActionsHandler._codeActionsCache; - } } } diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandlerProvider.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandlerProvider.cs deleted file mode 100644 index 3f38322b1950c..0000000000000 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandlerProvider.cs +++ /dev/null @@ -1,53 +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.Composition; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CodeRefactorings; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; -using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands; -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - /// - /// Exports all the code action handlers together to ensure they - /// share the same code actions cache state. - /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(CodeActionsHandler), typeof(CodeActionResolveHandler), typeof(RunCodeActionHandler)), Shared] - internal class CodeActionsHandlerProvider : IRequestHandlerProvider - { - private readonly ICodeFixService _codeFixService; - private readonly ICodeRefactoringService _codeRefactoringService; - private readonly IThreadingContext _threadingContext; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CodeActionsHandlerProvider( - ICodeFixService codeFixService, - ICodeRefactoringService codeRefactoringService, - IThreadingContext threadingContext, - IGlobalOptionService globalOptions) - { - _codeFixService = codeFixService; - _codeRefactoringService = codeRefactoringService; - _threadingContext = threadingContext; - _globalOptions = globalOptions; - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - var codeActionsCache = new CodeActionsCache(); - return ImmutableArray.Create( - new CodeActionsHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions), - new CodeActionResolveHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions), - new RunCodeActionHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions, _threadingContext)); - } - } -} diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs index 2529f8a318e1c..05a296035e172 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs @@ -2,6 +2,8 @@ // 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; @@ -9,6 +11,7 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands; using Microsoft.CodeAnalysis.Options; @@ -30,23 +33,23 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// UI thread dependencies are resolved and references are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// + [ExportRoslynStatelessLspService(typeof(RunCodeActionHandler)), Shared] [Command(CodeActionsHandler.RunCodeActionCommandName)] internal class RunCodeActionHandler : AbstractExecuteWorkspaceCommandHandler { - private readonly CodeActionsCache _codeActionsCache; private readonly ICodeFixService _codeFixService; private readonly ICodeRefactoringService _codeRefactoringService; private readonly IGlobalOptionService _globalOptions; private readonly IThreadingContext _threadingContext; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RunCodeActionHandler( - CodeActionsCache codeActionsCache, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IGlobalOptionService globalOptions, IThreadingContext threadingContext) { - _codeActionsCache = codeActionsCache; _codeFixService = codeFixService; _codeRefactoringService = codeRefactoringService; _globalOptions = globalOptions; @@ -76,8 +79,9 @@ public override async Task HandleRequestAsync(LSP.ExecuteCommandParams r var options = _globalOptions.GetCodeActionOptionsProvider(); + var codeActionsCache = context.GetRequiredLspService(); var codeActions = await CodeActionHelpers.GetCodeActionsAsync( - _codeActionsCache, document, runRequest.Range, options, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false); + codeActionsCache, document, runRequest.Range, options, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false); var actionToRun = CodeActionHelpers.GetCodeActionToResolve(runRequest.UniqueIdentifier, codeActions); Contract.ThrowIfNull(actionToRun); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs index 46a727cc3f799..c2978e1a667f4 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Composition; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -13,6 +14,7 @@ using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; @@ -31,6 +33,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// references to VS Icon types are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// + [ExportRoslynStatelessLspService(typeof(CompletionHandler)), Shared] [Method(LSP.Methods.TextDocumentCompletionName)] internal class CompletionHandler : IRequestHandler { @@ -40,15 +43,14 @@ internal class CompletionHandler : IRequestHandler _csharpTriggerCharacters; private readonly ImmutableHashSet _vbTriggerCharacters; - private readonly CompletionListCache _completionListCache; - public bool MutatesSolutionState => false; public bool RequiresLSPSolution => true; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CompletionHandler( IGlobalOptionService globalOptions, - IEnumerable> completionProviders, - CompletionListCache completionListCache) + [ImportMany] IEnumerable> completionProviders) { _globalOptions = globalOptions; @@ -56,8 +58,6 @@ public CompletionHandler( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet(); _vbTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.VisualBasic).SelectMany( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet(); - - _completionListCache = completionListCache; } public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.CompletionParams request) => request.TextDocument; @@ -84,7 +84,7 @@ public CompletionHandler( var completionService = document.GetRequiredLanguageService(); var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var completionListResult = await GetFilteredCompletionListAsync(request, documentText, document, completionOptions, completionService, cancellationToken).ConfigureAwait(false); + var completionListResult = await GetFilteredCompletionListAsync(request, context, documentText, document, completionOptions, completionService, cancellationToken).ConfigureAwait(false); if (completionListResult == null) { return null; @@ -375,6 +375,7 @@ static void PromoteCommonCommitCharactersOntoList(LSP.VSInternalCompletionList c private async Task<(CompletionList CompletionList, bool IsIncomplete, long ResultId)?> GetFilteredCompletionListAsync( LSP.CompletionParams request, + RequestContext context, SourceText sourceText, Document document, CompletionOptions completionOptions, @@ -385,6 +386,7 @@ static void PromoteCommonCommitCharactersOntoList(LSP.VSInternalCompletionList c var completionListSpan = completionService.GetDefaultCompletionListSpan(sourceText, position); var completionTrigger = await ProtocolConversions.LSPToRoslynCompletionTriggerAsync(request.Context, document, position, cancellationToken).ConfigureAwait(false); var isTriggerForIncompleteCompletions = request.Context?.TriggerKind == LSP.CompletionTriggerKind.TriggerForIncompleteCompletions; + var completionListCache = context.GetRequiredLspService(); (CompletionList List, long ResultId)? result; if (isTriggerForIncompleteCompletions) @@ -392,12 +394,12 @@ static void PromoteCommonCommitCharactersOntoList(LSP.VSInternalCompletionList c // We don't have access to the original trigger, but we know the completion list is already present. // It is safe to recompute with the invoked trigger as we will get all the items and filter down based on the current trigger. var originalTrigger = new CompletionTrigger(CompletionTriggerKind.Invoke); - result = await CalculateListAsync(request, document, position, originalTrigger, completionOptions, completionService, _completionListCache, cancellationToken).ConfigureAwait(false); + result = await CalculateListAsync(request, document, position, originalTrigger, completionOptions, completionService, completionListCache, cancellationToken).ConfigureAwait(false); } else { // This is a new completion request, clear out the last result Id for incomplete results. - result = await CalculateListAsync(request, document, position, completionTrigger, completionOptions, completionService, _completionListCache, cancellationToken).ConfigureAwait(false); + result = await CalculateListAsync(request, document, position, completionTrigger, completionOptions, completionService, completionListCache, cancellationToken).ConfigureAwait(false); } if (result == null) @@ -542,20 +544,6 @@ private static LSP.CompletionItemKind GetCompletionKind(ImmutableArray t return LSP.CompletionItemKind.Text; } - internal TestAccessor GetTestAccessor() - => new TestAccessor(this); - - internal readonly struct TestAccessor - { - private readonly CompletionHandler _completionHandler; - - public TestAccessor(CompletionHandler completionHandler) - => _completionHandler = completionHandler; - - public CompletionListCache GetCache() - => _completionHandler._completionListCache; - } - private class CommitCharacterArrayComparer : IEqualityComparer> { public static readonly CommitCharacterArrayComparer Instance = new(); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandlerProvider.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandlerProvider.cs deleted file mode 100644 index 22c652f152f96..0000000000000 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandlerProvider.cs +++ /dev/null @@ -1,41 +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.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.Completion.Providers; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(CompletionHandler), typeof(CompletionResolveHandler)), Shared] - internal class CompletionHandlerProvider : IRequestHandlerProvider - { - private readonly IEnumerable> _completionProviders; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CompletionHandlerProvider( - IGlobalOptionService globalOptions, - [ImportMany] IEnumerable> completionProviders) - { - _globalOptions = globalOptions; - _completionProviders = completionProviders; - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - var completionListCache = new CompletionListCache(); - return ImmutableArray.Create( - new CompletionHandler(_globalOptions, _completionProviders, completionListCache), - new CompletionResolveHandler(_globalOptions, completionListCache)); - } - } -} diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs index a459b1e16f59b..a4f542fbc2b5c 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs @@ -2,17 +2,32 @@ // 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.Completion; +using Microsoft.CodeAnalysis.Host.Mef; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion { + [ExportRoslynLspServiceFactory(typeof(CompletionListCache)), Shared] + internal class CompletionListCacheFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CompletionListCacheFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CompletionListCache(); + } + /// /// Caches completion lists in between calls to CompletionHandler and /// CompletionResolveHandler. Used to avoid unnecessary recomputation. /// - internal class CompletionListCache + internal class CompletionListCache : ILspService { /// /// Maximum number of completion lists allowed in cache. Must be >= 1. @@ -37,6 +52,7 @@ internal class CompletionListCache /// completion list. /// private readonly List _resultIdToCompletionList = new(); + #endregion /// diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs index 99fd0edef7d2c..3a92f57871948 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs @@ -3,10 +3,12 @@ // 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 Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.LanguageServices; @@ -18,6 +20,25 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { + [ExportRoslynLspServiceFactory(typeof(CompletionResolveHandler))] + internal sealed class CompletionResolveHandlerFactory : ILspServiceFactory + { + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CompletionResolveHandlerFactory(IGlobalOptionService globalOptions) + { + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + var completionListCache = lspServices.GetRequiredService(); + return new CompletionResolveHandler(_globalOptions, completionListCache); + } + } + /// /// Handle a completion resolve request to add description. /// @@ -49,6 +70,7 @@ public CompletionResolveHandler(IGlobalOptionService globalOptions, CompletionLi Contract.ThrowIfNull(document); var completionService = document.Project.LanguageServices.GetRequiredService(); + var cacheEntry = GetCompletionListCacheEntry(completionItem); if (cacheEntry == null) { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs index e0974a32da07b..e18b8f990b289 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs @@ -27,9 +27,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// no longer references VS icon or classified text run types. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(HoverHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(HoverHandler))] [Method(Methods.TextDocumentHoverName)] - internal sealed class HoverHandler : AbstractStatelessRequestHandler + internal sealed class HoverHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; @@ -40,12 +40,12 @@ public HoverHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs index f9b8ee6bffc5f..2cdbc671510b4 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs @@ -26,9 +26,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// we no longer reference VS classified text runs. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FindAllReferencesHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FindAllReferencesHandler)), Shared] [Method(LSP.Methods.TextDocumentReferencesName)] - internal class FindAllReferencesHandler : AbstractStatelessRequestHandler + internal class FindAllReferencesHandler : IRequestHandler { private readonly IMetadataAsSourceFileService _metadataAsSourceFileService; private readonly IAsynchronousOperationListener _asyncListener; @@ -46,12 +46,12 @@ public FindAllReferencesHandler( _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(ReferenceParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(ReferenceParams request) => request.TextDocument; - public override async Task HandleRequestAsync(ReferenceParams referenceParams, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(ReferenceParams referenceParams, RequestContext context, CancellationToken cancellationToken) { Debug.Assert(context.ClientCapabilities.HasVisualStudioLspCapability()); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs index 47c812558a823..dd9ea03f99695 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs @@ -15,9 +15,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FindImplementationsHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FindImplementationsHandler)), Shared] [Method(LSP.Methods.TextDocumentImplementationName)] - internal sealed class FindImplementationsHandler : AbstractStatelessRequestHandler + internal sealed class FindImplementationsHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; @@ -28,12 +28,12 @@ public FindImplementationsHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs index 1fe3f331c93ac..38d2b2eb604ce 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs @@ -22,9 +22,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// we no longer reference the /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(RenameHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(RenameHandler)), Shared] [Method(LSP.Methods.TextDocumentRenameName)] - internal class RenameHandler : AbstractStatelessRequestHandler + internal class RenameHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -32,12 +32,12 @@ public RenameHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(RenameParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(RenameParams request) => request.TextDocument; - public override async Task HandleRequestAsync(RenameParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(RenameParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs index 78c460b57bb50..4e72c2cd4590d 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs @@ -23,12 +23,12 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once /// we no longer reference VS icon types. /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DocumentSymbolsHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(DocumentSymbolsHandler)), Shared] [Method(Methods.TextDocumentDocumentSymbolName)] - internal class DocumentSymbolsHandler : AbstractStatelessRequestHandler + internal class DocumentSymbolsHandler : IRequestHandler { - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -36,9 +36,9 @@ public DocumentSymbolsHandler() { } - public override TextDocumentIdentifier GetTextDocumentIdentifier(DocumentSymbolParams request) => request.TextDocument; + public TextDocumentIdentifier GetTextDocumentIdentifier(DocumentSymbolParams request) => request.TextDocument; - public override async Task HandleRequestAsync(DocumentSymbolParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(DocumentSymbolParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs index e40947f5bb1f4..b99829c46bed5 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs @@ -20,9 +20,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once /// we no longer reference VS icon types. /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(WorkspaceSymbolsHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(WorkspaceSymbolsHandler)), Shared] [Method(Methods.WorkspaceSymbolName)] - internal class WorkspaceSymbolsHandler : AbstractStatelessRequestHandler + internal class WorkspaceSymbolsHandler : IRequestHandler { private static readonly IImmutableSet s_supportedKinds = ImmutableHashSet.Create( @@ -52,12 +52,12 @@ public WorkspaceSymbolsHandler( _threadingContext = threadingContext; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(WorkspaceSymbolParams request) => null; + public TextDocumentIdentifier? GetTextDocumentIdentifier(WorkspaceSymbolParams request) => null; - public override async Task HandleRequestAsync(WorkspaceSymbolParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(WorkspaceSymbolParams request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Solution); diff --git a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs index 231749f28b82f..2f679e4c633ff 100644 --- a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs @@ -30,14 +30,13 @@ internal class LiveShareInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public LiveShareInProcLanguageClient( - RequestDispatcherFactory csharpVBRequestDispatcherFactory, + RoslynLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, DefaultCapabilitiesProvider defaultCapabilitiesProvider, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs index 9aaec8682f691..7251d72755790 100644 --- a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs @@ -47,15 +47,14 @@ internal class RazorInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RazorInProcLanguageClient( - RequestDispatcherFactory csharpVBRequestDispatcherFactory, + RoslynLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, DefaultCapabilitiesProvider defaultCapabilitiesProvider, IThreadingContext threadingContext, ILspLoggerFactory lspLoggerFactory, [Import(AllowDefault = true)] AbstractLanguageClientMiddleLayer middleLayer) - : base(csharpVBRequestDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext, middleLayer) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext, middleLayer) { _defaultCapabilitiesProvider = defaultCapabilitiesProvider; } diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs index 3afeea0bb9836..d9fa7823cc898 100644 --- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs +++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs @@ -556,25 +556,18 @@ internal static async Task CreateAsync(TestWorkspace testWorkspac private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Stream outputStream, TestWorkspace workspace, WellKnownLspServerKinds serverKind) { - var dispatcherFactory = workspace.ExportProvider.GetExportedValue(); var listenerProvider = workspace.ExportProvider.GetExportedValue(); - var lspWorkspaceRegistrationService = workspace.ExportProvider.GetExportedValue(); var capabilitiesProvider = workspace.ExportProvider.GetExportedValue(); + var servicesProvider = workspace.ExportProvider.GetExportedValue(); var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, CreateJsonMessageFormatter())) { ExceptionStrategy = ExceptionProcessing.ISerializable, }; - var globalOptions = workspace.GetService(); - var languageServer = new LanguageServerTarget( - dispatcherFactory, - jsonRpc, + servicesProvider, jsonRpc, capabilitiesProvider, - lspWorkspaceRegistrationService, - new LspMiscellaneousFilesWorkspace(NoOpLspLogger.Instance), - globalOptions, listenerProvider, NoOpLspLogger.Instance, ProtocolConstants.RoslynLspLanguages, @@ -667,14 +660,16 @@ internal async Task WaitForDiagnosticsAsync() internal RequestExecutionQueue.TestAccessor GetQueueAccessor() => _languageServer.GetTestAccessor().GetQueueAccessor(); - internal RequestDispatcher.TestAccessor GetDispatcherAccessor() => _languageServer.GetTestAccessor().GetDispatcherAccessor(); - - internal LspWorkspaceManager.TestAccessor GetManagerAccessor() => _languageServer.GetTestAccessor().GetManagerAccessor(); + internal LspWorkspaceManager.TestAccessor GetManagerAccessor() => GetRequiredLspService().GetTestAccessor(); - internal LspWorkspaceManager GetManager() => _languageServer.GetTestAccessor().GetQueueAccessor().GetLspWorkspaceManager(); + internal LspWorkspaceManager GetManager() => GetRequiredLspService(); internal LanguageServerTarget.TestAccessor GetServerAccessor() => _languageServer.GetTestAccessor(); + internal T GetRequiredLspService() where T : class, ILspService => _languageServer.GetTestAccessor().GetRequiredLspService(); + + internal ImmutableArray GetTrackedTexts() => GetManager().GetTrackedLspText().Values.ToImmutableArray(); + public void Dispose() { // Some tests manually call shutdown, so avoid calling shutdown twice if already called. diff --git a/src/Features/LanguageServer/Protocol/AbstractRequestDispatcherFactory.cs b/src/Features/LanguageServer/Protocol/AbstractRequestDispatcherFactory.cs deleted file mode 100644 index 770835761aba8..0000000000000 --- a/src/Features/LanguageServer/Protocol/AbstractRequestDispatcherFactory.cs +++ /dev/null @@ -1,33 +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.Collections.Immutable; -using Microsoft.CodeAnalysis.LanguageServer.Handler; - -namespace Microsoft.CodeAnalysis.LanguageServer -{ - /// - /// Factory to handle creation of the - /// - internal abstract class AbstractRequestDispatcherFactory - { - protected readonly ImmutableArray> _requestHandlerProviders; - - protected AbstractRequestDispatcherFactory(IEnumerable> requestHandlerProviders) - { - _requestHandlerProviders = requestHandlerProviders.ToImmutableArray(); - } - - /// - /// Creates a new request dispatcher every time to ensure handlers are not shared - /// and cleaned up appropriately on server restart. - /// - public virtual RequestDispatcher CreateRequestDispatcher(WellKnownLspServerKinds serverKind) - { - return new RequestDispatcher(_requestHandlerProviders, serverKind); - } - } -} diff --git a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs index c7acd08270e6b..171f9a2100b58 100644 --- a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs +++ b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs @@ -15,23 +15,17 @@ namespace Microsoft.CodeAnalysis.LanguageServer [Export(typeof(ILanguageServerFactory)), Shared] internal class CSharpVisualBasicLanguageServerFactory : ILanguageServerFactory { - private readonly RequestDispatcherFactory _dispatcherFactory; - private readonly LspWorkspaceRegistrationService _lspWorkspaceRegistrationService; + private readonly AbstractLspServiceProvider _lspServiceProvider; private readonly IAsynchronousOperationListenerProvider _listenerProvider; - private readonly IGlobalOptionService _globalOptions; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CSharpVisualBasicLanguageServerFactory( - RequestDispatcherFactory dispatcherFactory, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, - IAsynchronousOperationListenerProvider listenerProvider, - IGlobalOptionService globalOptions) + RoslynLspServiceProvider lspServiceProvider, + IAsynchronousOperationListenerProvider listenerProvider) { - _dispatcherFactory = dispatcherFactory; - _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; + _lspServiceProvider = lspServiceProvider; _listenerProvider = listenerProvider; - _globalOptions = globalOptions; } public ILanguageServerTarget Create( @@ -39,15 +33,9 @@ public ILanguageServerTarget Create( ICapabilitiesProvider capabilitiesProvider, ILspLogger logger) { - var lspMiscellaneousFilesWorkspace = new LspMiscellaneousFilesWorkspace(logger); - return new LanguageServerTarget( - _dispatcherFactory, - jsonRpc, + _lspServiceProvider, jsonRpc, capabilitiesProvider, - _lspWorkspaceRegistrationService, - lspMiscellaneousFilesWorkspace, - _globalOptions, _listenerProvider, logger, ProtocolConstants.RoslynLspLanguages, diff --git a/src/Features/LanguageServer/Protocol/Handler/AbstractRequestHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/AbstractRequestHandlerProvider.cs deleted file mode 100644 index b89de95ac5ad2..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/AbstractRequestHandlerProvider.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.Collections.Immutable; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - /// - /// Defines a provider to create instances of . - /// New handler instances are created for each LSP server and re-created whenever the - /// server restarts. - /// - /// Each can create multiple - /// instances in order to share state between different LSP methods. - /// E.g. completion requests can share a cache with completion resolve requests for the same LSP server. - /// - internal interface IRequestHandlerProvider - { - /// - /// Instantiates new handler instances and returns them. - /// - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind); - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/AbstractStatelessRequestHandler.cs b/src/Features/LanguageServer/Protocol/Handler/AbstractStatelessRequestHandler.cs deleted file mode 100644 index afc02125fa503..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/AbstractStatelessRequestHandler.cs +++ /dev/null @@ -1,30 +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.Collections.Immutable; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - /// - /// Defines a request handler that saves no state between LSP requests. - /// This means that the handler can be shared between multiple servers - /// and does not need to be re-instantiated on server restarts. - /// - internal abstract class AbstractStatelessRequestHandler : IRequestHandlerProvider, IRequestHandler - { - public abstract bool MutatesSolutionState { get; } - public abstract bool RequiresLSPSolution { get; } - - public abstract TextDocumentIdentifier? GetTextDocumentIdentifier(RequestType request); - public abstract Task HandleRequestAsync(RequestType request, RequestContext context, CancellationToken cancellationToken); - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return ImmutableArray.Create(this); - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs index 7aea8d87d805a..ac7a9cc2c4dd8 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs @@ -15,9 +15,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(ValidateBreakableRangeHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(ValidateBreakableRangeHandler)), Shared] [Method(LSP.VSInternalMethods.TextDocumentValidateBreakableRangeName)] - internal sealed class ValidateBreakableRangeHandler : AbstractStatelessRequestHandler + internal sealed class ValidateBreakableRangeHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -25,13 +25,13 @@ public ValidateBreakableRangeHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.VSInternalValidateBreakableRangeParams request) + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.VSInternalValidateBreakableRangeParams request) => request.TextDocument; - public override async Task HandleRequestAsync(LSP.VSInternalValidateBreakableRangeParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(LSP.VSInternalValidateBreakableRangeParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs index 27109a471f4a8..11636129c02ed 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs @@ -13,11 +13,12 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.VisualStudio.LanguageServer.Protocol; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - internal abstract class AbstractGoToDefinitionHandler : AbstractStatelessRequestHandler + internal abstract class AbstractGoToDefinitionHandler : IRequestHandler { private readonly IMetadataAsSourceFileService _metadataAsSourceFileService; private readonly IGlobalOptionService _globalOptions; @@ -28,10 +29,12 @@ public AbstractGoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSour _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; + + public abstract Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken); protected async Task GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, RequestContext context, CancellationToken cancellationToken) { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs index 6c049f47252ba..ffb5d1e93bedc 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(GoToDefinitionHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(GoToDefinitionHandler)), Shared] [Method(LSP.Methods.TextDocumentDefinitionName)] internal class GoToDefinitionHandler : AbstractGoToDefinitionHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs index c0d74cde9e25f..69ceae10af33f 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(GoToTypeDefinitionHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(GoToTypeDefinitionHandler)), Shared] [Method(LSP.Methods.TextDocumentTypeDefinitionName)] internal class GoToTypeDefinitionHandler : AbstractGoToDefinitionHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs index 610d7540abb16..256a54ab812a9 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs @@ -46,6 +46,7 @@ internal abstract class AbstractPullDiagnosticHandler ComputeAndReportCurrentDiagnosticsAsync( _ => InternalDiagnosticsOptions.NormalDiagnosticMode, }; - var diagnosticMode = context.GlobalOptions.GetDiagnosticMode(diagnosticModeOption); + var diagnosticMode = _globalOptions.GetDiagnosticMode(diagnosticModeOption); var isPull = diagnosticMode == DiagnosticMode.Pull; context.TraceInformation($"Getting '{(isPull ? "pull" : "push")}' diagnostics with mode '{diagnosticMode}'"); diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs index 2ddf9d4fddd12..63eec018090bb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Immutable; +using System.Composition; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -15,6 +17,32 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { + [ExportRoslynLspServiceFactory(typeof(DocumentPullDiagnosticHandler)), Shared] + internal class DocumentPullDiagnosticHandlerFactory : ILspServiceFactory + { + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public DocumentPullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new DocumentPullDiagnosticHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); + } + [Method(VSInternalMethods.DocumentPullDiagnosticName)] internal class DocumentPullDiagnosticHandler : AbstractPullDiagnosticHandler { @@ -23,8 +51,9 @@ internal class DocumentPullDiagnosticHandler : AbstractPullDiagnosticHandler CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return ImmutableArray.Create(new ExperimentalDocumentPullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs index 313ee433ca8df..3c8efaa3dd733 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Immutable; +using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Utilities; @@ -22,6 +24,32 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental // See https://github.com/microsoft/vscode-languageserver-node/blob/main/protocol/src/common/proposed.diagnostics.md#textDocument_diagnostic using DocumentDiagnosticPartialReport = SumType, DocumentDiagnosticPartialResult>; +[ExportRoslynLspServiceFactory(typeof(ExperimentalDocumentPullDiagnosticsHandler)), Shared] +internal class ExperimentalDocumentPullDiagnosticHandlerFactory : ILspServiceFactory +{ + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ExperimentalDocumentPullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new ExperimentalDocumentPullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); +} + [Method(ExperimentalMethods.TextDocumentDiagnostic)] internal class ExperimentalDocumentPullDiagnosticsHandler : AbstractPullDiagnosticHandler { @@ -30,8 +58,9 @@ internal class ExperimentalDocumentPullDiagnosticsHandler : AbstractPullDiagnost public ExperimentalDocumentPullDiagnosticsHandler( IDiagnosticService diagnosticService, IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(diagnosticService, editAndContinueDiagnosticUpdateSource) + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource, globalOptions) { _analyzerService = analyzerService; } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs deleted file mode 100644 index e6d254afc8675..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerProvider.cs +++ /dev/null @@ -1,37 +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.Composition; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.EditAndContinue; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental; - -[ExportRoslynLanguagesLspRequestHandlerProvider(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] -internal class ExperimentalWorkspacePullDiagnosticHandlerProvider : IRequestHandlerProvider -{ - private readonly IDiagnosticService _diagnosticService; - private readonly IDiagnosticAnalyzerService _analyzerService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ExperimentalWorkspacePullDiagnosticHandlerProvider( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - { - _diagnosticService = diagnosticService; - _analyzerService = analyzerService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return ImmutableArray.Create(new ExperimentalWorkspacePullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource)); - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs index 0b3b5a89572df..16fc41073f905 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs @@ -4,12 +4,14 @@ using System; using System.Collections.Immutable; +using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -17,6 +19,32 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental using WorkspaceDocumentDiagnosticReport = SumType; +[ExportRoslynLspServiceFactory(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] +internal class ExperimentalWorkspacePullDiagnosticHandlerFactory : ILspServiceFactory +{ + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ExperimentalWorkspacePullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new ExperimentalWorkspacePullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); +} + [Method(ExperimentalMethods.WorkspaceDiagnostic)] internal class ExperimentalWorkspacePullDiagnosticsHandler : AbstractPullDiagnosticHandler { @@ -25,8 +53,9 @@ internal class ExperimentalWorkspacePullDiagnosticsHandler : AbstractPullDiagnos public ExperimentalWorkspacePullDiagnosticsHandler( IDiagnosticService diagnosticService, IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(diagnosticService, editAndContinueDiagnosticUpdateSource) + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource, globalOptions) { _analyzerService = analyzerService; } diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs deleted file mode 100644 index 5b3841aff441a..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/PullDiagnosticHandlerProvider.cs +++ /dev/null @@ -1,41 +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.Composition; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.EditAndContinue; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics -{ - [Shared] - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DocumentPullDiagnosticHandler), typeof(WorkspacePullDiagnosticHandler))] - internal class PullDiagnosticHandlerProvider : IRequestHandlerProvider - { - private readonly IDiagnosticService _diagnosticService; - private readonly IDiagnosticAnalyzerService _analyzerService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public PullDiagnosticHandlerProvider( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - { - _diagnosticService = diagnosticService; - _analyzerService = analyzerService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return ImmutableArray.Create( - new DocumentPullDiagnosticHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource), - new WorkspacePullDiagnosticHandler(_diagnosticService, _editAndContinueDiagnosticUpdateSource)); - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs index fbb96641c73c7..f4104b7f1c72c 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs @@ -2,7 +2,9 @@ // 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.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -10,6 +12,7 @@ using Microsoft.CodeAnalysis.EditAndContinue; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.SolutionCrawler; @@ -18,11 +21,34 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { + [ExportRoslynLspServiceFactory(typeof(WorkspacePullDiagnosticHandler)), Shared] + internal class WorkspacePullDiagnosticHandlerFactory : ILspServiceFactory + { + private readonly IDiagnosticService _diagnosticService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspacePullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new WorkspacePullDiagnosticHandler(_diagnosticService, _editAndContinueDiagnosticUpdateSource, _globalOptions); + } + [Method(VSInternalMethods.WorkspacePullDiagnosticName)] - internal class WorkspacePullDiagnosticHandler : AbstractPullDiagnosticHandler + internal sealed class WorkspacePullDiagnosticHandler : AbstractPullDiagnosticHandler { - public WorkspacePullDiagnosticHandler(IDiagnosticService diagnosticService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource) - : base(diagnosticService, editAndContinueDiagnosticUpdateSource) + public WorkspacePullDiagnosticHandler(IDiagnosticService diagnosticService, EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, IGlobalOptionService globalOptions) + : base(diagnosticService, editAndContinueDiagnosticUpdateSource, globalOptions) { } diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs index edd50acb7fcc2..4e2a4c78a5908 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs @@ -13,9 +13,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DidChangeHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(DidChangeHandler)), Shared] [Method(LSP.Methods.TextDocumentDidChangeName)] - internal class DidChangeHandler : AbstractStatelessRequestHandler + internal class DidChangeHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -23,12 +23,12 @@ public DidChangeHandler() { } - public override bool MutatesSolutionState => true; - public override bool RequiresLSPSolution => false; + public bool MutatesSolutionState => true; + public bool RequiresLSPSolution => false; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidChangeTextDocumentParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidChangeTextDocumentParams request) => request.TextDocument; - public override Task HandleRequestAsync(LSP.DidChangeTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(LSP.DidChangeTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) { var text = context.GetTrackedDocumentSourceText(request.TextDocument.Uri); diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs index c9b073e199aad..9b8cb9042faec 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs @@ -12,9 +12,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DidCloseHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(DidCloseHandler)), Shared] [Method(LSP.Methods.TextDocumentDidCloseName)] - internal class DidCloseHandler : AbstractStatelessRequestHandler + internal class DidCloseHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -22,12 +22,12 @@ public DidCloseHandler() { } - public override bool MutatesSolutionState => true; - public override bool RequiresLSPSolution => false; + public bool MutatesSolutionState => true; + public bool RequiresLSPSolution => false; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidCloseTextDocumentParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidCloseTextDocumentParams request) => request.TextDocument; - public override Task HandleRequestAsync(LSP.DidCloseTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(LSP.DidCloseTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) { // GetTextDocumentIdentifier returns null to avoid creating the solution, so the queue is not able to log the uri. context.TraceInformation($"didClose for {request.TextDocument.Uri}"); diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs index 540c79b492e63..021a8df690f7b 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs @@ -13,9 +13,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DidOpenHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(DidOpenHandler)), Shared] [Method(LSP.Methods.TextDocumentDidOpenName)] - internal class DidOpenHandler : AbstractStatelessRequestHandler + internal class DidOpenHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -23,12 +23,12 @@ public DidOpenHandler() { } - public override bool MutatesSolutionState => true; - public override bool RequiresLSPSolution => false; + public bool MutatesSolutionState => true; + public bool RequiresLSPSolution => false; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidOpenTextDocumentParams request) => new() { Uri = request.TextDocument.Uri }; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DidOpenTextDocumentParams request) => new() { Uri = request.TextDocument.Uri }; - public override Task HandleRequestAsync(LSP.DidOpenTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(LSP.DidOpenTextDocumentParams request, RequestContext context, CancellationToken cancellationToken) { // GetTextDocumentIdentifier returns null to avoid creating the solution, so the queue is not able to log the uri. context.TraceInformation($"didOpen for {request.TextDocument.Uri}"); diff --git a/src/Features/LanguageServer/Protocol/Handler/ExportLspRequestHandlerProviderAttribute.cs b/src/Features/LanguageServer/Protocol/Handler/ExportLspRequestHandlerProviderAttribute.cs deleted file mode 100644 index d97d32a2988df..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/ExportLspRequestHandlerProviderAttribute.cs +++ /dev/null @@ -1,56 +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.Composition; -using System.Linq; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - /// - /// Defines an attribute used to export instances of . - /// We specifically disallow multiple as a provider should only provide handlers for a single contract. - /// If we exported the same provider for multiple contracts, we would not be able to tell which handlers are associated with which contract. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] - internal class ExportLspRequestHandlerProviderAttribute : ExportAttribute - { - public Type[] HandlerTypes { get; } - - /// - /// Exports an and specifies the contract and - /// types this provider is associated with. - /// - /// - /// The contract name this provider is exported. Used by - /// when importing handlers to ensure that it only imports handlers that match this contract. - /// This is important to ensure that we only load relevant providers (e.g. don't load Xaml providers when creating the c# server), - /// otherwise we will get dll load RPS regressions for the - /// - /// - /// The concrete type of the provided in - /// - /// - /// Additional if - /// provides more than one handler at once. - /// - public ExportLspRequestHandlerProviderAttribute(string contractName, Type firstHandlerType, params Type[] additionalHandlerTypes) : base(contractName, typeof(IRequestHandlerProvider)) - { - HandlerTypes = additionalHandlerTypes.Concat(new[] { firstHandlerType }).ToArray(); - } - } - - /// - /// Defines an easy to use subclass for ExportLspRequestHandlerProviderAttribute with the roslyn languages contract name. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] - internal class ExportRoslynLanguagesLspRequestHandlerProviderAttribute : ExportLspRequestHandlerProviderAttribute - { - public ExportRoslynLanguagesLspRequestHandlerProviderAttribute(Type firstHandlerType, params Type[] additionalHandlerTypes) : base(ProtocolConstants.RoslynLspLanguagesContract, firstHandlerType, additionalHandlerTypes) - { - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs index 60256349ba9c0..8a500d340b725 100644 --- a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs @@ -16,14 +16,14 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FoldingRangesHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FoldingRangesHandler)), Shared] [Method(Methods.TextDocumentFoldingRangeName)] - internal sealed class FoldingRangesHandler : AbstractStatelessRequestHandler + internal sealed class FoldingRangesHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -32,9 +32,9 @@ public FoldingRangesHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override TextDocumentIdentifier? GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; - public override async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs index d68f12a94be88..fefd619a35bb3 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs @@ -12,15 +12,16 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - internal abstract class AbstractFormatDocumentHandlerBase : AbstractStatelessRequestHandler + internal abstract class AbstractFormatDocumentHandlerBase : IRequestHandler { - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; protected static async Task GetTextEditsAsync( RequestContext context, @@ -49,5 +50,8 @@ internal abstract class AbstractFormatDocumentHandlerBase ProtocolConversions.TextChangeToTextEdit(change, text))); return edits.ToArrayAndFree(); } + + public abstract TextDocumentIdentifier? GetTextDocumentIdentifier(RequestType request); + public abstract Task HandleRequestAsync(RequestType request, RequestContext context, CancellationToken cancellationToken); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs index ead76c293eace..6d0442bb2e737 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FormatDocumentHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FormatDocumentHandler)), Shared] [Method(LSP.Methods.TextDocumentFormattingName)] internal sealed class FormatDocumentHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index d199238e85ad6..5920431812008 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -21,14 +21,14 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FormatDocumentOnTypeHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FormatDocumentOnTypeHandler)), Shared] [Method(Methods.TextDocumentOnTypeFormattingName)] - internal sealed class FormatDocumentOnTypeHandler : AbstractStatelessRequestHandler + internal sealed class FormatDocumentOnTypeHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -37,9 +37,9 @@ public FormatDocumentOnTypeHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentOnTypeFormattingParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentOnTypeFormattingParams request) => request.TextDocument; - public override async Task HandleRequestAsync( + public async Task HandleRequestAsync( DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken) diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs index 5ce135c8bbaaf..a847db0cef1df 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FormatDocumentRangeHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(FormatDocumentRangeHandler)), Shared] [Method(Methods.TextDocumentRangeFormattingName)] internal sealed class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs index fa811dc17296f..5ccaf6ae9265c 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs @@ -20,9 +20,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DocumentHighlightsHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(DocumentHighlightsHandler)), Shared] [Method(Methods.TextDocumentDocumentHighlightName)] - internal class DocumentHighlightsHandler : AbstractStatelessRequestHandler + internal class DocumentHighlightsHandler : IRequestHandler { private readonly IHighlightingService _highlightingService; private readonly IGlobalOptionService _globalOptions; @@ -35,12 +35,12 @@ public DocumentHighlightsHandler(IHighlightingService highlightingService, IGlob _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs b/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs new file mode 100644 index 0000000000000..e692e2b796bae --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs @@ -0,0 +1,37 @@ +// 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 Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; +/// +/// Associates LSP document URIs with the roslyn source text containing the LSP document text. +/// Called via , and +/// +internal interface IDocumentChangeTracker +{ + void StartTracking(Uri documentUri, SourceText initialText); + void UpdateTrackedDocument(Uri documentUri, SourceText text); + void StopTracking(Uri documentUri); +} + +internal class NonMutatingDocumentChangeTracker : IDocumentChangeTracker +{ + public void StartTracking(Uri documentUri, SourceText initialText) + { + throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); + } + + public void StopTracking(Uri documentUri) + { + throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); + } + + public void UpdateTrackedDocument(Uri documentUri, SourceText text) + { + throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/IRequestHandler.cs b/src/Features/LanguageServer/Protocol/Handler/IRequestHandler.cs index 987800742759b..b7787edf04728 100644 --- a/src/Features/LanguageServer/Protocol/Handler/IRequestHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/IRequestHandler.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// /// Top level type for LSP request handler. /// - internal interface IRequestHandler + internal interface IRequestHandler : ILspService { /// /// Whether or not the solution state on the server is modified diff --git a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs index e070d253df8a4..38f93116e5ece 100644 --- a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs @@ -29,9 +29,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.InlineCompletions; /// /// Supports built in legacy snippets for razor scenarios. /// -[ExportRoslynLanguagesLspRequestHandlerProvider(typeof(InlineCompletionsHandler)), Shared] +[ExportRoslynStatelessLspService(typeof(InlineCompletionsHandler)), Shared] [Method(VSInternalMethods.TextDocumentInlineCompletionName)] -internal partial class InlineCompletionsHandler : AbstractStatelessRequestHandler +internal partial class InlineCompletionsHandler : IRequestHandler { /// /// The set of built in snippets from, typically found in @@ -46,9 +46,9 @@ internal partial class InlineCompletionsHandler : AbstractStatelessRequestHandle private readonly XmlSnippetParser _xmlSnippetParser; private readonly IGlobalOptionService _globalOptions; - public override bool MutatesSolutionState => false; + public bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -58,12 +58,12 @@ public InlineCompletionsHandler(XmlSnippetParser xmlSnippetParser, IGlobalOption _globalOptions = globalOptions; } - public override TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalInlineCompletionRequest request) + public TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalInlineCompletionRequest request) { return request.TextDocument; } - public override async Task HandleRequestAsync(VSInternalInlineCompletionRequest request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(VSInternalInlineCompletionRequest request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Document); diff --git a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs index b1b32520cf8f1..de89bc83e80c4 100644 --- a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -24,16 +24,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(OnAutoInsertHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(OnAutoInsertHandler)), Shared] [Method(LSP.VSInternalMethods.OnAutoInsertName)] - internal sealed class OnAutoInsertHandler : AbstractStatelessRequestHandler + internal sealed class OnAutoInsertHandler : IRequestHandler { private readonly ImmutableArray _csharpBraceCompletionServices; private readonly ImmutableArray _visualBasicBraceCompletionServices; private readonly IGlobalOptionService _globalOptions; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -47,9 +47,9 @@ public OnAutoInsertHandler( _globalOptions = globalOptions; } - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.VSInternalDocumentOnAutoInsertParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.VSInternalDocumentOnAutoInsertParams request) => request.TextDocument; - public override async Task HandleRequestAsync( + public async Task HandleRequestAsync( LSP.VSInternalDocumentOnAutoInsertParams request, RequestContext context, CancellationToken cancellationToken) diff --git a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs index b3861712e345f..d1d5929fd08f7 100644 --- a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs @@ -15,9 +15,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(GetTextDocumentWithContextHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(GetTextDocumentWithContextHandler)), Shared] [Method(VSMethods.GetProjectContextsName)] - internal class GetTextDocumentWithContextHandler : AbstractStatelessRequestHandler + internal class GetTextDocumentWithContextHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -25,12 +25,12 @@ public GetTextDocumentWithContextHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(VSGetProjectContextsParams request) => new TextDocumentIdentifier { Uri = request.TextDocument.Uri }; + public TextDocumentIdentifier? GetTextDocumentIdentifier(VSGetProjectContextsParams request) => new TextDocumentIdentifier { Uri = request.TextDocument.Uri }; - public override Task HandleRequestAsync(VSGetProjectContextsParams request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(VSGetProjectContextsParams request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Solution); diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs index f2173207a33d6..ed6a69ec59a6b 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs @@ -34,6 +34,8 @@ internal readonly struct RequestContext /// private readonly ImmutableDictionary _trackedDocuments; + private readonly LspServices _lspServices; + /// /// The solution state that the request should operate on, if the handler requires an LSP solution, or otherwise /// @@ -59,9 +61,6 @@ internal readonly struct RequestContext /// public readonly ImmutableArray SupportedLanguages; - public readonly IGlobalOptionService GlobalOptions; - - public readonly ILanguageServerNotificationManager NotificationManager; public readonly CancellationToken QueueCancellationToken; /// @@ -78,8 +77,7 @@ public RequestContext( IDocumentChangeTracker documentChangeTracker, ImmutableDictionary trackedDocuments, ImmutableArray supportedLanguages, - IGlobalOptionService globalOptions, - ILanguageServerNotificationManager notificationManager, + LspServices lspServices, CancellationToken queueCancellationToken) { Document = document; @@ -87,28 +85,28 @@ public RequestContext( ClientCapabilities = clientCapabilities; ServerKind = serverKind; SupportedLanguages = supportedLanguages; - GlobalOptions = globalOptions; _documentChangeTracker = documentChangeTracker; _logger = logger; _trackedDocuments = trackedDocuments; - NotificationManager = notificationManager; + _lspServices = lspServices; QueueCancellationToken = queueCancellationToken; } public static async Task CreateAsync( bool requiresLSPSolution, + bool mutatesSolutionState, TextDocumentIdentifier? textDocument, WellKnownLspServerKinds serverKind, - ILspLogger logger, ClientCapabilities clientCapabilities, - LspWorkspaceManager lspWorkspaceManager, - ILanguageServerNotificationManager notificationManager, - IDocumentChangeTracker documentChangeTracker, ImmutableArray supportedLanguages, - IGlobalOptionService globalOptions, + LspServices lspServices, CancellationToken queueCancellationToken, CancellationToken requestCancellationToken) { + var lspWorkspaceManager = lspServices.GetRequiredService(); + var logger = lspServices.GetRequiredService(); + var documentChangeTracker = mutatesSolutionState ? (IDocumentChangeTracker)lspWorkspaceManager : new NonMutatingDocumentChangeTracker(); + // Retrieve the current LSP tracked text as of this request. // This is safe as all creation of request contexts cannot happen concurrently. var trackedDocuments = lspWorkspaceManager.GetTrackedLspText(); @@ -121,8 +119,8 @@ public RequestContext( { return new RequestContext( solution: null, logger: logger, clientCapabilities: clientCapabilities, serverKind: serverKind, document: null, - documentChangeTracker: documentChangeTracker, trackedDocuments: trackedDocuments, supportedLanguages: supportedLanguages, globalOptions: globalOptions, - notificationManager: notificationManager, queueCancellationToken: queueCancellationToken); + documentChangeTracker: documentChangeTracker, trackedDocuments: trackedDocuments, supportedLanguages: supportedLanguages, lspServices: lspServices, + queueCancellationToken: queueCancellationToken); } Solution? workspaceSolution; @@ -152,8 +150,7 @@ public RequestContext( documentChangeTracker, trackedDocuments, supportedLanguages, - globalOptions, - notificationManager, + lspServices, queueCancellationToken); return context; } @@ -202,5 +199,10 @@ public void TraceError(string message) public void TraceException(Exception exception) => _logger.TraceException(exception); + + public T GetRequiredLspService() where T : class, ILspService + { + return _lspServices.GetRequiredService(); + } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs deleted file mode 100644 index 3d041a4608d6a..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs +++ /dev/null @@ -1,89 +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.Collections.Immutable; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - internal partial class RequestExecutionQueue - { - /// - /// Associates LSP document URIs with the roslyn source text containing the LSP document text. - /// Called via , and - /// - internal interface IDocumentChangeTracker - { - void StartTracking(Uri documentUri, SourceText initialText); - void UpdateTrackedDocument(Uri documentUri, SourceText text); - void StopTracking(Uri documentUri); - } - - private class NonMutatingDocumentChangeTracker : IDocumentChangeTracker - { - public void StartTracking(Uri documentUri, SourceText initialText) - { - throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); - } - - public void StopTracking(Uri documentUri) - { - throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); - } - - public void UpdateTrackedDocument(Uri documentUri, SourceText text) - { - throw new InvalidOperationException("Mutating documents not allowed in a non-mutating request handler"); - } - } - - internal TestAccessor GetTestAccessor() - => new TestAccessor(this); - - internal readonly struct TestAccessor - { - private readonly RequestExecutionQueue _queue; - - public TestAccessor(RequestExecutionQueue queue) - => _queue = queue; - - public ImmutableArray GetTrackedTexts() - => _queue._lspWorkspaceManager.GetTrackedLspText().Select(i => i.Value).ToImmutableArray(); - - public LspWorkspaceManager GetLspWorkspaceManager() => _queue._lspWorkspaceManager; - - public bool IsComplete() => _queue._queue.IsCompleted && _queue._queue.IsEmpty; - - public async Task WaitForProcessingToStopAsync() - { - await _queue._queueProcessingTask.ConfigureAwait(false); - } - - /// - /// Test only method to validate that remaining items in the queue are cancelled. - /// This directly mutates the queue in an unsafe way, so ensure that all relevant queue operations - /// are done before calling. - /// - public async Task AreAllItemsCancelledUnsafeAsync() - { - while (!_queue._queue.IsEmpty) - { - var (_, cancellationToken) = await _queue._queue.DequeueAsync().ConfigureAwait(false); - if (!cancellationToken.IsCancellationRequested) - { - return false; - } - } - - return true; - } - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs index 756af21c38e94..e08fc12b784d6 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs @@ -114,7 +114,7 @@ public static (IQueueItem, Task) Create( IRequestHandler handler, Guid activityId, ILspLogger logger, - RequestTelemetryLogger telemetryLogger, + LspServices lspServices, CancellationToken cancellationToken) { var queueItem = new QueueItem( @@ -127,7 +127,7 @@ public static (IQueueItem, Task) Create( handler, activityId, logger, - telemetryLogger, + lspServices.GetRequiredService(), cancellationToken); return (queueItem, queueItem._completionSource.Task); diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.RequestTelemetryLogger.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.RequestTelemetryLogger.cs deleted file mode 100644 index f28f6fdff17d6..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.RequestTelemetryLogger.cs +++ /dev/null @@ -1,213 +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.Concurrent; -using System.Threading; -using Microsoft.CodeAnalysis.Internal.Log; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - internal partial class RequestExecutionQueue - { - /// - /// Logs metadata on LSP requests (duration, success / failure metrics) - /// for this particular LSP server instance. - /// - internal sealed class RequestTelemetryLogger : IDisposable - { - private const string QueuedDurationKey = "QueuedDuration"; - - private readonly string _serverTypeName; - - /// - /// Histogram to aggregate the time in queue metrics. - /// - private readonly HistogramLogAggregator _queuedDurationLogAggregator; - - /// - /// Histogram to aggregate total request duration metrics. - /// This histogram is log based as request latencies can be highly variable depending - /// on the request being handled. As such, we apply the log based function - /// defined by ComputeLogValue to the request latencies for storing in the histogram. - /// This provides highly detailed buckets when duration is in MS, but less detailed - /// when the duration is in terms of seconds or minutes. - /// - private readonly HistogramLogAggregator _requestDurationLogAggregator; - - /// - /// Store request counters in a concurrent dictionary as non-mutating LSP requests can - /// run alongside other non-mutating requests. - /// - private readonly ConcurrentDictionary _requestCounters; - - private readonly LogAggregator _findDocumentResults; - - private readonly LogAggregator _usedForkedSolutionCounter; - - private int _disposed; - - public RequestTelemetryLogger(string serverTypeName) - { - _serverTypeName = serverTypeName; - _requestCounters = new(); - _findDocumentResults = new(); - _usedForkedSolutionCounter = new(); - - // Buckets queued duration into 10ms buckets with the last bucket starting at 1000ms. - // Queue times are relatively short and fall under 50ms, so tracking past 1000ms is not useful. - _queuedDurationLogAggregator = new HistogramLogAggregator(bucketSize: 10, maxBucketValue: 1000); - - // Since this is a log based histogram, these are appropriate bucket sizes for the log data. - // A bucket at 1 corresponds to ~26ms, while the max bucket value corresponds to ~17minutes - _requestDurationLogAggregator = new HistogramLogAggregator(bucketSize: 1, maxBucketValue: 40); - } - - public void UpdateFindDocumentTelemetryData(bool success, string? workspaceKind) - { - var workspaceKindTelemetryProperty = success ? workspaceKind : "Failed"; - - if (workspaceKindTelemetryProperty != null) - { - _findDocumentResults.IncreaseCount(workspaceKindTelemetryProperty); - } - } - - public void UpdateUsedForkedSolutionCounter(bool usedForkedSolution) - { - _usedForkedSolutionCounter.IncreaseCount(usedForkedSolution); - } - - public void UpdateTelemetryData( - string methodName, - TimeSpan queuedDuration, - TimeSpan requestDuration, - Result result) - { - // Find the bucket corresponding to the queued duration and update the count of durations in that bucket. - // This is not broken down per method as time in queue is not specific to an LSP method. - _queuedDurationLogAggregator.IncreaseCount(QueuedDurationKey, Convert.ToDecimal(queuedDuration.TotalMilliseconds)); - - // Store the request time metrics per LSP method. - _requestDurationLogAggregator.IncreaseCount(methodName, Convert.ToDecimal(ComputeLogValue(requestDuration.TotalMilliseconds))); - _requestCounters.GetOrAdd(methodName, (_) => new Counter()).IncrementCount(result); - } - - /// - /// Given an input duration in MS, this transforms it using - /// the log function below to put in reasonable log based buckets - /// from 50ms to 1 hour. Similar transformations must be done to read - /// the data from kusto. - /// - private static double ComputeLogValue(double durationInMS) - { - return 10d * Math.Log10((durationInMS / 100d) + 1); - } - - /// - /// Only output aggregate telemetry to the vs logger when the server instance is disposed - /// to avoid spamming the telemetry output with thousands of events - /// - public void Dispose() - { - if (Interlocked.Exchange(ref _disposed, 1) != 0) - { - return; - } - - if (_queuedDurationLogAggregator.IsEmpty || _requestDurationLogAggregator.IsEmpty) - { - return; - } - - var queuedDurationCounter = _queuedDurationLogAggregator.GetValue(QueuedDurationKey); - Logger.Log(FunctionId.LSP_TimeInQueue, KeyValueLogMessage.Create(LogType.Trace, m => - { - m["server"] = _serverTypeName; - m["bucketsize_ms"] = queuedDurationCounter?.BucketSize; - m["maxbucketvalue_ms"] = queuedDurationCounter?.MaxBucketValue; - m["buckets"] = queuedDurationCounter?.GetBucketsAsString(); - })); - - foreach (var kvp in _requestCounters) - { - Logger.Log(FunctionId.LSP_RequestCounter, KeyValueLogMessage.Create(LogType.Trace, m => - { - m["server"] = _serverTypeName; - m["method"] = kvp.Key; - m["successful"] = kvp.Value.SucceededCount; - m["failed"] = kvp.Value.FailedCount; - m["cancelled"] = kvp.Value.CancelledCount; - })); - - var requestExecutionDuration = _requestDurationLogAggregator.GetValue(kvp.Key); - Logger.Log(FunctionId.LSP_RequestDuration, KeyValueLogMessage.Create(LogType.Trace, m => - { - m["server"] = _serverTypeName; - m["method"] = kvp.Key; - m["bucketsize_logms"] = requestExecutionDuration?.BucketSize; - m["maxbucketvalue_logms"] = requestExecutionDuration?.MaxBucketValue; - m["bucketdata_logms"] = requestExecutionDuration?.GetBucketsAsString(); - })); - } - - Logger.Log(FunctionId.LSP_FindDocumentInWorkspace, KeyValueLogMessage.Create(LogType.Trace, m => - { - m["server"] = _serverTypeName; - foreach (var kvp in _findDocumentResults) - { - var info = kvp.Key.ToString()!; - m[info] = kvp.Value.GetCount(); - } - })); - - Logger.Log(FunctionId.LSP_UsedForkedSolution, KeyValueLogMessage.Create(LogType.Trace, m => - { - m["server"] = _serverTypeName; - foreach (var kvp in _usedForkedSolutionCounter) - { - var info = kvp.Key.ToString()!; - m[info] = kvp.Value.GetCount(); - } - })); - - _requestCounters.Clear(); - } - - private class Counter - { - private int _succeededCount; - private int _failedCount; - private int _cancelledCount; - - public int SucceededCount => _succeededCount; - public int FailedCount => _failedCount; - public int CancelledCount => _cancelledCount; - - public void IncrementCount(Result result) - { - switch (result) - { - case Result.Succeeded: - Interlocked.Increment(ref _succeededCount); - break; - case Result.Failed: - Interlocked.Increment(ref _failedCount); - break; - case Result.Cancelled: - Interlocked.Increment(ref _cancelledCount); - break; - } - } - } - - internal enum Result - { - Succeeded, - Failed, - Cancelled - } - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs index 089ab8466f34b..02fc627e26031 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs @@ -52,6 +52,8 @@ internal partial class RequestExecutionQueue { private readonly WellKnownLspServerKinds _serverKind; private readonly ImmutableArray _supportedLanguages; + private readonly ILspLogger _logger; + private readonly LspServices _lspServices; /// /// The queue containing the ordered LSP requests along with a combined cancellation token @@ -59,12 +61,6 @@ internal partial class RequestExecutionQueue /// private readonly AsyncQueue<(IQueueItem queueItem, CancellationToken cancellationToken)> _queue = new(); private readonly CancellationTokenSource _cancelSource = new(); - private readonly RequestTelemetryLogger _requestTelemetryLogger; - private readonly IGlobalOptionService _globalOptions; - - private readonly ILspLogger _logger; - private readonly LspWorkspaceManager _lspWorkspaceManager; - private readonly ILanguageServerNotificationManager _notificationManager; /// /// For test purposes only. @@ -85,21 +81,14 @@ internal partial class RequestExecutionQueue public event EventHandler? RequestServerShutdown; public RequestExecutionQueue( - ILspLogger logger, - IGlobalOptionService globalOptions, ImmutableArray supportedLanguages, WellKnownLspServerKinds serverKind, - RequestTelemetryLogger requestTelemetryLogger, - LspWorkspaceManager lspWorkspaceManager, - ILanguageServerNotificationManager notificationManager) + LspServices services) { - _logger = logger; - _globalOptions = globalOptions; _supportedLanguages = supportedLanguages; _serverKind = serverKind; - _requestTelemetryLogger = requestTelemetryLogger; - _lspWorkspaceManager = lspWorkspaceManager; - _notificationManager = notificationManager; + _lspServices = services; + _logger = _lspServices.GetRequiredService(); // Start the queue processing _queueProcessingTask = ProcessQueueAsync(); @@ -165,7 +154,7 @@ public void Shutdown() handler, Trace.CorrelationManager.ActivityId, _logger, - _requestTelemetryLogger, + _lspServices, combinedCancellationToken); // Run a continuation to ensure the cts is disposed of. @@ -259,23 +248,56 @@ private void OnRequestServerShutdown(string message) private Task CreateRequestContextAsync(IQueueItem queueItem, CancellationToken cancellationToken) { - var trackerToUse = queueItem.MutatesSolutionState - ? (IDocumentChangeTracker)_lspWorkspaceManager - : new NonMutatingDocumentChangeTracker(); - return RequestContext.CreateAsync( queueItem.RequiresLSPSolution, + queueItem.MutatesSolutionState, queueItem.TextDocument, _serverKind, - _logger, queueItem.ClientCapabilities, - _lspWorkspaceManager, - _notificationManager, - trackerToUse, _supportedLanguages, - _globalOptions, + _lspServices, queueCancellationToken: this.CancellationToken, requestCancellationToken: cancellationToken); } + + #region Test Accessor + internal TestAccessor GetTestAccessor() + => new(this); + + internal readonly struct TestAccessor + { + private readonly RequestExecutionQueue _queue; + + public TestAccessor(RequestExecutionQueue queue) + => _queue = queue; + + public bool IsComplete() => _queue._queue.IsCompleted && _queue._queue.IsEmpty; + + public async Task WaitForProcessingToStopAsync() + { + await _queue._queueProcessingTask.ConfigureAwait(false); + } + + /// + /// Test only method to validate that remaining items in the queue are cancelled. + /// This directly mutates the queue in an unsafe way, so ensure that all relevant queue operations + /// are done before calling. + /// + public async Task AreAllItemsCancelledUnsafeAsync() + { + while (!_queue._queue.IsEmpty) + { + var (_, cancellationToken) = await _queue._queue.DequeueAsync().ConfigureAwait(false); + if (!cancellationToken.IsCancellationRequested) + { + return false; + } + } + + return true; + } + } + + #endregion } } diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestHandlerProviderMetadataView.cs b/src/Features/LanguageServer/Protocol/Handler/RequestHandlerProviderMetadataView.cs deleted file mode 100644 index 430844dab7173..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/RequestHandlerProviderMetadataView.cs +++ /dev/null @@ -1,26 +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.Collections.Immutable; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - /// - /// Defines a custom view to allow MEF to import the correct handlers via metadata. - /// This is a work around for MEF by default being unable to handle an attribute with AllowMultiple = true - /// defined only once on a class. - /// - internal class RequestHandlerProviderMetadataView - { - public ImmutableArray HandlerTypes { get; set; } - - public RequestHandlerProviderMetadataView(IDictionary metadata) - { - var handlerMetadata = (Type[])metadata[nameof(ExportLspRequestHandlerProviderAttribute.HandlerTypes)]; - HandlerTypes = handlerMetadata.ToImmutableArray(); - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs new file mode 100644 index 0000000000000..410679dec7c04 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs @@ -0,0 +1,226 @@ +// 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.Concurrent; +using System.Composition; +using System.Threading; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Internal.Log; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + +[ExportRoslynLspServiceFactory(typeof(RequestTelemetryLogger))] +internal class RequestTelemetryLoggerFactory : ILspServiceFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RequestTelemetryLoggerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + return new RequestTelemetryLogger(serverKind.ToTelemetryString()); + } +} + +/// +/// Logs metadata on LSP requests (duration, success / failure metrics) +/// for this particular LSP server instance. +/// +internal sealed class RequestTelemetryLogger : IDisposable, ILspService +{ + private const string QueuedDurationKey = "QueuedDuration"; + + private readonly string _serverTypeName; + + /// + /// Histogram to aggregate the time in queue metrics. + /// + private readonly HistogramLogAggregator _queuedDurationLogAggregator; + + /// + /// Histogram to aggregate total request duration metrics. + /// This histogram is log based as request latencies can be highly variable depending + /// on the request being handled. As such, we apply the log based function + /// defined by ComputeLogValue to the request latencies for storing in the histogram. + /// This provides highly detailed buckets when duration is in MS, but less detailed + /// when the duration is in terms of seconds or minutes. + /// + private readonly HistogramLogAggregator _requestDurationLogAggregator; + + /// + /// Store request counters in a concurrent dictionary as non-mutating LSP requests can + /// run alongside other non-mutating requests. + /// + private readonly ConcurrentDictionary _requestCounters; + + private readonly LogAggregator _findDocumentResults; + + private readonly LogAggregator _usedForkedSolutionCounter; + + private int _disposed; + + public RequestTelemetryLogger(string serverTypeName) + { + _serverTypeName = serverTypeName; + _requestCounters = new(); + _findDocumentResults = new(); + _usedForkedSolutionCounter = new(); + + // Buckets queued duration into 10ms buckets with the last bucket starting at 1000ms. + // Queue times are relatively short and fall under 50ms, so tracking past 1000ms is not useful. + _queuedDurationLogAggregator = new HistogramLogAggregator(bucketSize: 10, maxBucketValue: 1000); + + // Since this is a log based histogram, these are appropriate bucket sizes for the log data. + // A bucket at 1 corresponds to ~26ms, while the max bucket value corresponds to ~17minutes + _requestDurationLogAggregator = new HistogramLogAggregator(bucketSize: 1, maxBucketValue: 40); + } + + public void UpdateFindDocumentTelemetryData(bool success, string? workspaceKind) + { + var workspaceKindTelemetryProperty = success ? workspaceKind : "Failed"; + + if (workspaceKindTelemetryProperty != null) + { + _findDocumentResults.IncreaseCount(workspaceKindTelemetryProperty); + } + } + + public void UpdateUsedForkedSolutionCounter(bool usedForkedSolution) + { + _usedForkedSolutionCounter.IncreaseCount(usedForkedSolution); + } + + public void UpdateTelemetryData( + string methodName, + TimeSpan queuedDuration, + TimeSpan requestDuration, + Result result) + { + // Find the bucket corresponding to the queued duration and update the count of durations in that bucket. + // This is not broken down per method as time in queue is not specific to an LSP method. + _queuedDurationLogAggregator.IncreaseCount(QueuedDurationKey, Convert.ToDecimal(queuedDuration.TotalMilliseconds)); + + // Store the request time metrics per LSP method. + _requestDurationLogAggregator.IncreaseCount(methodName, Convert.ToDecimal(ComputeLogValue(requestDuration.TotalMilliseconds))); + _requestCounters.GetOrAdd(methodName, (_) => new Counter()).IncrementCount(result); + } + + /// + /// Given an input duration in MS, this transforms it using + /// the log function below to put in reasonable log based buckets + /// from 50ms to 1 hour. Similar transformations must be done to read + /// the data from kusto. + /// + private static double ComputeLogValue(double durationInMS) + { + return 10d * Math.Log10((durationInMS / 100d) + 1); + } + + /// + /// Only output aggregate telemetry to the vs logger when the server instance is disposed + /// to avoid spamming the telemetry output with thousands of events + /// + public void Dispose() + { + if (Interlocked.Exchange(ref _disposed, 1) != 0) + { + return; + } + + if (_queuedDurationLogAggregator.IsEmpty || _requestDurationLogAggregator.IsEmpty) + { + return; + } + + var queuedDurationCounter = _queuedDurationLogAggregator.GetValue(QueuedDurationKey); + Logger.Log(FunctionId.LSP_TimeInQueue, KeyValueLogMessage.Create(LogType.Trace, m => + { + m["server"] = _serverTypeName; + m["bucketsize_ms"] = queuedDurationCounter?.BucketSize; + m["maxbucketvalue_ms"] = queuedDurationCounter?.MaxBucketValue; + m["buckets"] = queuedDurationCounter?.GetBucketsAsString(); + })); + + foreach (var kvp in _requestCounters) + { + Logger.Log(FunctionId.LSP_RequestCounter, KeyValueLogMessage.Create(LogType.Trace, m => + { + m["server"] = _serverTypeName; + m["method"] = kvp.Key; + m["successful"] = kvp.Value.SucceededCount; + m["failed"] = kvp.Value.FailedCount; + m["cancelled"] = kvp.Value.CancelledCount; + })); + + var requestExecutionDuration = _requestDurationLogAggregator.GetValue(kvp.Key); + Logger.Log(FunctionId.LSP_RequestDuration, KeyValueLogMessage.Create(LogType.Trace, m => + { + m["server"] = _serverTypeName; + m["method"] = kvp.Key; + m["bucketsize_logms"] = requestExecutionDuration?.BucketSize; + m["maxbucketvalue_logms"] = requestExecutionDuration?.MaxBucketValue; + m["bucketdata_logms"] = requestExecutionDuration?.GetBucketsAsString(); + })); + } + + Logger.Log(FunctionId.LSP_FindDocumentInWorkspace, KeyValueLogMessage.Create(LogType.Trace, m => + { + m["server"] = _serverTypeName; + foreach (var kvp in _findDocumentResults) + { + var info = kvp.Key.ToString()!; + m[info] = kvp.Value.GetCount(); + } + })); + + Logger.Log(FunctionId.LSP_UsedForkedSolution, KeyValueLogMessage.Create(LogType.Trace, m => + { + m["server"] = _serverTypeName; + foreach (var kvp in _usedForkedSolutionCounter) + { + var info = kvp.Key.ToString()!; + m[info] = kvp.Value.GetCount(); + } + })); + + _requestCounters.Clear(); + } + + private class Counter + { + private int _succeededCount; + private int _failedCount; + private int _cancelledCount; + + public int SucceededCount => _succeededCount; + public int FailedCount => _failedCount; + public int CancelledCount => _cancelledCount; + + public void IncrementCount(Result result) + { + switch (result) + { + case Result.Succeeded: + Interlocked.Increment(ref _succeededCount); + break; + case Result.Failed: + Interlocked.Increment(ref _failedCount); + break; + case Result.Cancelled: + Interlocked.Increment(ref _cancelledCount); + break; + } + } + } + + internal enum Result + { + Succeeded, + Failed, + Cancelled + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs index cd5c0f0e192f3..b646fa96bbb61 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs @@ -201,7 +201,7 @@ await classificationService.AddEmbeddedLanguageClassificationsAsync( return classifiedSpans.ToArray(); } - private static ClassifiedSpan[] ConvertMultiLineToSingleLineSpans(SourceText text, ClassifiedSpan[] classifiedSpans) + public static ClassifiedSpan[] ConvertMultiLineToSingleLineSpans(SourceText text, ClassifiedSpan[] classifiedSpans) { using var _ = ArrayBuilder.GetInstance(out var updatedClassifiedSpans); diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs index db440f8323e07..91553b1c88f05 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs @@ -22,18 +22,43 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens { - /// - /// Computes the semantic tokens for a given range. - /// - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(SemanticTokensRangeHandler)), Shared] + [ExportRoslynLspServiceFactory(typeof(SemanticTokensRangeHandler)), Shared] + internal sealed class SemanticTokensRangeHandlerFactory : ILspServiceFactory + { + private readonly IGlobalOptionService _globalOptions; + private readonly IAsynchronousOperationListenerProvider _asyncListenerProvider; + private readonly LspWorkspaceRegistrationService _lspWorkspaceRegistrationService; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public SemanticTokensRangeHandlerFactory( + IGlobalOptionService globalOptions, + IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider, + LspWorkspaceRegistrationService lspWorkspaceRegistrationService) + { + _globalOptions = globalOptions; + _asyncListenerProvider = asynchronousOperationListenerProvider; + _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + var clientCapabilities = lspServices.GetRequiredService().GetClientCapabilities(); + var notificationManager = lspServices.GetRequiredService(); + return new SemanticTokensRangeHandler(_globalOptions, _asyncListenerProvider, _lspWorkspaceRegistrationService, notificationManager, clientCapabilities); + } + } + [Method(Methods.TextDocumentSemanticTokensRangeName)] - internal class SemanticTokensRangeHandler : AbstractStatelessRequestHandler, IDisposable + internal class SemanticTokensRangeHandler : IRequestHandler, IDisposable { private readonly IGlobalOptionService _globalOptions; private readonly IAsynchronousOperationListener _asyncListener; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + private readonly CancellationTokenSource _disposalTokenSource; + + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; #region Semantic Tokens Refresh state @@ -55,36 +80,46 @@ internal class SemanticTokensRangeHandler : AbstractStatelessRequestHandler - /// Initially null. Set to true/false when first initialized. The other following fields will be set if this - /// is true. - /// - private bool? _supportsRefresh; - /// /// Debouncing queue so that we don't attempt to issue a semantic tokens refresh notification too often. + /// + /// Null when the client does not support sending refresh notifications. /// - private AsyncBatchingWorkQueue? _semanticTokenRefreshQueue; + private readonly AsyncBatchingWorkQueue? _semanticTokenRefreshQueue; #endregion - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public SemanticTokensRangeHandler( IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService) + LspWorkspaceRegistrationService lspWorkspaceRegistrationService, + ILanguageServerNotificationManager notificationManager, + ClientCapabilities clientCapabilities) { _globalOptions = globalOptions; _asyncListener = asynchronousOperationListenerProvider.GetListener(FeatureAttribute.Classification); _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; - _lspWorkspaceRegistrationService.LspSolutionChanged += OnLspSolutionChanged; + + _disposalTokenSource = new(); + + if (clientCapabilities.Workspace?.SemanticTokens?.RefreshSupport is true) + { + // Only send a refresh notification to the client every 0.5s (if needed) in order to avoid + // sending too many notifications at once. This ensures we batch up workspace notifications, + // but also means we send soon enough after a compilation-computation to not make the user wait + // an enormous amount of time. + _semanticTokenRefreshQueue = new AsyncBatchingWorkQueue( + delay: TimeSpan.FromMilliseconds(500), + processBatchAsync: c => notificationManager.SendNotificationAsync(Methods.WorkspaceSemanticTokensRefreshName, c), + asyncListener: _asyncListener, + _disposalTokenSource.Token); + + _lspWorkspaceRegistrationService.LspSolutionChanged += OnLspSolutionChanged; + } } - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.SemanticTokensRangeParams request) + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.SemanticTokensRangeParams request) { Contract.ThrowIfNull(request.TextDocument); return request.TextDocument; @@ -103,35 +138,9 @@ public void Dispose() foreach (var eventSource in eventSources) eventSource.Dispose(); - } - /// - /// Returns true/false if refresh is supported for semantic tokens. - /// - private bool InitializeIfFirstRequest(RequestContext context) - { - lock (_gate) - { - if (_supportsRefresh == null) - { - _supportsRefresh = context.ClientCapabilities.Workspace?.SemanticTokens?.RefreshSupport is true; - - if (_supportsRefresh.Value) - { - // Only send a refresh notification to the client every 0.5s (if needed) in order to avoid - // sending too many notifications at once. This ensures we batch up workspace notifications, - // but also means we send soon enough after a compilation-computation to not make the user wait - // an enormous amount of time. - _semanticTokenRefreshQueue = new AsyncBatchingWorkQueue( - delay: TimeSpan.FromMilliseconds(500), - processBatchAsync: c => context.NotificationManager.SendNotificationAsync(Methods.WorkspaceSemanticTokensRefreshName, c), - asyncListener: _asyncListener, - context.QueueCancellationToken); - } - } - - return _supportsRefresh.Value; - } + _disposalTokenSource.Cancel(); + _disposalTokenSource.Dispose(); } private void OnLspSolutionChanged(object? sender, WorkspaceChangeEventArgs e) @@ -139,21 +148,16 @@ private void OnLspSolutionChanged(object? sender, WorkspaceChangeEventArgs e) private void EnqueueSemanticTokenRefreshNotification() { - // We should only get here if refresh was enabled, which only happens in a codepath that ensured the queue - // was instantiated. + // We should have only gotten here if semantic tokens refresh is supported. Contract.ThrowIfNull(_semanticTokenRefreshQueue); _semanticTokenRefreshQueue.AddWork(); } - public override async Task HandleRequestAsync( + public async Task HandleRequestAsync( SemanticTokensRangeParams request, RequestContext context, CancellationToken cancellationToken) { - // If this is the first time getting a request, initialize our state with information about the - // server/manager we're owned by. - var supportsRefresh = InitializeIfFirstRequest(context); - Contract.ThrowIfNull(request.TextDocument, "TextDocument is null."); Contract.ThrowIfNull(context.Document, "Document is null."); @@ -179,7 +183,7 @@ private void EnqueueSemanticTokenRefreshNotification() // off a request to ensure that the OOP side gets a fully up to compilation for this project. Once it does // we can optionally choose to notify our caller to do a refresh if we computed a compilation for a new // solution snapshot. - if (supportsRefresh) + if (_semanticTokenRefreshQueue != null) await TryEnqueueRefreshComputationAsync(project, cancellationToken).ConfigureAwait(false); return new LSP.SemanticTokens { Data = tokensData }; diff --git a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs index 87008c6b60184..50c0c0884fe42 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs @@ -18,9 +18,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(SignatureHelpHandler)), Shared] + [ExportRoslynStatelessLspService(typeof(SignatureHelpHandler)), Shared] [Method(LSP.Methods.TextDocumentSignatureHelpName)] - internal class SignatureHelpHandler : AbstractStatelessRequestHandler + internal class SignatureHelpHandler : IRequestHandler { private readonly IEnumerable> _allProviders; private readonly IGlobalOptionService _globalOptions; @@ -35,12 +35,12 @@ public SignatureHelpHandler( _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; + public LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs index da2bcf551bed1..a93c199a10a79 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs @@ -2,15 +2,35 @@ // 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.Composition; using System.Threading; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { + [ExportRoslynLspServiceFactory(typeof(DocumentSpellCheckHandler)), Shared] + internal class DocumentSpellCheckHandlerFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public DocumentSpellCheckHandlerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new DocumentSpellCheckHandler(); + } + [Method(VSInternalMethods.TextDocumentSpellCheckableRangesName)] internal class DocumentSpellCheckHandler : AbstractSpellCheckHandler { + public DocumentSpellCheckHandler() + { + } + public override TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalDocumentSpellCheckableParams requestParams) => requestParams.TextDocument; diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerProvider.cs deleted file mode 100644 index 736aaee419390..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerProvider.cs +++ /dev/null @@ -1,24 +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.Composition; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck -{ - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(DocumentSpellCheckHandler)), Shared] - internal class DocumentSpellCheckHandlerProvider : IRequestHandlerProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DocumentSpellCheckHandlerProvider() - { - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - => ImmutableArray.Create(new DocumentSpellCheckHandler()); - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs index 3101c1cd3d2a3..b95e21e65efea 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs @@ -2,16 +2,32 @@ // 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.Composition; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { + [ExportRoslynLspServiceFactory(typeof(WorkspaceSpellCheckHandler)), Shared] + internal class WorkspaceSpellCheckHandlerFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspaceSpellCheckHandlerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new WorkspaceSpellCheckHandler(); + } + [Method(VSInternalMethods.WorkspaceSpellCheckableRangesName)] internal class WorkspaceSpellCheckHandler : AbstractSpellCheckHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerProvider.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerProvider.cs deleted file mode 100644 index d772b9f96db71..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerProvider.cs +++ /dev/null @@ -1,24 +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.Composition; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck -{ - [ExportRoslynLanguagesLspRequestHandlerProvider(typeof(WorkspaceSpellCheckHandler)), Shared] - internal class WorkspaceSpellCheckHandlerProvider : IRequestHandlerProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public WorkspaceSpellCheckHandlerProvider() - { - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - => ImmutableArray.Create(new WorkspaceSpellCheckHandler()); - } -} diff --git a/src/Features/LanguageServer/Protocol/ILanguageServerNotificationManager.cs b/src/Features/LanguageServer/Protocol/ILanguageServerNotificationManager.cs index 644d4a4ae36e3..e4c1e030653c3 100644 --- a/src/Features/LanguageServer/Protocol/ILanguageServerNotificationManager.cs +++ b/src/Features/LanguageServer/Protocol/ILanguageServerNotificationManager.cs @@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - internal interface ILanguageServerNotificationManager + internal interface ILanguageServerNotificationManager : ILspService { ValueTask SendNotificationAsync(string methodName, CancellationToken cancellationToken); } diff --git a/src/Features/LanguageServer/Protocol/ILspLogger.cs b/src/Features/LanguageServer/Protocol/ILspLogger.cs index e907e98bbcdec..f32c32eae22f2 100644 --- a/src/Features/LanguageServer/Protocol/ILspLogger.cs +++ b/src/Features/LanguageServer/Protocol/ILspLogger.cs @@ -6,7 +6,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - internal interface ILspLogger + internal interface ILspLogger : ILspService { void TraceInformation(string message); void TraceWarning(string message); diff --git a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs index 548cc77d7eb00..41158e39a7be4 100644 --- a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs +++ b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs @@ -20,17 +20,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - internal class LanguageServerTarget : ILanguageServerTarget + internal interface IClientCapabilitiesProvider : ILspService + { + ClientCapabilities GetClientCapabilities(); + } + + internal class LanguageServerTarget : ILanguageServerTarget, IClientCapabilitiesProvider { private readonly ICapabilitiesProvider _capabilitiesProvider; private readonly JsonRpc _jsonRpc; private readonly RequestDispatcher _requestDispatcher; - private readonly LspWorkspaceManager _lspWorkspaceManager; private readonly RequestExecutionQueue _queue; - private readonly LanguageServerNotificationManager _notificationManager; + private readonly LspServices _lspServices; private readonly IAsynchronousOperationListener _listener; - private readonly RequestTelemetryLogger _requestTelemetryLogger; private readonly ILspLogger _logger; // Set on first LSP initialize request. @@ -43,19 +46,14 @@ internal class LanguageServerTarget : ILanguageServerTarget internal bool HasShutdownStarted => _shuttingDown; internal LanguageServerTarget( - AbstractRequestDispatcherFactory requestDispatcherFactory, + AbstractLspServiceProvider lspServiceProvider, JsonRpc jsonRpc, ICapabilitiesProvider capabilitiesProvider, - LspWorkspaceRegistrationService workspaceRegistrationService, - LspMiscellaneousFilesWorkspace? lspMiscellaneousFilesWorkspace, - IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, ILspLogger logger, ImmutableArray supportedLanguages, WellKnownLspServerKinds serverKind) { - _requestDispatcher = requestDispatcherFactory.CreateRequestDispatcher(serverKind); - _capabilitiesProvider = capabilitiesProvider; _logger = logger; @@ -63,26 +61,22 @@ internal LanguageServerTarget( _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.Disconnected += JsonRpc_Disconnected; - _notificationManager = new LanguageServerNotificationManager(_jsonRpc); _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); - // Pass the language client instance type name to the telemetry logger to ensure we can - // differentiate between the different C# LSP servers that have the same client name. - // We also don't use the language client's name property as it is a localized user facing string - // which is difficult to write telemetry queries for. - _requestTelemetryLogger = new RequestTelemetryLogger(serverKind.ToTelemetryString()); - _lspWorkspaceManager = new LspWorkspaceManager(logger, lspMiscellaneousFilesWorkspace, workspaceRegistrationService, _requestTelemetryLogger); + // Add services that require base dependencies (jsonrpc) or are more complex to create to the set manually. + _lspServices = lspServiceProvider.CreateServices(serverKind, ImmutableArray.Create( + CreateLspServiceInstance(new LanguageServerNotificationManager(_jsonRpc)), + CreateLspServiceInstance(logger), + CreateLspServiceInstance(this))); _queue = new RequestExecutionQueue( - logger, - globalOptions, supportedLanguages, serverKind, - _requestTelemetryLogger, - _lspWorkspaceManager, - _notificationManager); + _lspServices); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; + _requestDispatcher = _lspServices.GetRequiredService(); + var entryPointMethod = typeof(DelegatingEntryPoint).GetMethod(nameof(DelegatingEntryPoint.EntryPointAsync)); Contract.ThrowIfNull(entryPointMethod, $"{typeof(DelegatingEntryPoint).FullName} is missing method {nameof(DelegatingEntryPoint.EntryPointAsync)}"); @@ -101,6 +95,12 @@ internal LanguageServerTarget( _jsonRpc.AddLocalRpcMethod(genericEntryPointMethod, delegatingEntryPoint, new JsonRpcMethodAttribute(metadata.MethodName) { UseSingleObjectParameterDeserialization = true }); } + + static Lazy CreateLspServiceInstance(T lspServiceInstance) where T : ILspService + { + return new Lazy( + () => lspServiceInstance, new LspServiceMetadataView(typeof(T))); + } } /// @@ -131,6 +131,12 @@ public DelegatingEntryPoint(string method, LanguageServerTarget target) } } + public ClientCapabilities GetClientCapabilities() + { + Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); + return _clientCapabilities; + } + /// /// Handle the LSP initialize request by storing the client capabilities and responding with the server /// capabilities. The specification assures that the initialize request is sent only once. @@ -211,6 +217,9 @@ private void ExitImpl() try { ShutdownRequestQueue(); + + _lspServices.Dispose(); + _jsonRpc.Disconnected -= JsonRpc_Disconnected; _jsonRpc.Dispose(); } @@ -245,9 +254,7 @@ private void ShutdownRequestQueue() _queue.RequestServerShutdown -= RequestExecutionQueue_Errored; // if the queue requested shutdown via its event, it will have already shut itself down, but this // won't cause any problems calling it again - _queue.Shutdown(); - - _requestTelemetryLogger.Dispose(); + _queue?.Shutdown(); } private void RequestExecutionQueue_Errored(object? sender, RequestShutdownEventArgs e) @@ -311,14 +318,10 @@ internal TestAccessor(LanguageServerTarget server) _server = server; } - internal RequestExecutionQueue.TestAccessor GetQueueAccessor() - => _server._queue.GetTestAccessor(); - - internal LspWorkspaceManager.TestAccessor GetManagerAccessor() - => _server._queue.GetTestAccessor().GetLspWorkspaceManager().GetTestAccessor(); + public T GetRequiredLspService() where T : class, ILspService => _server._lspServices.GetRequiredService(); - internal RequestDispatcher.TestAccessor GetDispatcherAccessor() - => _server._requestDispatcher.GetTestAccessor(); + internal RequestExecutionQueue.TestAccessor GetQueueAccessor() + => _server._queue!.GetTestAccessor(); internal JsonRpc GetServerRpc() => _server._jsonRpc; diff --git a/src/Features/LanguageServer/Protocol/LspServices/AbstractLspServiceProvider.cs b/src/Features/LanguageServer/Protocol/LspServices/AbstractLspServiceProvider.cs new file mode 100644 index 0000000000000..a23a3f61d414a --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/AbstractLspServiceProvider.cs @@ -0,0 +1,29 @@ +// 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.Collections.Immutable; +using System.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer; +internal class AbstractLspServiceProvider +{ + private readonly ImmutableArray> _lspServices; + private readonly ImmutableArray> _lspServiceFactories; + + public AbstractLspServiceProvider( + IEnumerable> lspServices, + IEnumerable> lspServiceFactories) + { + _lspServices = lspServices.ToImmutableArray(); + _lspServiceFactories = lspServiceFactories.ToImmutableArray(); + } + + public LspServices CreateServices(WellKnownLspServerKinds serverKind, ImmutableArray> baseServices) + { + return new LspServices(_lspServices, _lspServiceFactories, serverKind, baseServices); + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs new file mode 100644 index 0000000000000..df36a5285fa4b --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs @@ -0,0 +1,39 @@ +// 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 Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] + internal class ExportLspServiceFactoryAttribute : ExportAttribute + { + /// + /// The type of the service being exported. Used during retrieval to find the matching service. + /// + public Type Type { get; } + + /// + /// The LSP server for which this service applies to. If null, this service applies to any server + /// with the matching contract name. + /// + public WellKnownLspServerKinds ServerKind { get; } + + /// + /// Services MEF exported as are statefull as + /// creates a new instance for each server instance. + /// + public bool IsStateless { get; } = false; + + public ExportLspServiceFactoryAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspServiceFactory)) + { + Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); + Type = type; + ServerKind = serverKind; + } + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs new file mode 100644 index 0000000000000..e18286f45768b --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs @@ -0,0 +1,30 @@ +// 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.Composition; +using System.Linq; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + +/// +/// Defines an easy to use subclass for with the roslyn languages contract name. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportRoslynLspServiceFactoryAttribute : ExportLspServiceFactoryAttribute +{ + public ExportRoslynLspServiceFactoryAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) + { + } +} + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportRoslynStatelessLspServiceAttribute : ExportStatelessLspServiceAttribute +{ + public ExportRoslynStatelessLspServiceAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) + { + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs new file mode 100644 index 0000000000000..cc19a3fe376a0 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs @@ -0,0 +1,38 @@ +// 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 Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportStatelessLspServiceAttribute : ExportAttribute +{ + /// + /// The type of the service being exported. Used during retrieval to find the matching service. + /// + public Type Type { get; } + + /// + /// The LSP server for which this service applies to. If null, this service applies to any server + /// with the matching contract name. + /// + public WellKnownLspServerKinds? ServerKind { get; } + + /// + /// Services MEF exported as must by definition be stateless as they are + /// shared amongst all LSP server instances through restarts. + /// + public bool IsStateless { get; } = true; + + public ExportStatelessLspServiceAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspService)) + { + Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); + Type = type; + ServerKind = serverKind; + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs b/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs new file mode 100644 index 0000000000000..e93498dd62574 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs @@ -0,0 +1,11 @@ +// 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.LanguageServer +{ + internal interface ILspService + { + + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs b/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs new file mode 100644 index 0000000000000..90004464a2b19 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs @@ -0,0 +1,17 @@ +// 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 Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer +{ + internal interface ILspServiceFactory + { + /// + /// Some LSP services need to know the client capabilities on construction or + /// need to know about other instances to be constructed. + /// + ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind); + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs new file mode 100644 index 0000000000000..dba317b36ffeb --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs @@ -0,0 +1,33 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer; + +internal class LspServiceMetadataView +{ + public Type Type { get; set; } + + public WellKnownLspServerKinds ServerKind { get; set; } + + public bool IsStateless { get; set; } + + public LspServiceMetadataView(IDictionary metadata) + { + var handlerMetadata = (Type)metadata[nameof(Type)]; + Type = handlerMetadata; + + ServerKind = (WellKnownLspServerKinds)metadata[nameof(ServerKind)]; + IsStateless = (bool)metadata[nameof(IsStateless)]; + } + + public LspServiceMetadataView(Type type) + { + Type = type; + ServerKind = WellKnownLspServerKinds.NotSpecified; + IsStateless = false; + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs new file mode 100644 index 0000000000000..76ab9a20dd853 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs @@ -0,0 +1,108 @@ +// 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.Collections.Immutable; +using System.ComponentModel.Composition.Hosting; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer +{ + internal class LspServices : IDisposable + { + private ImmutableDictionary> _lazyLspServices { get; } + + /// + /// Gates access to . + /// + private readonly object _gate = new(); + private readonly HashSet _servicesToDispose = new(ReferenceEqualityComparer.Instance); + + public LspServices( + ImmutableArray> mefLspServices, + ImmutableArray> mefLspServiceFactories, + WellKnownLspServerKinds serverKind, + ImmutableArray> baseServices) + { + // Convert MEF exported service factories to the lazy LSP services that they create. + var servicesFromFactories = mefLspServiceFactories.Select(lz => new Lazy(() => lz.Value.CreateILspService(this, serverKind), lz.Metadata)); + + var services = mefLspServices.Concat(servicesFromFactories); + + // Make sure that we only include services exported for the specified server kind (or NotSpecified). + services = services.Where(lazyService => lazyService.Metadata.ServerKind == serverKind || lazyService.Metadata.ServerKind == WellKnownLspServerKinds.NotSpecified); + + // Include the base level services that were passed in. + services = services.Concat(baseServices); + + _lazyLspServices = services.ToImmutableDictionary(lazyService => lazyService.Metadata.Type, lazyService => lazyService); + } + + public T GetRequiredService() where T : class, ILspService + { + var service = GetService(); + Contract.ThrowIfNull(service, $"Missing required LSP service {typeof(T).FullName}"); + return service; + } + + public T? GetService() where T : class, ILspService + { + var type = typeof(T); + return TryGetService(type, out var service) ? (T)service : null; + } + + public bool TryGetService(Type type, [NotNullWhen(true)] out object? lspService) + { + if (_lazyLspServices.TryGetValue(type, out var lazyService)) + { + // If we are creating a stateful LSP service for the first time, we need to check + // if it is disposable after creation and keep it around to dispose of on shutdown. + // Stateless LSP services will be disposed of on MEF container disposal. + var checkDisposal = !lazyService.Metadata.IsStateless && !lazyService.IsValueCreated; + + lspService = lazyService.Value; + if (checkDisposal && lspService is IDisposable disposable) + { + lock (_gate) + { + var res = _servicesToDispose.Add(disposable); + } + } + + return true; + } + + lspService = null; + return false; + } + + public ImmutableArray GetRegisteredServices() => _lazyLspServices.Keys.ToImmutableArray(); + + public void Dispose() + { + ImmutableArray disposableServices; + lock (_gate) + { + disposableServices = _servicesToDispose.ToImmutableArray(); + _servicesToDispose.Clear(); + } + + foreach (var disposableService in disposableServices) + { + try + { + disposableService.Dispose(); + } + catch (Exception ex) when (FatalError.ReportAndCatch(ex)) + { + } + } + } + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs new file mode 100644 index 0000000000000..f3af74dcee238 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs @@ -0,0 +1,23 @@ +// 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 System.Text; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.LanguageServer; + +[Export, Shared] +internal class RoslynLspServiceProvider : AbstractLspServiceProvider +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RoslynLspServiceProvider( + [ImportMany(ProtocolConstants.RoslynLspLanguagesContract)] IEnumerable> lspServices, + [ImportMany(ProtocolConstants.RoslynLspLanguagesContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) + { + } +} diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs index 9c44acba729ee..fae565289c16f 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs @@ -20,43 +20,33 @@ namespace Microsoft.CodeAnalysis.LanguageServer /// Aggregates handlers for the specified languages and dispatches LSP requests /// to the appropriate handler for the request. /// - internal class RequestDispatcher + internal class RequestDispatcher : ILspService { private readonly ImmutableDictionary> _requestHandlers; - public RequestDispatcher( - // Lazily imported handler providers to avoid instantiating providers until they are directly needed. - ImmutableArray> requestHandlerProviders, - WellKnownLspServerKinds serverKind) + public RequestDispatcher(LspServices lspServices) { - _requestHandlers = CreateMethodToHandlerMap(requestHandlerProviders, serverKind); + _requestHandlers = CreateMethodToHandlerMap(lspServices); } - private static ImmutableDictionary> CreateMethodToHandlerMap( - IEnumerable> requestHandlerProviders, WellKnownLspServerKinds serverKind) + private static ImmutableDictionary> CreateMethodToHandlerMap(LspServices lspServices) { var requestHandlerDictionary = ImmutableDictionary.CreateBuilder>(); - // Store the request handlers in a dictionary from request name to handler instance. - foreach (var handlerProvider in requestHandlerProviders) + var requestHandlerTypes = lspServices.GetRegisteredServices().Where(type => IsTypeRequestHandler(type)); + + foreach (var handlerType in requestHandlerTypes) { - var handlerTypes = handlerProvider.Metadata.HandlerTypes; - // Instantiate all the providers as one lazy object and re-use it for all methods that the provider provides handlers for. - // This ensures 2 things: - // 1. That the handler provider is not instantiated (and therefore its dependencies are not) until a handler it provides is needed. - // 2. That the handler provider's CreateRequestHandlers is only called once and always returns the same handler instances. - var lazyProviders = new Lazy>(() => handlerProvider.Value.CreateRequestHandlers(serverKind) - .ToImmutableDictionary(p => GetRequestHandlerMethod(p.GetType()), p => p, StringComparer.OrdinalIgnoreCase)); - - foreach (var handlerType in handlerTypes) - { - var (requestType, responseType) = ConvertHandlerTypeToRequestResponseTypes(handlerType); - var method = GetRequestHandlerMethod(handlerType); + var (requestType, responseType) = ConvertHandlerTypeToRequestResponseTypes(handlerType); + var method = GetRequestHandlerMethod(handlerType); - // Using the lazy set of handlers, create a lazy instance that will resolve the set of handlers for the provider - // and then lookup the correct handler for the specified method. - requestHandlerDictionary.Add(new RequestHandlerMetadata(method, requestType, responseType), new Lazy(() => lazyProviders.Value[method])); - } + // Using the lazy set of handlers, create a lazy instance that will resolve the set of handlers for the provider + // and then lookup the correct handler for the specified method. + requestHandlerDictionary.Add(new RequestHandlerMetadata(method, requestType, responseType), new Lazy(() => + { + Contract.ThrowIfFalse(lspServices.TryGetService(handlerType, out var lspService)); + return (IRequestHandler)lspService; + })); } return requestHandlerDictionary.ToImmutable(); @@ -69,6 +59,11 @@ static string GetRequestHandlerMethod(Type handlerType) return methodAttribute.Method; } + + static bool IsTypeRequestHandler(Type type) + { + return type.GetInterfaces().Contains(typeof(IRequestHandler)); + } } /// @@ -126,19 +121,5 @@ public ImmutableArray GetRegisteredMethods() { return _requestHandlers.Keys.ToImmutableArray(); } - - internal TestAccessor GetTestAccessor() - => new TestAccessor(this); - - internal readonly struct TestAccessor - { - private readonly RequestDispatcher _requestDispatcher; - - public TestAccessor(RequestDispatcher requestDispatcher) - => _requestDispatcher = requestDispatcher; - - public IRequestHandler GetHandler(string methodName) - => (IRequestHandler)_requestDispatcher._requestHandlers.Single(handler => handler.Key.MethodName == methodName).Value.Value; - } } } diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs index 98905e69c0451..0bb88b22a8e7d 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs @@ -4,21 +4,30 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.ComponentModel.Composition.Hosting; using System.Composition; +using System.Linq; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer { - [Shared] - [Export(typeof(RequestDispatcherFactory))] - internal sealed class RequestDispatcherFactory : AbstractRequestDispatcherFactory + [ExportRoslynLspServiceFactory(typeof(RequestDispatcher))] + internal class RequestDispatcherFactory : ILspServiceFactory { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RequestDispatcherFactory([ImportMany(ProtocolConstants.RoslynLspLanguagesContract)] IEnumerable> requestHandlerProviders) - : base(requestHandlerProviders) + public RequestDispatcherFactory() { } + + public virtual ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + return new RequestDispatcher(lspServices); + } } } diff --git a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs index f2d6ce68708bb..85a267b5dfc06 100644 --- a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs +++ b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs @@ -41,6 +41,12 @@ internal enum WellKnownLspServerKinds /// LSP server for TypeScript /// RoslynTypeScriptLspServer, + + /// + /// Flag representing any LSP server - used by + /// to specify that something applies to any LSP server. + /// + NotSpecified, } internal static class WellKnownLspServerExtensions @@ -88,4 +94,19 @@ public static string ToTelemetryString(this WellKnownLspServerKinds server) _ => throw ExceptionUtilities.UnexpectedValue(server), }; } + + public static string GetContractName(this WellKnownLspServerKinds server) + { + return server switch + { + WellKnownLspServerKinds.RazorLspServer => ProtocolConstants.RoslynLspLanguagesContract, + WellKnownLspServerKinds.LiveShareLspServer => ProtocolConstants.RoslynLspLanguagesContract, + WellKnownLspServerKinds.AlwaysActiveVSLspServer => ProtocolConstants.RoslynLspLanguagesContract, + WellKnownLspServerKinds.CSharpVisualBasicLspServer => ProtocolConstants.RoslynLspLanguagesContract, + WellKnownLspServerKinds.XamlLspServer => "XamlLspLanguages", + WellKnownLspServerKinds.XamlLspServerDisableUX => "XamlLspLanguages", + WellKnownLspServerKinds.RoslynTypeScriptLspServer => ProtocolConstants.TypeScriptLanguageContract, + _ => throw ExceptionUtilities.UnexpectedValue(server), + }; + } } diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs index 80391b843d6b0..2e3adcb274a8d 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Composition; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -12,11 +13,24 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Features.Workspaces; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.LanguageServer { + [ExportRoslynLspServiceFactory(typeof(LspMiscellaneousFilesWorkspace), WellKnownLspServerKinds.CSharpVisualBasicLspServer), Shared] + internal class LspMiscellaneousFilesWorkspaceFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public LspMiscellaneousFilesWorkspaceFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new LspMiscellaneousFilesWorkspace(); + } + /// /// Defines a default workspace for opened LSP files that are not found in any /// workspace registered by the . @@ -26,7 +40,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer /// Future work for this workspace includes supporting basic metadata references (mscorlib, System dlls, etc), /// but that is dependent on having a x-plat mechanism for retrieving those references from the framework / sdk. /// - internal class LspMiscellaneousFilesWorkspace : Workspace + internal class LspMiscellaneousFilesWorkspace : Workspace, ILspService { private static readonly LanguageInformation s_csharpLanguageInformation = new(LanguageNames.CSharp, ".csx"); private static readonly LanguageInformation s_vbLanguageInformation = new(LanguageNames.VisualBasic, ".vbx"); @@ -39,11 +53,8 @@ internal class LspMiscellaneousFilesWorkspace : Workspace { ".vbx", s_vbLanguageInformation }, }; - private readonly ILspLogger _logger; - - public LspMiscellaneousFilesWorkspace(ILspLogger logger) : base(MefHostServices.DefaultHost, WorkspaceKind.MiscellaneousFiles) + public LspMiscellaneousFilesWorkspace() : base(MefHostServices.DefaultHost, WorkspaceKind.MiscellaneousFiles) { - _logger = logger; } /// @@ -52,13 +63,13 @@ public LspMiscellaneousFilesWorkspace(ILspLogger logger) : base(MefHostServices. /// Calls to this method and are made /// from LSP text sync request handling which do not run concurrently. /// - public Document? AddMiscellaneousDocument(Uri uri, SourceText documentText) + public Document? AddMiscellaneousDocument(Uri uri, SourceText documentText, ILspLogger logger) { var uriAbsolutePath = uri.AbsolutePath; if (!s_extensionToLanguageInformation.TryGetValue(Path.GetExtension(uriAbsolutePath), out var languageInformation)) { // Only log here since throwing here could take down the LSP server. - _logger.TraceError($"Could not find language information for {uri} with absolute path {uriAbsolutePath}"); + logger.TraceError($"Could not find language information for {uri} with absolute path {uriAbsolutePath}"); return null; } @@ -74,7 +85,7 @@ public LspMiscellaneousFilesWorkspace(ILspLogger logger) : base(MefHostServices. /// /// Removes a document with the matching file path from this workspace. /// - /// Calls to this method and are made + /// Calls to this method and are made /// from LSP text sync request handling which do not run concurrently. /// public void TryRemoveMiscellaneousDocument(Uri uri) diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs index c6085cb737dfe..afec0f48d120e 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs @@ -5,10 +5,12 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Composition; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges; using Microsoft.CodeAnalysis.PooledObjects; @@ -43,7 +45,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; /// The code is relatively straightforward /// /// -internal class LspWorkspaceManager : IDocumentChangeTracker +internal class LspWorkspaceManager : IDocumentChangeTracker, ILspService { /// /// A cache from workspace to the last solution we returned for LSP. @@ -86,6 +88,7 @@ public LspWorkspaceManager( _requestTelemetryLogger = requestTelemetryLogger; _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; + } #region Implementation of IDocumentChangeTracker @@ -197,7 +200,7 @@ public void UpdateTrackedDocument(Uri uri, SourceText newSourceText) _requestTelemetryLogger.UpdateFindDocumentTelemetryData(success: false, workspaceKind: null); // Add the document to our loose files workspace if its open. - var miscDocument = _trackedDocuments.ContainsKey(uri) ? _lspMiscellaneousFilesWorkspace?.AddMiscellaneousDocument(uri, _trackedDocuments[uri]) : null; + var miscDocument = _trackedDocuments.ContainsKey(uri) ? _lspMiscellaneousFilesWorkspace?.AddMiscellaneousDocument(uri, _trackedDocuments[uri], _logger) : null; return miscDocument; } diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs new file mode 100644 index 0000000000000..b7dd8b576dbac --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs @@ -0,0 +1,31 @@ +// 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.LanguageServer; + +[ExportRoslynLspServiceFactory(typeof(LspWorkspaceManager))] +internal class LspWorkspaceManagerFactory : ILspServiceFactory +{ + private readonly LspWorkspaceRegistrationService _workspaceRegistrationService; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public LspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) + { + _workspaceRegistrationService = lspWorkspaceRegistrationService; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + var logger = lspServices.GetRequiredService(); + var telemetryLogger = lspServices.GetRequiredService(); + var miscFilesWorkspace = lspServices.GetService(); + return new LspWorkspaceManager(logger, miscFilesWorkspace, _workspaceRegistrationService, telemetryLogger); + } +} diff --git a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs index 1a47503ba6e0d..4ce1225326c69 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs @@ -298,11 +298,8 @@ internal static LSP.VSInternalCodeAction CreateCodeAction( private static CodeActionsCache GetCodeActionsCache(TestLspServer testLspServer) { - var dispatchAccessor = testLspServer.GetDispatcherAccessor(); - var handler = (CodeActionsHandler)dispatchAccessor.GetHandler(LSP.Methods.TextDocumentCodeActionName); - Assert.NotNull(handler); - var cache = handler.GetTestAccessor().GetCache(); - return Assert.IsType(cache); + var cache = testLspServer.GetRequiredLspService(); + return cache; } private static Document GetDocument(Workspace workspace, LSP.TextDocumentIdentifier textDocument) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs index ae78c32d67206..710ff8a23e93d 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.Options; using Roslyn.Test.Utilities; @@ -1369,10 +1370,8 @@ void M() private static CompletionListCache GetCompletionListCache(TestLspServer testLspServer) { - var dispatchAccessor = testLspServer.GetDispatcherAccessor(); - var handler = (CompletionHandler)dispatchAccessor.GetHandler(LSP.Methods.TextDocumentCompletionName); - Assert.NotNull(handler); - return handler.GetTestAccessor().GetCache(); + var cache = testLspServer.GetRequiredLspService(); + return cache; } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs index ec2535a62fcaa..5277792d0e78b 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs @@ -33,7 +33,7 @@ public async Task LinkedDocuments_AllTracked() await DidOpen(testLspServer, caretLocation.Uri); - var trackedDocuments = testLspServer.GetQueueAccessor().GetTrackedTexts(); + var trackedDocuments = testLspServer.GetTrackedTexts(); Assert.Equal(1, trackedDocuments.Length); var solution = await GetLSPSolutionAsync(testLspServer, caretLocation.Uri).ConfigureAwait(false); @@ -45,7 +45,7 @@ public async Task LinkedDocuments_AllTracked() await DidClose(testLspServer, caretLocation.Uri); - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); } [Fact] @@ -83,7 +83,7 @@ void M() await DidOpen(testLspServer, caretLocation.Uri); - Assert.Equal(1, testLspServer.GetQueueAccessor().GetTrackedTexts().Length); + Assert.Equal(1, testLspServer.GetTrackedTexts().Length); await DidChange(testLspServer, caretLocation.Uri, (4, 8, "// hi there")); @@ -96,7 +96,7 @@ void M() await DidClose(testLspServer, caretLocation.Uri); - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); } private static async Task GetLSPSolutionAsync(TestLspServer testLspServer, Uri uri) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.WithFindAllReferences.cs b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.WithFindAllReferences.cs index a492c42a6213b..0e502f913103b 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.WithFindAllReferences.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.WithFindAllReferences.cs @@ -32,7 +32,7 @@ void M2() using (testLspServer) { - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); await DidOpen(testLspServer, locationTyped.Uri); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.cs index 6f7945652507d..64deb3cba6982 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.cs @@ -41,23 +41,23 @@ void M() using (testLspServer) { - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); await DidOpen(testLspServer, locationTyped.Uri); - Assert.Single(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Single(testLspServer.GetTrackedTexts()); - var document = testLspServer.GetQueueAccessor().GetTrackedTexts().Single(); + var document = testLspServer.GetTrackedTexts().Single(); Assert.Equal(documentText, document.ToString()); await DidChange(testLspServer, locationTyped.Uri, (4, 8, "// hi there")); - document = testLspServer.GetQueueAccessor().GetTrackedTexts().Single(); + document = testLspServer.GetTrackedTexts().Single(); Assert.Equal(expected, document.ToString()); await DidClose(testLspServer, locationTyped.Uri); - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); } } @@ -78,7 +78,7 @@ void M() { await DidOpen(testLspServer, locationTyped.Uri); - var document = testLspServer.GetQueueAccessor().GetTrackedTexts().FirstOrDefault(); + var document = testLspServer.GetTrackedTexts().FirstOrDefault(); AssertEx.NotNull(document); Assert.Equal(documentText, document.ToString()); @@ -164,7 +164,7 @@ void M() await DidClose(testLspServer, locationTyped.Uri); - Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); + Assert.Empty(testLspServer.GetTrackedTexts()); } } @@ -196,7 +196,7 @@ void M() await DidChange(testLspServer, locationTyped.Uri, (4, 8, "// hi there")); - var document = testLspServer.GetQueueAccessor().GetTrackedTexts().FirstOrDefault(); + var document = testLspServer.GetTrackedTexts().FirstOrDefault(); AssertEx.NotNull(document); Assert.Equal(expected, document.ToString()); @@ -270,7 +270,7 @@ void M() await DidChange(testLspServer, locationTyped.Uri, (4, 8, "// hi there"), (5, 0, " // this builds on that\r\n")); - var document = testLspServer.GetQueueAccessor().GetTrackedTexts().FirstOrDefault(); + var document = testLspServer.GetTrackedTexts().FirstOrDefault(); AssertEx.NotNull(document); Assert.Equal(expected, document.ToString()); @@ -308,7 +308,7 @@ void M() await DidChange(testLspServer, locationTyped.Uri, (5, 0, " // this builds on that\r\n")); - var document = testLspServer.GetQueueAccessor().GetTrackedTexts().FirstOrDefault(); + var document = testLspServer.GetTrackedTexts().FirstOrDefault(); AssertEx.NotNull(document); Assert.Equal(expected, document.ToString()); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs index 6e1cdf2e47be1..2061aa6545885 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs @@ -2,7 +2,12 @@ // 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.Tasks; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -12,6 +17,8 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests [UseExportProvider] public class LanguageServerTargetTests : AbstractLanguageServerProtocolTests { + protected override TestComposition Composition => base.Composition.AddParts(typeof(StatefulLspServiceFactory), typeof(StatelessLspService)); + [Fact] public async Task LanguageServerQueueEmptyOnShutdownMessage() { @@ -46,6 +53,40 @@ public async Task LanguageServerCleansUpOnUnexpectedJsonRpcDisconnectAsync() Assert.True(server.GetServerAccessor().GetServerRpc().IsDisposed); } + [Fact] + public async Task LanguageServerHasSeparateServiceInstances() + { + using var serverOne = await CreateTestLspServerAsync(""); + using var serverTwo = await CreateTestLspServerAsync(""); + + // Get an LSP service and verify each server has its own instance per server. + Assert.NotSame(serverOne.GetRequiredLspService(), serverTwo.GetRequiredLspService()); + Assert.Same(serverOne.GetRequiredLspService(), serverOne.GetRequiredLspService()); + Assert.Same(serverTwo.GetRequiredLspService(), serverTwo.GetRequiredLspService()); + + // Get a stateless request handler and verify each server has the same instance. + Assert.Same(serverOne.GetRequiredLspService(), serverTwo.GetRequiredLspService()); + } + + [Fact] + public async Task LanguageServerDisposesOfServicesOnShutdown() + { + using var server = await CreateTestLspServerAsync(""); + + var statefulService = server.GetRequiredLspService(); + var statelessService = server.GetRequiredLspService(); + + Assert.False(statefulService.IsDisposed); + Assert.False(statelessService.IsDisposed); + + server.GetServerAccessor().ShutdownServer(); + server.GetServerAccessor().ExitServer(); + + // Only the stateful service should be disposed of on server shutdown. + Assert.True(statefulService.IsDisposed); + Assert.False(statelessService.IsDisposed); + } + private static void AssertServerAlive(TestLspServer server) { Assert.False(server.GetServerAccessor().HasShutdownStarted()); @@ -58,5 +99,42 @@ private static async Task AssertServerQueueClosed(TestLspServer server) Assert.True(server.GetServerAccessor().HasShutdownStarted()); Assert.True(server.GetQueueAccessor().IsComplete()); } + + [ExportRoslynLspServiceFactory(typeof(StatefulLspService)), Shared] + internal class StatefulLspServiceFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public StatefulLspServiceFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new StatefulLspService(); + } + + internal class StatefulLspService : ILspService, IDisposable + { + public bool IsDisposed { get; private set; } = false; + public void Dispose() + { + IsDisposed = true; + } + } + + [ExportRoslynStatelessLspService(typeof(StatelessLspService)), Shared] + internal class StatelessLspService : ILspService, IDisposable + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public StatelessLspService() + { + } + + public bool IsDisposed { get; private set; } = false; + public void Dispose() + { + IsDisposed = true; + } + } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs index 5c7f08c636cb1..751e7952e0c06 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs @@ -28,8 +28,8 @@ void M() } }"; - // Create the server and verify no misc files present. - using var testLspServer = await CreateTestLspServerAsync(string.Empty); + // Create a server that supports LSP misc files and verify no misc files present. + using var testLspServer = await CreateTestLspServerAsync(string.Empty, new LSP.ClientCapabilities(), WellKnownLspServerKinds.CSharpVisualBasicLspServer); Assert.Null(GetMiscellaneousDocument(testLspServer)); // Open an empty loose file and make a request to verify it gets added to the misc workspace. @@ -51,7 +51,8 @@ void M() } }"; - using var testLspServer = await CreateTestLspServerAsync(string.Empty); + // Create a server that supports LSP misc files and verify no misc files present. + using var testLspServer = await CreateTestLspServerAsync(string.Empty, new LSP.ClientCapabilities(), WellKnownLspServerKinds.CSharpVisualBasicLspServer); Assert.Null(GetMiscellaneousDocument(testLspServer)); var looseFileUri = new Uri(@"C:\SomeFile.cs"); @@ -79,8 +80,8 @@ void M() } }"; - // Create the server and verify no misc files present. - using var testLspServer = await CreateTestLspServerAsync(string.Empty); + // Create a server that supports LSP misc files and verify no misc files present. + using var testLspServer = await CreateTestLspServerAsync(string.Empty, new LSP.ClientCapabilities(), WellKnownLspServerKinds.CSharpVisualBasicLspServer); Assert.Null(GetMiscellaneousDocument(testLspServer)); // Open an empty loose file and make a request to verify it gets added to the misc workspace. @@ -104,8 +105,8 @@ void M() } }"; - // Create the server and verify no misc files present. - using var testLspServer = await CreateTestLspServerAsync(markup); + // Create a server that supports LSP misc files and verify no misc files present. + using var testLspServer = await CreateTestLspServerAsync(markup, new LSP.ClientCapabilities(), WellKnownLspServerKinds.CSharpVisualBasicLspServer); Assert.Null(GetMiscellaneousDocument(testLspServer)); // Open a file that is part of a registered workspace and verify it is not present in the misc workspace. @@ -125,8 +126,8 @@ void M() } }"; - // Create the server and verify no misc files present. - using var testLspServer = await CreateTestLspServerAsync(string.Empty); + // Create a server that supports LSP misc files and verify no misc files present. + using var testLspServer = await CreateTestLspServerAsync(string.Empty, new LSP.ClientCapabilities(), WellKnownLspServerKinds.CSharpVisualBasicLspServer); Assert.Null(GetMiscellaneousDocument(testLspServer)); // Open an empty loose file and make a request to verify it gets added to the misc workspace. @@ -154,6 +155,30 @@ void M() await AssertFileInMainWorkspaceAsync(testLspServer, looseFileUri).ConfigureAwait(false); } + [Fact] + public async Task TestLooseFile_DoesNotSupportLspMiscFiles() + { + var source = +@"class A +{ + void M() + { + } +}"; + + // Create a server that doesn't use the LSP misc files workspace. + using var testLspServer = await CreateTestLspServerAsync(string.Empty, new LSP.ClientCapabilities(), WellKnownLspServerKinds.AlwaysActiveVSLspServer); + Assert.Null(testLspServer.GetManagerAccessor().GetLspMiscellaneousFilesWorkspace()); + + // Open an empty loose file and make a request to verify it gets added to the misc workspace. + var looseFileUri = new Uri(@"C:\SomeFile.cs"); + await testLspServer.OpenDocumentAsync(looseFileUri, source).ConfigureAwait(false); + + // Verify the request on the loose file fails. + var lspDocument = await testLspServer.GetManager().GetLspDocumentAsync(new LSP.TextDocumentIdentifier { Uri = looseFileUri }, CancellationToken.None).ConfigureAwait(false); + Assert.Null(lspDocument); + } + private static async Task AssertFileInMiscWorkspaceAsync(TestLspServer testLspServer, Uri fileUri) { var lspDocument = await testLspServer.GetManager().GetLspDocumentAsync(new LSP.TextDocumentIdentifier { Uri = fileUri }, CancellationToken.None); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs index 031c3fb6c644e..a886cd60d915a 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs @@ -13,9 +13,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FailingMutatingRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(FailingMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class FailingMutatingRequestHandler : AbstractStatelessRequestHandler + internal class FailingMutatingRequestHandler : IRequestHandler { public const string MethodName = nameof(FailingMutatingRequestHandler); private const int Delay = 100; @@ -26,12 +26,12 @@ public FailingMutatingRequestHandler() { } - public override bool MutatesSolutionState => true; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => true; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { await Task.Delay(Delay, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs index ca787d4129f3e..ab327838dad05 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs @@ -14,9 +14,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(FailingRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(FailingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class FailingRequestHandler : AbstractStatelessRequestHandler + internal class FailingRequestHandler : IRequestHandler { public const string MethodName = nameof(FailingRequestHandler); private const int Delay = 100; @@ -27,12 +27,12 @@ public FailingRequestHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { await Task.Delay(Delay, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs index 5853e12dab00d..4b41f63556582 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs @@ -15,9 +15,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(LongRunningNonMutatingRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(LongRunningNonMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class LongRunningNonMutatingRequestHandler : AbstractStatelessRequestHandler + internal class LongRunningNonMutatingRequestHandler : IRequestHandler { public const string MethodName = nameof(LongRunningNonMutatingRequestHandler); @@ -27,13 +27,13 @@ public LongRunningNonMutatingRequestHandler() { } - public override bool MutatesSolutionState => false; + public bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { do { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs index f1a9f84b1ae17..715e982f352a4 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs @@ -13,9 +13,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(MutatingRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(MutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class MutatingRequestHandler : AbstractStatelessRequestHandler + internal class MutatingRequestHandler : IRequestHandler { public const string MethodName = nameof(MutatingRequestHandler); private const int Delay = 100; @@ -26,12 +26,12 @@ public MutatingRequestHandler() { } - public override bool MutatesSolutionState => true; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => true; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { var response = new TestResponse { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs index b9cdc5b5cfc3f..8345b74c6f053 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs @@ -15,9 +15,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(NonLSPSolutionRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(NonLSPSolutionRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class NonLSPSolutionRequestHandler : AbstractStatelessRequestHandler + internal class NonLSPSolutionRequestHandler : IRequestHandler { public const string MethodName = nameof(NonLSPSolutionRequestHandler); @@ -27,12 +27,12 @@ public NonLSPSolutionRequestHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => false; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => false; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { Assert.Null(context.Solution); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs index 4eadbfd198671..3ae41bd5a38ba 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs @@ -13,9 +13,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [Shared, ExportRoslynLanguagesLspRequestHandlerProvider(typeof(NonMutatingRequestHandler)), PartNotDiscoverable] + [ExportRoslynStatelessLspService(typeof(NonMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] - internal class NonMutatingRequestHandler : AbstractStatelessRequestHandler + internal class NonMutatingRequestHandler : IRequestHandler { public const string MethodName = nameof(NonMutatingRequestHandler); private const int Delay = 100; @@ -26,12 +26,12 @@ public NonMutatingRequestHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; + public TextDocumentIdentifier GetTextDocumentIdentifier(TestRequest request) => null; - public override async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TestRequest request, RequestContext context, CancellationToken cancellationToken) { var response = new TestResponse(); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs index a5cfc214141f1..3d9e76e876a17 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/VSTypeScriptHandlerTests.cs @@ -28,7 +28,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; public class VSTypeScriptHandlerTests : AbstractLanguageServerProtocolTests { - protected override TestComposition Composition => base.Composition.AddParts(typeof(TypeScriptHandlerProvider)); + protected override TestComposition Composition => base.Composition.AddParts(typeof(TypeScriptHandlerFactory)); [Fact] public async Task TestExternalAccessTypeScriptHandlerInvoked() @@ -85,25 +85,18 @@ private async Task CreateTsTestLspServerAsync(string workspaceXml private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Stream outputStream, TestWorkspace workspace) { - var dispatcherFactory = workspace.ExportProvider.GetExportedValue(); var listenerProvider = workspace.ExportProvider.GetExportedValue(); - var lspWorkspaceRegistrationService = workspace.ExportProvider.GetExportedValue(); var capabilitiesProvider = workspace.ExportProvider.GetExportedValue(); + var servicesProvider = workspace.ExportProvider.GetExportedValue(); var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream)) { ExceptionStrategy = ExceptionProcessing.ISerializable, }; - var globalOptions = workspace.GetService(); - var languageServer = new LanguageServerTarget( - dispatcherFactory, - jsonRpc, + servicesProvider, jsonRpc, capabilitiesProvider, - lspWorkspaceRegistrationService, - new LspMiscellaneousFilesWorkspace(NoOpLspLogger.Instance), - globalOptions, listenerProvider, NoOpLspLogger.Instance, ImmutableArray.Create(InternalLanguageNames.TypeScript), @@ -115,6 +108,21 @@ private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Str internal record TSRequest(Uri Document, string Project); + [ExportTypeScriptLspServiceFactory(typeof(TypeScriptHandler)), PartNotDiscoverable, Shared] + internal class TypeScriptHandlerFactory : AbstractVSTypeScriptRequestHandlerFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public TypeScriptHandlerFactory() + { + } + + protected override IVSTypeScriptRequestHandler CreateRequestHandler() + { + return new TypeScriptHandler(); + } + } + [VSTypeScriptMethod(MethodName)] internal class TypeScriptHandler : AbstractVSTypeScriptRequestHandler { @@ -139,19 +147,4 @@ protected override Task HandleRequestAsync(TSRequest request, TypeScriptReq return Task.FromResult(Response); } } - - [ExportTypeScriptLspRequestHandlerProvider(typeof(TypeScriptHandler)), Shared, PartNotDiscoverable] - internal class TypeScriptHandlerProvider : AbstractVSTypeScriptRequestHandlerProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public TypeScriptHandlerProvider() - { - } - - protected override ImmutableArray CreateRequestHandlers() - { - return ImmutableArray.Create(new TypeScriptHandler()); - } - } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs index 4a609e39edd11..6443727f79469 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Workspaces/LspWorkspaceManagerTests.cs @@ -189,7 +189,9 @@ public async Task TestLspFindsNewDocumentAsync() public async Task TestLspTransfersDocumentToNewWorkspaceAsync() { var markup = "One"; - using var testLspServer = await CreateTestLspServerAsync(markup); + + // Create a server that includes the LSP misc files workspace so we can test transfers to and from it. + using var testLspServer = await CreateTestLspServerAsync(markup, new ClientCapabilities(), serverKind: WellKnownLspServerKinds.CSharpVisualBasicLspServer); // Create a new document, but do not update the workspace solution yet. var newDocumentId = DocumentId.CreateNewId(testLspServer.TestWorkspace.CurrentSolution.ProjectIds[0]); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs index 1078566ab1676..391c100155d94 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClient.cs @@ -32,13 +32,12 @@ internal class XamlInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public XamlInProcLanguageClient( - XamlRequestDispatcherFactory xamlDispatcherFactory, + XamlLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext) { } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs index bcdba101eca9f..907d1ad7c97a2 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageClient/XamlInProcLanguageClientDisableUX.cs @@ -35,13 +35,12 @@ internal class XamlInProcLanguageClientDisableUX : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public XamlInProcLanguageClientDisableUX( - XamlRequestDispatcherFactory xamlDispatcherFactory, + XamlLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService, ILspLoggerFactory lspLoggerFactory, IThreadingContext threadingContext) - : base(xamlDispatcherFactory, globalOptions, listenerProvider, lspWorkspaceRegistrationService, lspLoggerFactory, threadingContext) + : base(lspServiceProvider, globalOptions, listenerProvider, lspLoggerFactory, threadingContext) { } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs index ee3fd8e052d7a..a55d9aee3445e 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs @@ -14,45 +14,48 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; +using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; +using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands; namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - /// - /// Exports all the code action handlers together to ensure they - /// share the same code actions cache state. - /// - /// - /// Same as C# and VB but for XAML. See also . - /// - [ExportXamlLspRequestHandlerProvider(typeof(CodeActionsHandler), typeof(CodeActionResolveHandler), typeof(RunCodeActionHandler)), Shared] - internal class CodeActionsHandlerProvider : IRequestHandlerProvider + [ExportStatelessXamlLspService(typeof(CodeActionsHandler))] + internal class XamlCodeActionsHandler : CodeActionsHandler { - private readonly ICodeFixService _codeFixService; - private readonly ICodeRefactoringService _codeRefactoringService; - private readonly IThreadingContext _threadingContext; - private readonly IGlobalOptionService _globalOptions; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlCodeActionsHandler( + ICodeFixService codeFixService, + ICodeRefactoringService codeRefactoringService, + IGlobalOptionService globalOptions) : base(codeFixService, codeRefactoringService, globalOptions) + { + } + } + [ExportStatelessXamlLspService(typeof(CodeActionResolveHandler))] + internal class XamlCodeActionResolveHandler : CodeActionResolveHandler + { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CodeActionsHandlerProvider( + public XamlCodeActionResolveHandler( ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, - IThreadingContext threadingContext, - IGlobalOptionService globalOptions) + IGlobalOptionService globalOptions) : base(codeFixService, codeRefactoringService, globalOptions) { - _codeFixService = codeFixService; - _codeRefactoringService = codeRefactoringService; - _threadingContext = threadingContext; - _globalOptions = globalOptions; } + } - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) + [ExportStatelessXamlLspService(typeof(RunCodeActionHandler))] + internal class XamlRunCodeActionHandler : RunCodeActionHandler + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlRunCodeActionHandler( + ICodeFixService codeFixService, + ICodeRefactoringService codeRefactoringService, + IGlobalOptionService globalOptions, + IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, globalOptions, threadingContext) { - var codeActionsCache = new CodeActionsCache(); - return ImmutableArray.Create( - new CodeActionsHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions), - new CodeActionResolveHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions), - new RunCodeActionHandler(codeActionsCache, _codeFixService, _codeRefactoringService, _globalOptions, _threadingContext)); } } } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs index b6cb52bf8cec3..36ac9e22200eb 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs @@ -2,26 +2,37 @@ // 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 Microsoft.CodeAnalysis.Editor.Xaml; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands; using Microsoft.VisualStudio.LanguageServer.Protocol; using Microsoft.VisualStudio.LanguageServices.Xaml.Features.Commands; using Microsoft.VisualStudio.LanguageServices.Xaml.Features.Completion; +using Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer; using Newtonsoft.Json.Linq; using Roslyn.Utilities; -namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Commands +namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { /// /// Handle the command that adds an event handler method in code /// + [ExportStatelessXamlLspService(typeof(CreateEventCommandHandler))] [Command(StringConstants.CreateEventHandlerCommand)] internal class CreateEventCommandHandler : AbstractExecuteWorkspaceCommandHandler { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CreateEventCommandHandler() + { + } + public override string Command => StringConstants.CreateEventHandlerCommand; public override bool MutatesSolutionState => false; diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandlerProvider.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandlerProvider.cs deleted file mode 100644 index 4b0564d83f583..0000000000000 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandlerProvider.cs +++ /dev/null @@ -1,31 +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.Composition; -using Microsoft.CodeAnalysis.Editor.Xaml; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands; -using Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer; - -namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Commands -{ - [ExportXamlLspRequestHandlerProvider(typeof(CreateEventCommandHandler)), Shared] - internal class CreateEventCommandHandlerProvider : IRequestHandlerProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CreateEventCommandHandlerProvider() - { - } - - public ImmutableArray CreateRequestHandlers(WellKnownLspServerKinds serverKind) - { - return ImmutableArray.Create(new CreateEventCommandHandler()); - } - } -} diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionHandler.cs index 452cd53d616b3..fb617a9115fec 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionHandler.cs @@ -24,9 +24,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler /// /// Handle a completion request. /// - [ExportXamlLspRequestHandlerProvider(typeof(CompletionHandler)), Shared] + [ExportStatelessXamlLspService(typeof(CompletionHandler)), Shared] [Method(Methods.TextDocumentCompletionName)] - internal class CompletionHandler : AbstractStatelessRequestHandler + internal class CompletionHandler : IRequestHandler { private const string CreateEventHandlerCommandTitle = "Create Event Handler"; @@ -36,8 +36,8 @@ internal class CompletionHandler : AbstractStatelessRequestHandler false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -45,9 +45,9 @@ public CompletionHandler() { } - public override TextDocumentIdentifier GetTextDocumentIdentifier(CompletionParams request) => request.TextDocument; + public TextDocumentIdentifier GetTextDocumentIdentifier(CompletionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(CompletionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(CompletionParams request, RequestContext context, CancellationToken cancellationToken) { if (request.Context is VSInternalCompletionContext completionContext && completionContext.InvokeKind == VSInternalCompletionInvokeKind.Deletion) { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionResolveHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionResolveHandler.cs index d92ee3b29540b..09827855c8262 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionResolveHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Completion/CompletionResolveHandler.cs @@ -27,14 +27,14 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler /// /// Handle a completion resolve request to add description. /// - [ExportXamlLspRequestHandlerProvider(typeof(CompletionResolveHandler)), Shared] + [ExportStatelessXamlLspService(typeof(CompletionResolveHandler)), Shared] [Method(LSP.Methods.TextDocumentCompletionResolveName)] - internal class CompletionResolveHandler : AbstractStatelessRequestHandler + internal class CompletionResolveHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -43,9 +43,9 @@ public CompletionResolveHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override TextDocumentIdentifier? GetTextDocumentIdentifier(CompletionItem request) => null; + public TextDocumentIdentifier? GetTextDocumentIdentifier(CompletionItem request) => null; - public override async Task HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Solution); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs index adbcbe894fa56..72d7ff6278e28 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs @@ -27,9 +27,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Definitions { - [ExportXamlLspRequestHandlerProvider(typeof(GoToDefinitionHandler)), Shared] + [ExportStatelessXamlLspService(typeof(GoToDefinitionHandler)), Shared] [Method(Methods.TextDocumentDefinitionName)] - internal class GoToDefinitionHandler : AbstractStatelessRequestHandler + internal class GoToDefinitionHandler : IRequestHandler { private readonly IMetadataAsSourceFileService _metadataAsSourceFileService; private readonly IGlobalOptionService _globalOptions; @@ -42,13 +42,13 @@ public GoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileSe _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; + public bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var locations = new ConcurrentBag(); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs index c830018864bbb..9fad5083ed7da 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/AbstractPullDiagnosticHandler.cs @@ -25,13 +25,13 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageSe /// /// Root type for both document and workspace diagnostic pull requests. /// - internal abstract class AbstractPullDiagnosticHandler : AbstractStatelessRequestHandler + internal abstract class AbstractPullDiagnosticHandler : IRequestHandler where TReport : VSInternalDiagnosticReport { private readonly IXamlPullDiagnosticService _xamlDiagnosticService; - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; /// /// Gets the progress object to stream results to. @@ -59,7 +59,7 @@ protected AbstractPullDiagnosticHandler(IXamlPullDiagnosticService xamlDiagnosti _xamlDiagnosticService = xamlDiagnosticService; } - public override async Task HandleRequestAsync(TDiagnosticsParams diagnosticsParams, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TDiagnosticsParams diagnosticsParams, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Solution); @@ -189,5 +189,7 @@ private static DiagnosticTag[] ConvertTags(XamlDiagnostic diagnostic) return result.ToArray(); } + + public abstract TextDocumentIdentifier? GetTextDocumentIdentifier(TDiagnosticsParams request); } } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs index 08ab143035859..cc0445d4fd897 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Diagnostics { - [ExportXamlLspRequestHandlerProvider(typeof(DocumentPullDiagnosticHandler)), Shared] + [ExportStatelessXamlLspService(typeof(DocumentPullDiagnosticHandler)), Shared] [Method(VSInternalMethods.DocumentPullDiagnosticName)] internal class DocumentPullDiagnosticHandler : AbstractPullDiagnosticHandler { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs index 6502af8cbed76..77ae57185664e 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs @@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.Implementation.LanguageServer.Handler.Diagnostics { - [ExportXamlLspRequestHandlerProvider(typeof(WorkspacePullDiagnosticHandler)), Shared] + [ExportStatelessXamlLspService(typeof(WorkspacePullDiagnosticHandler)), Shared] [Method(VSInternalMethods.WorkspacePullDiagnosticName)] internal class WorkspacePullDiagnosticHandler : AbstractPullDiagnosticHandler { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/FoldingRanges/FoldingRangesHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/FoldingRanges/FoldingRangesHandler.cs index e7a5beab88d3f..042f95f263676 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/FoldingRanges/FoldingRangesHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/FoldingRanges/FoldingRangesHandler.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Xaml; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -15,9 +16,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(FoldingRangesHandler)), Shared] + [ExportStatelessXamlLspService(typeof(FoldingRangesHandler)), Shared] [Method(Methods.TextDocumentFoldingRangeName)] - internal class FoldingRangesHandler : AbstractStatelessRequestHandler + internal class FoldingRangesHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -25,12 +26,12 @@ public FoldingRangesHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; - public override async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) { var foldingRanges = ArrayBuilder.GetInstance(); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs index ca1f02968f887..7c2f0c9f8069d 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs @@ -9,15 +9,19 @@ using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; using Microsoft.VisualStudio.LanguageServices.Xaml.Features.Formatting; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - internal abstract class AbstractFormatDocumentHandlerBase : AbstractStatelessRequestHandler + internal abstract class AbstractFormatDocumentHandlerBase : IRequestHandler { - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; + + public abstract TextDocumentIdentifier? GetTextDocumentIdentifier(RequestType request); + public abstract Task HandleRequestAsync(RequestType request, RequestContext context, CancellationToken cancellationToken); protected async Task GetTextEditsAsync(LSP.FormattingOptions formattingOptions, RequestContext context, CancellationToken cancellationToken, LSP.Range? range = null) { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentHandler.cs index 412636961380d..1f0dbf4b6e037 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(FormatDocumentHandler)), Shared] + [ExportStatelessXamlLspService(typeof(FormatDocumentHandler)), Shared] [Method(LSP.Methods.TextDocumentFormattingName)] internal class FormatDocumentHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentOnTypeHandler.cs index 30d1a5f660369..469684460f5fd 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -19,9 +19,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(FormatDocumentOnTypeHandler)), Shared] + [ExportStatelessXamlLspService(typeof(FormatDocumentOnTypeHandler)), Shared] [Method(Methods.TextDocumentOnTypeFormattingName)] - internal class FormatDocumentOnTypeHandler : AbstractStatelessRequestHandler + internal class FormatDocumentOnTypeHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -29,12 +29,12 @@ public FormatDocumentOnTypeHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentOnTypeFormattingParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentOnTypeFormattingParams request) => request.TextDocument; - public override async Task HandleRequestAsync(DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken) { var edits = new ArrayBuilder(); if (string.IsNullOrEmpty(request.Character)) diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentRangeHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentRangeHandler.cs index f67afcb105a91..618b5863e4b45 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentRangeHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Formatting/FormatDocumentRangeHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(FormatDocumentRangeHandler)), Shared] + [ExportStatelessXamlLspService(typeof(FormatDocumentRangeHandler)), Shared] [Method(Methods.TextDocumentRangeFormattingName)] internal class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Hover/HoverHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Hover/HoverHandler.cs index f43439072400c..d064b10c4a1fd 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Hover/HoverHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Hover/HoverHandler.cs @@ -23,9 +23,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(HoverHandler)), Shared] + [ExportStatelessXamlLspService(typeof(HoverHandler)), Shared] [Method(Methods.TextDocumentHoverName)] - internal sealed class HoverHandler : AbstractStatelessRequestHandler + internal sealed class HoverHandler : IRequestHandler { private readonly IGlobalOptionService _globalOptions; @@ -36,12 +36,12 @@ public HoverHandler(IGlobalOptionService globalOptions) _globalOptions = globalOptions; } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnAutoInsert/OnAutoInsertHandler.cs index f964579828523..1bb243725f661 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -16,9 +16,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(OnAutoInsertHandler)), Shared] + [ExportStatelessXamlLspService(typeof(OnAutoInsertHandler)), Shared] [Method(VSInternalMethods.OnAutoInsertName)] - internal class OnAutoInsertHandler : AbstractStatelessRequestHandler + internal class OnAutoInsertHandler : IRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -26,12 +26,12 @@ public OnAutoInsertHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalDocumentOnAutoInsertParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalDocumentOnAutoInsertParams request) => request.TextDocument; - public override async Task HandleRequestAsync(VSInternalDocumentOnAutoInsertParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(VSInternalDocumentOnAutoInsertParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnTypeRename/OnTypeRenameHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnTypeRename/OnTypeRenameHandler.cs index 3dd53b1372e5a..c003976b77bf7 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnTypeRename/OnTypeRenameHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/OnTypeRename/OnTypeRenameHandler.cs @@ -17,9 +17,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportXamlLspRequestHandlerProvider(typeof(OnTypeRenameHandler)), Shared] + [ExportStatelessXamlLspService(typeof(OnTypeRenameHandler)), Shared] [Method(Methods.TextDocumentLinkedEditingRangeName)] - internal class OnTypeRenameHandler : AbstractStatelessRequestHandler + internal class OnTypeRenameHandler : IRequestHandler { // From https://www.w3.org/TR/xml/#NT-NameStartChar // Notes: @@ -58,12 +58,12 @@ public OnTypeRenameHandler() { } - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => true; - public override TextDocumentIdentifier? GetTextDocumentIdentifier(LinkedEditingRangeParams request) => request.TextDocument; + public TextDocumentIdentifier? GetTextDocumentIdentifier(LinkedEditingRangeParams request) => request.TextDocument; - public override async Task HandleRequestAsync(LinkedEditingRangeParams request, RequestContext context, CancellationToken cancellationToken) + public async Task HandleRequestAsync(LinkedEditingRangeParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs index b9a08c4312801..8efed16331318 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs @@ -22,8 +22,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer /// /// Implements the Language Server Protocol for XAML /// - [Export(typeof(XamlRequestDispatcherFactory)), Shared] - internal sealed class XamlRequestDispatcherFactory : AbstractRequestDispatcherFactory + [ExportLspServiceFactory(typeof(RequestDispatcher), StringConstants.XamlLspLanguagesContract), Shared] + internal sealed class XamlRequestDispatcherFactory : RequestDispatcherFactory { private readonly XamlProjectService _projectService; private readonly IXamlLanguageServerFeedbackService? _feedbackService; @@ -31,18 +31,16 @@ internal sealed class XamlRequestDispatcherFactory : AbstractRequestDispatcherFa [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public XamlRequestDispatcherFactory( - [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> requestHandlerProviders, XamlProjectService projectService, [Import(AllowDefault = true)] IXamlLanguageServerFeedbackService? feedbackService) - : base(requestHandlerProviders) { _projectService = projectService; _feedbackService = feedbackService; } - public override RequestDispatcher CreateRequestDispatcher(WellKnownLspServerKinds serverKind) + public override ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) { - return new XamlRequestDispatcher(_projectService, _requestHandlerProviders, _feedbackService, serverKind); + return new XamlRequestDispatcher(_projectService, lspServices, _feedbackService); } private class XamlRequestDispatcher : RequestDispatcher @@ -52,9 +50,8 @@ private class XamlRequestDispatcher : RequestDispatcher public XamlRequestDispatcher( XamlProjectService projectService, - ImmutableArray> requestHandlerProviders, - IXamlLanguageServerFeedbackService? feedbackService, - WellKnownLspServerKinds serverKind) : base(requestHandlerProviders, serverKind) + LspServices services, + IXamlLanguageServerFeedbackService? feedbackService) : base(services) { _projectService = projectService; _feedbackService = feedbackService; @@ -91,10 +88,42 @@ public XamlRequestDispatcher( } } + [ExportLspServiceFactory(typeof(LspWorkspaceManager), StringConstants.XamlLspLanguagesContract), Shared] + internal class XamlLspWorkspaceManagerFactory : LspWorkspaceManagerFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlLspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) : base(lspWorkspaceRegistrationService) + { + } + } + + [ExportLspServiceFactory(typeof(RequestTelemetryLogger), StringConstants.XamlLspLanguagesContract), Shared] + internal class XamlRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlRequestTelemetryLoggerFactory() + { + } + } + [AttributeUsage(AttributeTargets.Class), MetadataAttribute] - internal class ExportXamlLspRequestHandlerProviderAttribute : ExportLspRequestHandlerProviderAttribute + internal class ExportStatelessXamlLspServiceAttribute : ExportStatelessLspServiceAttribute + { + public ExportStatelessXamlLspServiceAttribute(Type handlerType) : base(handlerType, StringConstants.XamlLspLanguagesContract, WellKnownLspServerKinds.XamlLspServer) + { + } + } + + [Export, Shared] + internal class XamlLspServiceProvider : AbstractLspServiceProvider { - public ExportXamlLspRequestHandlerProviderAttribute(Type first, params Type[] handlerTypes) : base(StringConstants.XamlLspLanguagesContract, first, handlerTypes) + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlLspServiceProvider( + [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServices, + [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) { } } From c05216b4bd0519f706fdea5329eff846dd58a974 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 13 May 2022 11:01:20 -0700 Subject: [PATCH 2/8] small cleanup --- .../SpellCheck/DocumentSpellCheckHandler.cs | 4 - .../Protocol/LspServices/ILspService.cs | 8 +- .../LspServices/ILspServiceFactory.cs | 17 ++- .../Protocol/LspServices/LspServices.cs | 135 +++++++++--------- .../Workspaces/LspWorkspaceManager.cs | 1 - 5 files changed, 78 insertions(+), 87 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs index a93c199a10a79..062d167a5c2b7 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs @@ -27,10 +27,6 @@ public ILspService CreateILspService(LspServices lspServices, WellKnownLspServer [Method(VSInternalMethods.TextDocumentSpellCheckableRangesName)] internal class DocumentSpellCheckHandler : AbstractSpellCheckHandler { - public DocumentSpellCheckHandler() - { - } - public override TextDocumentIdentifier? GetTextDocumentIdentifier(VSInternalDocumentSpellCheckableParams requestParams) => requestParams.TextDocument; diff --git a/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs b/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs index e93498dd62574..52badd11de8ba 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ILspService.cs @@ -2,10 +2,8 @@ // 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.LanguageServer -{ - internal interface ILspService - { +namespace Microsoft.CodeAnalysis.LanguageServer; - } +internal interface ILspService +{ } diff --git a/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs b/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs index 90004464a2b19..1e5c9979f5f1c 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ILspServiceFactory.cs @@ -4,14 +4,13 @@ using Microsoft.VisualStudio.LanguageServer.Protocol; -namespace Microsoft.CodeAnalysis.LanguageServer +namespace Microsoft.CodeAnalysis.LanguageServer; + +internal interface ILspServiceFactory { - internal interface ILspServiceFactory - { - /// - /// Some LSP services need to know the client capabilities on construction or - /// need to know about other instances to be constructed. - /// - ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind); - } + /// + /// Some LSP services need to know the client capabilities on construction or + /// need to know about other instances to be constructed. + /// + ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind); } diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs index 76ab9a20dd853..f36cd1450648f 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs @@ -12,96 +12,95 @@ using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.LanguageServer +namespace Microsoft.CodeAnalysis.LanguageServer; + +internal class LspServices : IDisposable { - internal class LspServices : IDisposable + private ImmutableDictionary> _lazyLspServices { get; } + + /// + /// Gates access to . + /// + private readonly object _gate = new(); + private readonly HashSet _servicesToDispose = new(ReferenceEqualityComparer.Instance); + + public LspServices( + ImmutableArray> mefLspServices, + ImmutableArray> mefLspServiceFactories, + WellKnownLspServerKinds serverKind, + ImmutableArray> baseServices) { - private ImmutableDictionary> _lazyLspServices { get; } - - /// - /// Gates access to . - /// - private readonly object _gate = new(); - private readonly HashSet _servicesToDispose = new(ReferenceEqualityComparer.Instance); - - public LspServices( - ImmutableArray> mefLspServices, - ImmutableArray> mefLspServiceFactories, - WellKnownLspServerKinds serverKind, - ImmutableArray> baseServices) - { - // Convert MEF exported service factories to the lazy LSP services that they create. - var servicesFromFactories = mefLspServiceFactories.Select(lz => new Lazy(() => lz.Value.CreateILspService(this, serverKind), lz.Metadata)); + // Convert MEF exported service factories to the lazy LSP services that they create. + var servicesFromFactories = mefLspServiceFactories.Select(lz => new Lazy(() => lz.Value.CreateILspService(this, serverKind), lz.Metadata)); - var services = mefLspServices.Concat(servicesFromFactories); + var services = mefLspServices.Concat(servicesFromFactories); - // Make sure that we only include services exported for the specified server kind (or NotSpecified). - services = services.Where(lazyService => lazyService.Metadata.ServerKind == serverKind || lazyService.Metadata.ServerKind == WellKnownLspServerKinds.NotSpecified); + // Make sure that we only include services exported for the specified server kind (or NotSpecified). + services = services.Where(lazyService => lazyService.Metadata.ServerKind == serverKind || lazyService.Metadata.ServerKind == WellKnownLspServerKinds.NotSpecified); - // Include the base level services that were passed in. - services = services.Concat(baseServices); + // Include the base level services that were passed in. + services = services.Concat(baseServices); - _lazyLspServices = services.ToImmutableDictionary(lazyService => lazyService.Metadata.Type, lazyService => lazyService); - } + _lazyLspServices = services.ToImmutableDictionary(lazyService => lazyService.Metadata.Type, lazyService => lazyService); + } - public T GetRequiredService() where T : class, ILspService - { - var service = GetService(); - Contract.ThrowIfNull(service, $"Missing required LSP service {typeof(T).FullName}"); - return service; - } + public T GetRequiredService() where T : class, ILspService + { + var service = GetService(); + Contract.ThrowIfNull(service, $"Missing required LSP service {typeof(T).FullName}"); + return service; + } - public T? GetService() where T : class, ILspService - { - var type = typeof(T); - return TryGetService(type, out var service) ? (T)service : null; - } + public T? GetService() where T : class, ILspService + { + var type = typeof(T); + return TryGetService(type, out var service) ? (T)service : null; + } - public bool TryGetService(Type type, [NotNullWhen(true)] out object? lspService) + public bool TryGetService(Type type, [NotNullWhen(true)] out object? lspService) + { + if (_lazyLspServices.TryGetValue(type, out var lazyService)) { - if (_lazyLspServices.TryGetValue(type, out var lazyService)) - { - // If we are creating a stateful LSP service for the first time, we need to check - // if it is disposable after creation and keep it around to dispose of on shutdown. - // Stateless LSP services will be disposed of on MEF container disposal. - var checkDisposal = !lazyService.Metadata.IsStateless && !lazyService.IsValueCreated; + // If we are creating a stateful LSP service for the first time, we need to check + // if it is disposable after creation and keep it around to dispose of on shutdown. + // Stateless LSP services will be disposed of on MEF container disposal. + var checkDisposal = !lazyService.Metadata.IsStateless && !lazyService.IsValueCreated; - lspService = lazyService.Value; - if (checkDisposal && lspService is IDisposable disposable) + lspService = lazyService.Value; + if (checkDisposal && lspService is IDisposable disposable) + { + lock (_gate) { - lock (_gate) - { - var res = _servicesToDispose.Add(disposable); - } + var res = _servicesToDispose.Add(disposable); } - - return true; } - lspService = null; - return false; + return true; } - public ImmutableArray GetRegisteredServices() => _lazyLspServices.Keys.ToImmutableArray(); + lspService = null; + return false; + } + + public ImmutableArray GetRegisteredServices() => _lazyLspServices.Keys.ToImmutableArray(); - public void Dispose() + public void Dispose() + { + ImmutableArray disposableServices; + lock (_gate) { - ImmutableArray disposableServices; - lock (_gate) + disposableServices = _servicesToDispose.ToImmutableArray(); + _servicesToDispose.Clear(); + } + + foreach (var disposableService in disposableServices) + { + try { - disposableServices = _servicesToDispose.ToImmutableArray(); - _servicesToDispose.Clear(); + disposableService.Dispose(); } - - foreach (var disposableService in disposableServices) + catch (Exception ex) when (FatalError.ReportAndCatch(ex)) { - try - { - disposableService.Dispose(); - } - catch (Exception ex) when (FatalError.ReportAndCatch(ex)) - { - } } } } diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs index afec0f48d120e..0ee06fb6d8d99 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs @@ -88,7 +88,6 @@ public LspWorkspaceManager( _requestTelemetryLogger = requestTelemetryLogger; _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; - } #region Implementation of IDocumentChangeTracker From c320d2eba21c89f9a27be869ee7a83f74e368ff2 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 13 May 2022 12:15:41 -0700 Subject: [PATCH 3/8] Split factories into their own files --- .../VSTypeScriptLspServiceProvider.cs | 2 +- ...VSTypeScriptLspWorkspaceManagerFactory.cs} | 22 --------- .../VSTypeScriptRequestDispatcherFactory.cs | 20 ++++++++ ...TypeScriptRequestTelemetryLoggerFactory.cs | 22 +++++++++ .../Handlers/CodeActions/CodeActionsCache.cs | 12 ----- .../CodeActions/CodeActionsCacheFactory.cs | 21 +++++++++ .../Completion/CompletionListCache.cs | 12 ----- .../Completion/CompletionListCacheFactory.cs | 21 +++++++++ .../Completion/CompletionResolveHandler.cs | 19 -------- .../CompletionResolveHandlerFactory.cs | 31 ++++++++++++ .../DocumentPullDiagnosticHandler.cs | 26 ---------- .../DocumentPullDiagnosticHandlerFactory.cs | 39 +++++++++++++++ ...talDocumentPullDiagnosticHandlerFactory.cs | 42 +++++++++++++++++ ...erimentalDocumentPullDiagnosticsHandler.cs | 26 ---------- ...alWorkspacePullDiagnosticHandlerFactory.cs | 39 +++++++++++++++ ...rimentalWorkspacePullDiagnosticsHandler.cs | 26 ---------- .../WorkspacePullDiagnosticHandler.cs | 23 --------- .../WorkspacePullDiagnosticHandlerFactory.cs | 36 ++++++++++++++ .../Handler/RequestTelemetryLogger.cs | 15 ------ .../Handler/RequestTelemetryLoggerFactory.cs | 24 ++++++++++ .../SemanticTokensRangeHandler.cs | 27 ----------- .../SemanticTokensRangeHandlerFactory.cs | 39 +++++++++++++++ .../SpellCheck/DocumentSpellCheckHandler.cs | 13 ----- .../DocumentSpellCheckHandlerFactory.cs | 23 +++++++++ .../SpellCheck/WorkspaceSpellCheckHandler.cs | 13 ----- .../WorkspaceSpellCheckHandlerFactory.cs | 23 +++++++++ .../Protocol/IClientCapabilitiesProvider.cs | 13 +++++ .../Protocol/LanguageServerTarget.cs | 5 -- .../ExportLspServiceFactoryAttribute.cs | 47 +++++++++---------- .../Protocol/LspServices/LspServices.cs | 2 +- .../LspServices/RoslynLspServiceProvider.cs | 2 +- .../Protocol/RequestDispatcherFactory.cs | 2 +- .../LspMiscellaneousFilesWorkspace.cs | 12 ----- .../LspMiscellaneousFilesWorkspaceFactory.cs | 22 +++++++++ .../Workspaces/LspWorkspaceManagerFactory.cs | 2 +- .../ExportStatelessXamlLspServiceAttribute.cs | 19 ++++++++ .../LanguageServer/XamlLspServiceProvider.cs | 25 ++++++++++ .../XamlLspWorkspaceManagerFactory.cs | 22 +++++++++ .../XamlRequestDispatcherFactory.cs | 41 ---------------- .../XamlRequestTelemetryLoggerFactory.cs | 23 +++++++++ 40 files changed, 532 insertions(+), 321 deletions(-) rename src/EditorFeatures/Core/ExternalAccess/VSTypeScript/{VSTypeScriptLspFactories.cs => VSTypeScriptLspWorkspaceManagerFactory.cs} (51%) create mode 100644 src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs create mode 100644 src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestTelemetryLoggerFactory.cs create mode 100644 src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs create mode 100644 src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs create mode 100644 src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs create mode 100644 src/Features/LanguageServer/Protocol/IClientCapabilitiesProvider.cs create mode 100644 src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs create mode 100644 src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/ExportStatelessXamlLspServiceAttribute.cs create mode 100644 src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspServiceProvider.cs create mode 100644 src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspWorkspaceManagerFactory.cs create mode 100644 src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestTelemetryLoggerFactory.cs diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs index 6f0ddc0d0db63..6f1db20ab5f37 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspServiceProvider.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[Export, Shared] +[Export(typeof(VSTypeScriptLspServiceProvider)), Shared] internal class VSTypeScriptLspServiceProvider : AbstractLspServiceProvider { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspWorkspaceManagerFactory.cs similarity index 51% rename from src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs rename to src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspWorkspaceManagerFactory.cs index 7417cf97b3084..d8b0b289558f9 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspFactories.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptLspWorkspaceManagerFactory.cs @@ -3,24 +3,12 @@ // 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; -using Microsoft.CodeAnalysis.LanguageServer.Handler; namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; -[ExportLspServiceFactory(typeof(RequestDispatcher), ProtocolConstants.TypeScriptLanguageContract), Shared] -internal class VSTypeScriptRequestDispatcherFactory : RequestDispatcherFactory -{ - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSTypeScriptRequestDispatcherFactory() - { - } -} - [ExportLspServiceFactory(typeof(LspWorkspaceManager), ProtocolConstants.TypeScriptLanguageContract), Shared] internal class VSTypeScriptLspWorkspaceManagerFactory : LspWorkspaceManagerFactory { @@ -30,13 +18,3 @@ public VSTypeScriptLspWorkspaceManagerFactory(LspWorkspaceRegistrationService ls { } } - -[ExportLspServiceFactory(typeof(RequestTelemetryLogger), ProtocolConstants.TypeScriptLanguageContract), Shared] -internal class VSTypeScriptRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory -{ - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSTypeScriptRequestTelemetryLoggerFactory() - { - } -} diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs new file mode 100644 index 0000000000000..7041f2561fa86 --- /dev/null +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestDispatcherFactory.cs @@ -0,0 +1,20 @@ +// 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.VSTypeScript; + +[ExportLspServiceFactory(typeof(RequestDispatcher), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptRequestDispatcherFactory : RequestDispatcherFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptRequestDispatcherFactory() + { + } +} diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestTelemetryLoggerFactory.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestTelemetryLoggerFactory.cs new file mode 100644 index 0000000000000..b2968ee42d11c --- /dev/null +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/VSTypeScriptRequestTelemetryLoggerFactory.cs @@ -0,0 +1,22 @@ +// 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; +using Microsoft.CodeAnalysis.LanguageServer.Handler; + +namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; + +[ExportLspServiceFactory(typeof(RequestTelemetryLogger), ProtocolConstants.TypeScriptLanguageContract), Shared] +internal class VSTypeScriptRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSTypeScriptRequestTelemetryLoggerFactory() + { + } +} diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs index b033277a6a8a9..bd4bac23fac21 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCache.cs @@ -17,18 +17,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions { - [ExportRoslynLspServiceFactory(typeof(CodeActionsCache)), Shared] - internal class CodeActionsCacheFactory : ILspServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CodeActionsCacheFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CodeActionsCache(); - } - /// /// Caches suggested action sets between calls to and /// . diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs new file mode 100644 index 0000000000000..951034b24c1bc --- /dev/null +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; + +[ExportRoslynLspServiceFactory(typeof(CodeActionsCache)), Shared] +internal class CodeActionsCacheFactory : ILspServiceFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CodeActionsCacheFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CodeActionsCache(); +} diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs index a4f542fbc2b5c..fd2dc27d0e0a1 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCache.cs @@ -11,18 +11,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion { - [ExportRoslynLspServiceFactory(typeof(CompletionListCache)), Shared] - internal class CompletionListCacheFactory : ILspServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CompletionListCacheFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CompletionListCache(); - } - /// /// Caches completion lists in between calls to CompletionHandler and /// CompletionResolveHandler. Used to avoid unnecessary recomputation. diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs new file mode 100644 index 0000000000000..f2247e9c474cd --- /dev/null +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; + +[ExportRoslynLspServiceFactory(typeof(CompletionListCache)), Shared] +internal class CompletionListCacheFactory : ILspServiceFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CompletionListCacheFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CompletionListCache(); +} diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs index 3a92f57871948..d278025ec39a3 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandler.cs @@ -20,25 +20,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLspServiceFactory(typeof(CompletionResolveHandler))] - internal sealed class CompletionResolveHandlerFactory : ILspServiceFactory - { - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CompletionResolveHandlerFactory(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - { - var completionListCache = lspServices.GetRequiredService(); - return new CompletionResolveHandler(_globalOptions, completionListCache); - } - } - /// /// Handle a completion resolve request to add description. /// diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs new file mode 100644 index 0000000000000..a165edc840367 --- /dev/null +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs @@ -0,0 +1,31 @@ +// 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.Completion; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler +{ + [ExportRoslynLspServiceFactory(typeof(CompletionResolveHandler)), Shared] + internal sealed class CompletionResolveHandlerFactory : ILspServiceFactory + { + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CompletionResolveHandlerFactory(IGlobalOptionService globalOptions) + { + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + var completionListCache = lspServices.GetRequiredService(); + return new CompletionResolveHandler(_globalOptions, completionListCache); + } + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs index 63eec018090bb..92ecc5bd5264e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs @@ -17,32 +17,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { - [ExportRoslynLspServiceFactory(typeof(DocumentPullDiagnosticHandler)), Shared] - internal class DocumentPullDiagnosticHandlerFactory : ILspServiceFactory - { - private readonly IDiagnosticService _diagnosticService; - private readonly IDiagnosticAnalyzerService _analyzerService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DocumentPullDiagnosticHandlerFactory( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, - IGlobalOptionService globalOptions) - { - _diagnosticService = diagnosticService; - _analyzerService = analyzerService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - _globalOptions = globalOptions; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new DocumentPullDiagnosticHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); - } - [Method(VSInternalMethods.DocumentPullDiagnosticName)] internal class DocumentPullDiagnosticHandler : AbstractPullDiagnosticHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs new file mode 100644 index 0000000000000..182ded27fc045 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs @@ -0,0 +1,39 @@ +// 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.Diagnostics; +using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics +{ + [ExportRoslynLspServiceFactory(typeof(DocumentPullDiagnosticHandler)), Shared] + internal class DocumentPullDiagnosticHandlerFactory : ILspServiceFactory + { + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public DocumentPullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new DocumentPullDiagnosticHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs new file mode 100644 index 0000000000000..3b748119d022a --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs @@ -0,0 +1,42 @@ +// 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.Diagnostics; +using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental; + +// A document diagnostic partial report is defined as having the first literal send = DocumentDiagnosticReport (aka the sumtype of changed / unchanged) followed +// by n DocumentDiagnosticPartialResult literals. +// See https://github.com/microsoft/vscode-languageserver-node/blob/main/protocol/src/common/proposed.diagnostics.md#textDocument_diagnostic +[ExportRoslynLspServiceFactory(typeof(ExperimentalDocumentPullDiagnosticsHandler)), Shared] +internal class ExperimentalDocumentPullDiagnosticHandlerFactory : ILspServiceFactory +{ + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ExperimentalDocumentPullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new ExperimentalDocumentPullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); +} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs index 3c8efaa3dd733..6a1584b714d9e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticsHandler.cs @@ -24,32 +24,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental // See https://github.com/microsoft/vscode-languageserver-node/blob/main/protocol/src/common/proposed.diagnostics.md#textDocument_diagnostic using DocumentDiagnosticPartialReport = SumType, DocumentDiagnosticPartialResult>; -[ExportRoslynLspServiceFactory(typeof(ExperimentalDocumentPullDiagnosticsHandler)), Shared] -internal class ExperimentalDocumentPullDiagnosticHandlerFactory : ILspServiceFactory -{ - private readonly IDiagnosticService _diagnosticService; - private readonly IDiagnosticAnalyzerService _analyzerService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ExperimentalDocumentPullDiagnosticHandlerFactory( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, - IGlobalOptionService globalOptions) - { - _diagnosticService = diagnosticService; - _analyzerService = analyzerService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - _globalOptions = globalOptions; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new ExperimentalDocumentPullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); -} - [Method(ExperimentalMethods.TextDocumentDiagnostic)] internal class ExperimentalDocumentPullDiagnosticsHandler : AbstractPullDiagnosticHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs new file mode 100644 index 0000000000000..b564147c93189 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs @@ -0,0 +1,39 @@ +// 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.Diagnostics; +using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental; + +[ExportRoslynLspServiceFactory(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] +internal class ExperimentalWorkspacePullDiagnosticHandlerFactory : ILspServiceFactory +{ + private readonly IDiagnosticService _diagnosticService; + private readonly IDiagnosticAnalyzerService _analyzerService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ExperimentalWorkspacePullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + IDiagnosticAnalyzerService analyzerService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _analyzerService = analyzerService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new ExperimentalWorkspacePullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); +} diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs index 16fc41073f905..35be7dc8109bb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticsHandler.cs @@ -19,32 +19,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental using WorkspaceDocumentDiagnosticReport = SumType; -[ExportRoslynLspServiceFactory(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] -internal class ExperimentalWorkspacePullDiagnosticHandlerFactory : ILspServiceFactory -{ - private readonly IDiagnosticService _diagnosticService; - private readonly IDiagnosticAnalyzerService _analyzerService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ExperimentalWorkspacePullDiagnosticHandlerFactory( - IDiagnosticService diagnosticService, - IDiagnosticAnalyzerService analyzerService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, - IGlobalOptionService globalOptions) - { - _diagnosticService = diagnosticService; - _analyzerService = analyzerService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - _globalOptions = globalOptions; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new ExperimentalWorkspacePullDiagnosticsHandler(_diagnosticService, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions); -} - [Method(ExperimentalMethods.WorkspaceDiagnostic)] internal class ExperimentalWorkspacePullDiagnosticsHandler : AbstractPullDiagnosticHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs index f4104b7f1c72c..ea557e1a02f03 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs @@ -21,29 +21,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { - [ExportRoslynLspServiceFactory(typeof(WorkspacePullDiagnosticHandler)), Shared] - internal class WorkspacePullDiagnosticHandlerFactory : ILspServiceFactory - { - private readonly IDiagnosticService _diagnosticService; - private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public WorkspacePullDiagnosticHandlerFactory( - IDiagnosticService diagnosticService, - EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, - IGlobalOptionService globalOptions) - { - _diagnosticService = diagnosticService; - _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; - _globalOptions = globalOptions; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new WorkspacePullDiagnosticHandler(_diagnosticService, _editAndContinueDiagnosticUpdateSource, _globalOptions); - } - [Method(VSInternalMethods.WorkspacePullDiagnosticName)] internal sealed class WorkspacePullDiagnosticHandler : AbstractPullDiagnosticHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs new file mode 100644 index 0000000000000..d21a9621ac745 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs @@ -0,0 +1,36 @@ +// 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.Diagnostics; +using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics +{ + [ExportRoslynLspServiceFactory(typeof(WorkspacePullDiagnosticHandler)), Shared] + internal class WorkspacePullDiagnosticHandlerFactory : ILspServiceFactory + { + private readonly IDiagnosticService _diagnosticService; + private readonly EditAndContinueDiagnosticUpdateSource _editAndContinueDiagnosticUpdateSource; + private readonly IGlobalOptionService _globalOptions; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspacePullDiagnosticHandlerFactory( + IDiagnosticService diagnosticService, + EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource, + IGlobalOptionService globalOptions) + { + _diagnosticService = diagnosticService; + _editAndContinueDiagnosticUpdateSource = editAndContinueDiagnosticUpdateSource; + _globalOptions = globalOptions; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new WorkspacePullDiagnosticHandler(_diagnosticService, _editAndContinueDiagnosticUpdateSource, _globalOptions); + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs index 410679dec7c04..e53c233f0caa2 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs @@ -11,21 +11,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler; -[ExportRoslynLspServiceFactory(typeof(RequestTelemetryLogger))] -internal class RequestTelemetryLoggerFactory : ILspServiceFactory -{ - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RequestTelemetryLoggerFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - { - return new RequestTelemetryLogger(serverKind.ToTelemetryString()); - } -} - /// /// Logs metadata on LSP requests (duration, success / failure metrics) /// for this particular LSP server instance. diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs new file mode 100644 index 0000000000000..80fe6b0bc3760 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs @@ -0,0 +1,24 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + +[ExportRoslynLspServiceFactory(typeof(RequestTelemetryLogger)), Shared] +internal class RequestTelemetryLoggerFactory : ILspServiceFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RequestTelemetryLoggerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + return new RequestTelemetryLogger(serverKind.ToTelemetryString()); + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs index 91553b1c88f05..5a164f473cc01 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs @@ -22,33 +22,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens { - [ExportRoslynLspServiceFactory(typeof(SemanticTokensRangeHandler)), Shared] - internal sealed class SemanticTokensRangeHandlerFactory : ILspServiceFactory - { - private readonly IGlobalOptionService _globalOptions; - private readonly IAsynchronousOperationListenerProvider _asyncListenerProvider; - private readonly LspWorkspaceRegistrationService _lspWorkspaceRegistrationService; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SemanticTokensRangeHandlerFactory( - IGlobalOptionService globalOptions, - IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider, - LspWorkspaceRegistrationService lspWorkspaceRegistrationService) - { - _globalOptions = globalOptions; - _asyncListenerProvider = asynchronousOperationListenerProvider; - _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - { - var clientCapabilities = lspServices.GetRequiredService().GetClientCapabilities(); - var notificationManager = lspServices.GetRequiredService(); - return new SemanticTokensRangeHandler(_globalOptions, _asyncListenerProvider, _lspWorkspaceRegistrationService, notificationManager, clientCapabilities); - } - } - [Method(Methods.TextDocumentSemanticTokensRangeName)] internal class SemanticTokensRangeHandler : IRequestHandler, IDisposable { diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs new file mode 100644 index 0000000000000..ef1e959cc2589 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs @@ -0,0 +1,39 @@ +// 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.Options; +using Microsoft.CodeAnalysis.Shared.TestHooks; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens +{ + [ExportRoslynLspServiceFactory(typeof(SemanticTokensRangeHandler)), Shared] + internal sealed class SemanticTokensRangeHandlerFactory : ILspServiceFactory + { + private readonly IGlobalOptionService _globalOptions; + private readonly IAsynchronousOperationListenerProvider _asyncListenerProvider; + private readonly LspWorkspaceRegistrationService _lspWorkspaceRegistrationService; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public SemanticTokensRangeHandlerFactory( + IGlobalOptionService globalOptions, + IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider, + LspWorkspaceRegistrationService lspWorkspaceRegistrationService) + { + _globalOptions = globalOptions; + _asyncListenerProvider = asynchronousOperationListenerProvider; + _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + { + var clientCapabilities = lspServices.GetRequiredService().GetClientCapabilities(); + var notificationManager = lspServices.GetRequiredService(); + return new SemanticTokensRangeHandler(_globalOptions, _asyncListenerProvider, _lspWorkspaceRegistrationService, notificationManager, clientCapabilities); + } + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs index 062d167a5c2b7..026432ae26a14 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandler.cs @@ -11,19 +11,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { - [ExportRoslynLspServiceFactory(typeof(DocumentSpellCheckHandler)), Shared] - internal class DocumentSpellCheckHandlerFactory : ILspServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DocumentSpellCheckHandlerFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new DocumentSpellCheckHandler(); - } - [Method(VSInternalMethods.TextDocumentSpellCheckableRangesName)] internal class DocumentSpellCheckHandler : AbstractSpellCheckHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs new file mode 100644 index 0000000000000..de1c4107202ea --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs @@ -0,0 +1,23 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck +{ + [ExportRoslynLspServiceFactory(typeof(DocumentSpellCheckHandler)), Shared] + internal class DocumentSpellCheckHandlerFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public DocumentSpellCheckHandlerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new DocumentSpellCheckHandler(); + } +} diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs index b95e21e65efea..772d4a58e32cb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandler.cs @@ -15,19 +15,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { - [ExportRoslynLspServiceFactory(typeof(WorkspaceSpellCheckHandler)), Shared] - internal class WorkspaceSpellCheckHandlerFactory : ILspServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public WorkspaceSpellCheckHandlerFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) - => new WorkspaceSpellCheckHandler(); - } - [Method(VSInternalMethods.WorkspaceSpellCheckableRangesName)] internal class WorkspaceSpellCheckHandler : AbstractSpellCheckHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs new file mode 100644 index 0000000000000..e674d291c14b5 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs @@ -0,0 +1,23 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck +{ + [ExportRoslynLspServiceFactory(typeof(WorkspaceSpellCheckHandler)), Shared] + internal class WorkspaceSpellCheckHandlerFactory : ILspServiceFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspaceSpellCheckHandlerFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) + => new WorkspaceSpellCheckHandler(); + } +} diff --git a/src/Features/LanguageServer/Protocol/IClientCapabilitiesProvider.cs b/src/Features/LanguageServer/Protocol/IClientCapabilitiesProvider.cs new file mode 100644 index 0000000000000..ef6315e3f11ff --- /dev/null +++ b/src/Features/LanguageServer/Protocol/IClientCapabilitiesProvider.cs @@ -0,0 +1,13 @@ +// 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 Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer +{ + internal interface IClientCapabilitiesProvider : ILspService + { + ClientCapabilities GetClientCapabilities(); + } +} diff --git a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs index 41158e39a7be4..66815d298e122 100644 --- a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs +++ b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs @@ -20,11 +20,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - internal interface IClientCapabilitiesProvider : ILspService - { - ClientCapabilities GetClientCapabilities(); - } - internal class LanguageServerTarget : ILanguageServerTarget, IClientCapabilitiesProvider { private readonly ICapabilitiesProvider _capabilitiesProvider; diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs index df36a5285fa4b..920c0e529ddaa 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs @@ -7,33 +7,32 @@ using System.Linq; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.LanguageServer +namespace Microsoft.CodeAnalysis.LanguageServer; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportLspServiceFactoryAttribute : ExportAttribute { - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] - internal class ExportLspServiceFactoryAttribute : ExportAttribute - { - /// - /// The type of the service being exported. Used during retrieval to find the matching service. - /// - public Type Type { get; } + /// + /// The type of the service being exported. Used during retrieval to find the matching service. + /// + public Type Type { get; } - /// - /// The LSP server for which this service applies to. If null, this service applies to any server - /// with the matching contract name. - /// - public WellKnownLspServerKinds ServerKind { get; } + /// + /// The LSP server for which this service applies to. If null, this service applies to any server + /// with the matching contract name. + /// + public WellKnownLspServerKinds ServerKind { get; } - /// - /// Services MEF exported as are statefull as - /// creates a new instance for each server instance. - /// - public bool IsStateless { get; } = false; + /// + /// Services MEF exported as are statefull as + /// creates a new instance for each server instance. + /// + public bool IsStateless { get; } = false; - public ExportLspServiceFactoryAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspServiceFactory)) - { - Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); - Type = type; - ServerKind = serverKind; - } + public ExportLspServiceFactoryAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspServiceFactory)) + { + Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); + Type = type; + ServerKind = serverKind; } } diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs index f36cd1450648f..c795f5d568e43 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal class LspServices : IDisposable { - private ImmutableDictionary> _lazyLspServices { get; } + private readonly ImmutableDictionary> _lazyLspServices; /// /// Gates access to . diff --git a/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs index f3af74dcee238..646a47dee1226 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; -[Export, Shared] +[Export(typeof(RoslynLspServiceProvider)), Shared] internal class RoslynLspServiceProvider : AbstractLspServiceProvider { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs index 0bb88b22a8e7d..6c17f43718e01 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - [ExportRoslynLspServiceFactory(typeof(RequestDispatcher))] + [ExportRoslynLspServiceFactory(typeof(RequestDispatcher)), Shared] internal class RequestDispatcherFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs index 2e3adcb274a8d..b8ba6a8e3305d 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspace.cs @@ -19,18 +19,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - [ExportRoslynLspServiceFactory(typeof(LspMiscellaneousFilesWorkspace), WellKnownLspServerKinds.CSharpVisualBasicLspServer), Shared] - internal class LspMiscellaneousFilesWorkspaceFactory : ILspServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public LspMiscellaneousFilesWorkspaceFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new LspMiscellaneousFilesWorkspace(); - } - /// /// Defines a default workspace for opened LSP files that are not found in any /// workspace registered by the . diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs new file mode 100644 index 0000000000000..a842e103738ce --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs @@ -0,0 +1,22 @@ +// 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.LanguageServer; + +[ExportRoslynLspServiceFactory(typeof(LspMiscellaneousFilesWorkspace), WellKnownLspServerKinds.CSharpVisualBasicLspServer), Shared] +internal class LspMiscellaneousFilesWorkspaceFactory : ILspServiceFactory +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public LspMiscellaneousFilesWorkspaceFactory() + { + } + + public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new LspMiscellaneousFilesWorkspace(); +} diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs index b7dd8b576dbac..07f50399708dc 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; -[ExportRoslynLspServiceFactory(typeof(LspWorkspaceManager))] +[ExportRoslynLspServiceFactory(typeof(LspWorkspaceManager)), Shared] internal class LspWorkspaceManagerFactory : ILspServiceFactory { private readonly LspWorkspaceRegistrationService _workspaceRegistrationService; diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/ExportStatelessXamlLspServiceAttribute.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/ExportStatelessXamlLspServiceAttribute.cs new file mode 100644 index 0000000000000..fb43c9447fec1 --- /dev/null +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/ExportStatelessXamlLspServiceAttribute.cs @@ -0,0 +1,19 @@ +// 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.Editor.Xaml; +using Microsoft.CodeAnalysis.LanguageServer; + +namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer +{ + [AttributeUsage(AttributeTargets.Class), MetadataAttribute] + internal class ExportStatelessXamlLspServiceAttribute : ExportStatelessLspServiceAttribute + { + public ExportStatelessXamlLspServiceAttribute(Type handlerType) : base(handlerType, StringConstants.XamlLspLanguagesContract, WellKnownLspServerKinds.XamlLspServer) + { + } + } +} diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspServiceProvider.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspServiceProvider.cs new file mode 100644 index 0000000000000..e86cf0a4b6c37 --- /dev/null +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspServiceProvider.cs @@ -0,0 +1,25 @@ +// 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.Editor.Xaml; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer; + +namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer +{ + [Export(typeof(XamlLspServiceProvider)), Shared] + internal class XamlLspServiceProvider : AbstractLspServiceProvider + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlLspServiceProvider( + [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServices, + [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) + { + } + } +} diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspWorkspaceManagerFactory.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspWorkspaceManagerFactory.cs new file mode 100644 index 0000000000000..cf7ea99515121 --- /dev/null +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlLspWorkspaceManagerFactory.cs @@ -0,0 +1,22 @@ +// 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.Editor.Xaml; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer; + +namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer +{ + [ExportLspServiceFactory(typeof(LspWorkspaceManager), StringConstants.XamlLspLanguagesContract), Shared] + internal class XamlLspWorkspaceManagerFactory : LspWorkspaceManagerFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlLspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) : base(lspWorkspaceRegistrationService) + { + } + } +} diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs index 8efed16331318..dd3d3264b6881 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestDispatcherFactory.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; @@ -87,44 +86,4 @@ public XamlRequestDispatcher( } } } - - [ExportLspServiceFactory(typeof(LspWorkspaceManager), StringConstants.XamlLspLanguagesContract), Shared] - internal class XamlLspWorkspaceManagerFactory : LspWorkspaceManagerFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public XamlLspWorkspaceManagerFactory(LspWorkspaceRegistrationService lspWorkspaceRegistrationService) : base(lspWorkspaceRegistrationService) - { - } - } - - [ExportLspServiceFactory(typeof(RequestTelemetryLogger), StringConstants.XamlLspLanguagesContract), Shared] - internal class XamlRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public XamlRequestTelemetryLoggerFactory() - { - } - } - - [AttributeUsage(AttributeTargets.Class), MetadataAttribute] - internal class ExportStatelessXamlLspServiceAttribute : ExportStatelessLspServiceAttribute - { - public ExportStatelessXamlLspServiceAttribute(Type handlerType) : base(handlerType, StringConstants.XamlLspLanguagesContract, WellKnownLspServerKinds.XamlLspServer) - { - } - } - - [Export, Shared] - internal class XamlLspServiceProvider : AbstractLspServiceProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public XamlLspServiceProvider( - [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServices, - [ImportMany(StringConstants.XamlLspLanguagesContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) - { - } - } } diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestTelemetryLoggerFactory.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestTelemetryLoggerFactory.cs new file mode 100644 index 0000000000000..444e187b8dae7 --- /dev/null +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/XamlRequestTelemetryLoggerFactory.cs @@ -0,0 +1,23 @@ +// 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.Editor.Xaml; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.LanguageServer.Handler; + +namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer +{ + [ExportLspServiceFactory(typeof(RequestTelemetryLogger), StringConstants.XamlLspLanguagesContract), Shared] + internal class XamlRequestTelemetryLoggerFactory : RequestTelemetryLoggerFactory + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public XamlRequestTelemetryLoggerFactory() + { + } + } +} From f6e4aca9c9d794d20187558b00ba2f05059f6623 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 16 May 2022 10:46:10 -0700 Subject: [PATCH 4/8] small feedback --- .../Protocol/Handler/IDocumentChangeTracker.cs | 1 + .../LspServices/ExportLspServiceFactoryAttribute.cs | 7 +++++++ .../LspServices/ExportRoslynLspServiceFactoryAttribute.cs | 8 -------- .../LspServices/ExportStatelessLspServiceAttribute.cs | 7 +++++++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs b/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs index e692e2b796bae..ed72bf4ef4b57 100644 --- a/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs +++ b/src/Features/LanguageServer/Protocol/Handler/IDocumentChangeTracker.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + /// /// Associates LSP document URIs with the roslyn source text containing the LSP document text. /// Called via , and diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs index 920c0e529ddaa..ac31a6b36a41e 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs @@ -9,6 +9,13 @@ namespace Microsoft.CodeAnalysis.LanguageServer; +/// +/// Exports an that is used by LSP server instances +/// to create new instances of the each time an LSP server is started. +/// +/// The services created by the are disposed of by +/// when the LSP server instance shuts down. +/// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] internal class ExportLspServiceFactoryAttribute : ExportAttribute { diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs index e18286f45768b..2df575f12896f 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs @@ -20,11 +20,3 @@ public ExportRoslynLspServiceFactoryAttribute(Type type, WellKnownLspServerKinds { } } - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] -internal class ExportRoslynStatelessLspServiceAttribute : ExportStatelessLspServiceAttribute -{ - public ExportRoslynStatelessLspServiceAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) - { - } -} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs index cc19a3fe376a0..9a75660993287 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs @@ -9,6 +9,13 @@ namespace Microsoft.CodeAnalysis.LanguageServer; +/// +/// Defines an attribute to export an instance of that is re-used across +/// all server instances in the same mef container. Services using this export attribute should not +/// store any kind of server specific state in them. +/// +/// MEF will dispose of these services when the container is disposed of. +/// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] internal class ExportStatelessLspServiceAttribute : ExportAttribute { From 9d02aabb48ba974b144f3f9e81db1143797d71fe Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 16 May 2022 10:55:24 -0700 Subject: [PATCH 5/8] renames --- .../AlwaysActivateInProcLanguageClient.cs | 2 +- .../CodeActions/CodeActionResolveHandler.cs | 2 +- .../CodeActions/CodeActionsCacheFactory.cs | 2 +- .../CodeActions/CodeActionsHandler.cs | 2 +- .../CodeActions/RunCodeActionHandler.cs | 2 +- .../Handlers/Completion/CompletionHandler.cs | 2 +- .../Completion/CompletionListCacheFactory.cs | 2 +- .../CompletionResolveHandlerFactory.cs | 2 +- .../Handlers/Hover/HoverHandler.cs | 2 +- .../References/FindAllReferencesHandler.cs | 2 +- .../References/FindImplementationsHandler.cs | 2 +- .../Handlers/Rename/RenameHandler.cs | 2 +- .../Symbols/DocumentSymbolsHandler.cs | 2 +- .../Symbols/WorkspaceSymbolsHandler.cs | 2 +- .../LiveShareInProcLanguageClient.cs | 2 +- .../RazorInProcLanguageClient.cs | 2 +- .../AbstractLanguageServerProtocolTests.cs | 2 +- .../CSharpVisualBasicLanguageServerFactory.cs | 2 +- .../ValidateBreakableRangeHandler.cs | 2 +- .../Definitions/GoToDefinitionHandler.cs | 2 +- .../Definitions/GoToTypeDefinitionHandler.cs | 2 +- .../DocumentPullDiagnosticHandlerFactory.cs | 2 +- ...talDocumentPullDiagnosticHandlerFactory.cs | 2 +- ...alWorkspacePullDiagnosticHandlerFactory.cs | 2 +- .../WorkspacePullDiagnosticHandlerFactory.cs | 2 +- .../DocumentChanges/DidChangeHandler.cs | 2 +- .../DocumentChanges/DidCloseHandler.cs | 2 +- .../Handler/DocumentChanges/DidOpenHandler.cs | 2 +- .../FoldingRanges/FoldingRangesHandler.cs | 2 +- .../Formatting/FormatDocumentHandler.cs | 2 +- .../Formatting/FormatDocumentOnTypeHandler.cs | 2 +- .../Formatting/FormatDocumentRangeHandler.cs | 2 +- .../Highlights/DocumentHighlightHandler.cs | 2 +- .../InlineCompletionsHandler.cs | 2 +- .../OnAutoInsert/OnAutoInsertHandler.cs | 2 +- .../GetTextDocumentWithContextHandler.cs | 2 +- .../Handler/RequestTelemetryLoggerFactory.cs | 2 +- .../SemanticTokensRangeHandlerFactory.cs | 2 +- .../SignatureHelp/SignatureHelpHandler.cs | 2 +- .../DocumentSpellCheckHandlerFactory.cs | 2 +- .../WorkspaceSpellCheckHandlerFactory.cs | 2 +- .../ExportLspServiceFactoryAttribute.cs | 2 +- .../ExportRoslynLspServiceFactoryAttribute.cs | 22 ------------------- .../ExportStatelessLspServiceAttribute.cs | 2 +- .../LspServices/LspServiceMetadataView.cs | 2 +- .../Protocol/LspServices/LspServices.cs | 2 +- .../LspServices/RoslynLspServiceProvider.cs | 6 ++--- .../Protocol/RequestDispatcherFactory.cs | 2 +- .../Protocol/WellKnownLspServerKinds.cs | 2 +- .../LspMiscellaneousFilesWorkspaceFactory.cs | 2 +- .../Workspaces/LspWorkspaceManagerFactory.cs | 2 +- .../LanguageServerTargetTests.cs | 4 ++-- .../Ordering/FailingMutatingRequestHandler.cs | 2 +- .../Ordering/FailingRequestHandler.cs | 2 +- .../LongRunningNonMutatingRequestHandler.cs | 2 +- .../Ordering/MutatingRequestHandler.cs | 2 +- .../NonLSPSolutionRequestHandlerProvider.cs | 2 +- .../Ordering/NonMutatingRequestHandler.cs | 2 +- 58 files changed, 60 insertions(+), 82 deletions(-) delete mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs diff --git a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs index b96d266812b55..db2cbcacdc17a 100644 --- a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs @@ -36,7 +36,7 @@ internal class AlwaysActivateInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public AlwaysActivateInProcLanguageClient( - RoslynLspServiceProvider lspServiceProvider, + CSharpVisualBasicLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, DefaultCapabilitiesProvider defaultCapabilitiesProvider, diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs index 5dbcef1f44c0b..8bccffebf339a 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionResolveHandler.cs @@ -34,7 +34,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// EditorFeatures references in are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(CodeActionResolveHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(CodeActionResolveHandler)), Shared] [Method(LSP.Methods.CodeActionResolveName)] internal class CodeActionResolveHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs index 951034b24c1bc..21af32026a444 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsCacheFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; -[ExportRoslynLspServiceFactory(typeof(CodeActionsCache)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(CodeActionsCache)), Shared] internal class CodeActionsCacheFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs index 9193ecc94b7d1..45c8138a0976a 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionsHandler.cs @@ -27,7 +27,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// EditorFeatures references in are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(CodeActionsHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(CodeActionsHandler)), Shared] [Method(LSP.Methods.TextDocumentCodeActionName)] internal class CodeActionsHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs index 05a296035e172..63a38b7af59be 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/RunCodeActionHandler.cs @@ -33,7 +33,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// UI thread dependencies are resolved and references are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(RunCodeActionHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(RunCodeActionHandler)), Shared] [Command(CodeActionsHandler.RunCodeActionCommandName)] internal class RunCodeActionHandler : AbstractExecuteWorkspaceCommandHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs index c2978e1a667f4..1050a63235065 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionHandler.cs @@ -33,7 +33,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// references to VS Icon types are removed. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(CompletionHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(CompletionHandler)), Shared] [Method(LSP.Methods.TextDocumentCompletionName)] internal class CompletionHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs index f2247e9c474cd..b2d97ab2f3e57 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionListCacheFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; -[ExportRoslynLspServiceFactory(typeof(CompletionListCache)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(CompletionListCache)), Shared] internal class CompletionListCacheFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs index a165edc840367..ad55e53dc391d 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Completion/CompletionResolveHandlerFactory.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynLspServiceFactory(typeof(CompletionResolveHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(CompletionResolveHandler)), Shared] internal sealed class CompletionResolveHandlerFactory : ILspServiceFactory { private readonly IGlobalOptionService _globalOptions; diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs index e18b8f990b289..ac4b769539980 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs @@ -27,7 +27,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// no longer references VS icon or classified text run types. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(HoverHandler))] + [ExportCSharpVisualBasicStatelessLspService(typeof(HoverHandler))] [Method(Methods.TextDocumentHoverName)] internal sealed class HoverHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs index 2cdbc671510b4..2f8c906c3c011 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindAllReferencesHandler.cs @@ -26,7 +26,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// we no longer reference VS classified text runs. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(FindAllReferencesHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FindAllReferencesHandler)), Shared] [Method(LSP.Methods.TextDocumentReferencesName)] internal class FindAllReferencesHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs index dd9ea03f99695..8347b40db129f 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindImplementationsHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(FindImplementationsHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FindImplementationsHandler)), Shared] [Method(LSP.Methods.TextDocumentImplementationName)] internal sealed class FindImplementationsHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs index 38d2b2eb604ce..7cf171728af02 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Rename/RenameHandler.cs @@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// we no longer reference the /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportRoslynStatelessLspService(typeof(RenameHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(RenameHandler)), Shared] [Method(LSP.Methods.TextDocumentRenameName)] internal class RenameHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs index 4e72c2cd4590d..7fe0045844257 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/DocumentSymbolsHandler.cs @@ -23,7 +23,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once /// we no longer reference VS icon types. /// - [ExportRoslynStatelessLspService(typeof(DocumentSymbolsHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(DocumentSymbolsHandler)), Shared] [Method(Methods.TextDocumentDocumentSymbolName)] internal class DocumentSymbolsHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs index b99829c46bed5..9e18d18560f51 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Symbols/WorkspaceSymbolsHandler.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once /// we no longer reference VS icon types. /// - [ExportRoslynStatelessLspService(typeof(WorkspaceSymbolsHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(WorkspaceSymbolsHandler)), Shared] [Method(Methods.WorkspaceSymbolName)] internal class WorkspaceSymbolsHandler : IRequestHandler { diff --git a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs index 2f679e4c633ff..988814bb4571f 100644 --- a/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/LiveShareInProcLanguageClient.cs @@ -30,7 +30,7 @@ internal class LiveShareInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, true)] public LiveShareInProcLanguageClient( - RoslynLspServiceProvider lspServiceProvider, + CSharpVisualBasicLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, DefaultCapabilitiesProvider defaultCapabilitiesProvider, diff --git a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs index 7251d72755790..b811930e097f2 100644 --- a/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/RazorInProcLanguageClient.cs @@ -47,7 +47,7 @@ internal class RazorInProcLanguageClient : AbstractInProcLanguageClient [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RazorInProcLanguageClient( - RoslynLspServiceProvider lspServiceProvider, + CSharpVisualBasicLspServiceProvider lspServiceProvider, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, DefaultCapabilitiesProvider defaultCapabilitiesProvider, diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs index d9fa7823cc898..84858f4982337 100644 --- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs +++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs @@ -558,7 +558,7 @@ private static LanguageServerTarget CreateLanguageServer(Stream inputStream, Str { var listenerProvider = workspace.ExportProvider.GetExportedValue(); var capabilitiesProvider = workspace.ExportProvider.GetExportedValue(); - var servicesProvider = workspace.ExportProvider.GetExportedValue(); + var servicesProvider = workspace.ExportProvider.GetExportedValue(); var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, CreateJsonMessageFormatter())) { diff --git a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs index 171f9a2100b58..44e6d704f92c4 100644 --- a/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs +++ b/src/Features/LanguageServer/Protocol/CSharpVisualBasicLanguageServerFactory.cs @@ -21,7 +21,7 @@ internal class CSharpVisualBasicLanguageServerFactory : ILanguageServerFactory [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CSharpVisualBasicLanguageServerFactory( - RoslynLspServiceProvider lspServiceProvider, + CSharpVisualBasicLspServiceProvider lspServiceProvider, IAsynchronousOperationListenerProvider listenerProvider) { _lspServiceProvider = lspServiceProvider; diff --git a/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs index ac7a9cc2c4dd8..1a7afe412bd34 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Breakpoints/ValidateBreakableRangeHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(ValidateBreakableRangeHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(ValidateBreakableRangeHandler)), Shared] [Method(LSP.VSInternalMethods.TextDocumentValidateBreakableRangeName)] internal sealed class ValidateBreakableRangeHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs index ffb5d1e93bedc..b79a4f99cea20 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(GoToDefinitionHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(GoToDefinitionHandler)), Shared] [Method(LSP.Methods.TextDocumentDefinitionName)] internal class GoToDefinitionHandler : AbstractGoToDefinitionHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs index 69ceae10af33f..34c0540522c9f 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(GoToTypeDefinitionHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(GoToTypeDefinitionHandler)), Shared] [Method(LSP.Methods.TextDocumentTypeDefinitionName)] internal class GoToTypeDefinitionHandler : AbstractGoToDefinitionHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs index 182ded27fc045..ec49e17deb952 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandlerFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { - [ExportRoslynLspServiceFactory(typeof(DocumentPullDiagnosticHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(DocumentPullDiagnosticHandler)), Shared] internal class DocumentPullDiagnosticHandlerFactory : ILspServiceFactory { private readonly IDiagnosticService _diagnosticService; diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs index 3b748119d022a..da574046ca137 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalDocumentPullDiagnosticHandlerFactory.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental // A document diagnostic partial report is defined as having the first literal send = DocumentDiagnosticReport (aka the sumtype of changed / unchanged) followed // by n DocumentDiagnosticPartialResult literals. // See https://github.com/microsoft/vscode-languageserver-node/blob/main/protocol/src/common/proposed.diagnostics.md#textDocument_diagnostic -[ExportRoslynLspServiceFactory(typeof(ExperimentalDocumentPullDiagnosticsHandler)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(ExperimentalDocumentPullDiagnosticsHandler)), Shared] internal class ExperimentalDocumentPullDiagnosticHandlerFactory : ILspServiceFactory { private readonly IDiagnosticService _diagnosticService; diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs index b564147c93189..f0dfe24fc4339 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/Experimental/ExperimentalWorkspacePullDiagnosticHandlerFactory.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental; -[ExportRoslynLspServiceFactory(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(ExperimentalWorkspacePullDiagnosticsHandler)), Shared] internal class ExperimentalWorkspacePullDiagnosticHandlerFactory : ILspServiceFactory { private readonly IDiagnosticService _diagnosticService; diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs index d21a9621ac745..f0760002fa4b7 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandlerFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics { - [ExportRoslynLspServiceFactory(typeof(WorkspacePullDiagnosticHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(WorkspacePullDiagnosticHandler)), Shared] internal class WorkspacePullDiagnosticHandlerFactory : ILspServiceFactory { private readonly IDiagnosticService _diagnosticService; diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs index 4e2a4c78a5908..af8e962972bae 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidChangeHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynStatelessLspService(typeof(DidChangeHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(DidChangeHandler)), Shared] [Method(LSP.Methods.TextDocumentDidChangeName)] internal class DidChangeHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs index 9b8cb9042faec..a2714c3779b83 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidCloseHandler.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynStatelessLspService(typeof(DidCloseHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(DidCloseHandler)), Shared] [Method(LSP.Methods.TextDocumentDidCloseName)] internal class DidCloseHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs index 021a8df690f7b..eb02cb25745b5 100644 --- a/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/DocumentChanges/DidOpenHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DocumentChanges { - [ExportRoslynStatelessLspService(typeof(DidOpenHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(DidOpenHandler)), Shared] [Method(LSP.Methods.TextDocumentDidOpenName)] internal class DidOpenHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs index 8a500d340b725..1b80f52667c4b 100644 --- a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(FoldingRangesHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FoldingRangesHandler)), Shared] [Method(Methods.TextDocumentFoldingRangeName)] internal sealed class FoldingRangesHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs index 6d0442bb2e737..23ddc0bbf788e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(FormatDocumentHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FormatDocumentHandler)), Shared] [Method(LSP.Methods.TextDocumentFormattingName)] internal sealed class FormatDocumentHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index 5920431812008..bb1346cd08e61 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(FormatDocumentOnTypeHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FormatDocumentOnTypeHandler)), Shared] [Method(Methods.TextDocumentOnTypeFormattingName)] internal sealed class FormatDocumentOnTypeHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs index a847db0cef1df..381a93aab25f2 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(FormatDocumentRangeHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FormatDocumentRangeHandler)), Shared] [Method(Methods.TextDocumentRangeFormattingName)] internal sealed class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase { diff --git a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs index 5ccaf6ae9265c..f07e08beec8ff 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(DocumentHighlightsHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(DocumentHighlightsHandler)), Shared] [Method(Methods.TextDocumentDocumentHighlightName)] internal class DocumentHighlightsHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs index 38f93116e5ece..ae05e9304d4d0 100644 --- a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs @@ -29,7 +29,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.InlineCompletions; /// /// Supports built in legacy snippets for razor scenarios. /// -[ExportRoslynStatelessLspService(typeof(InlineCompletionsHandler)), Shared] +[ExportCSharpVisualBasicStatelessLspService(typeof(InlineCompletionsHandler)), Shared] [Method(VSInternalMethods.TextDocumentInlineCompletionName)] internal partial class InlineCompletionsHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs index de89bc83e80c4..c60d731534785 100644 --- a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(OnAutoInsertHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(OnAutoInsertHandler)), Shared] [Method(LSP.VSInternalMethods.OnAutoInsertName)] internal sealed class OnAutoInsertHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs index d1d5929fd08f7..cab18fc1665bc 100644 --- a/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/ProjectContext/GetTextDocumentWithContextHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(GetTextDocumentWithContextHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(GetTextDocumentWithContextHandler)), Shared] [Method(VSMethods.GetProjectContextsName)] internal class GetTextDocumentWithContextHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs index 80fe6b0bc3760..bd6963b36a625 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLoggerFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler; -[ExportRoslynLspServiceFactory(typeof(RequestTelemetryLogger)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(RequestTelemetryLogger)), Shared] internal class RequestTelemetryLoggerFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs index ef1e959cc2589..bdf588b0bddec 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandlerFactory.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens { - [ExportRoslynLspServiceFactory(typeof(SemanticTokensRangeHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(SemanticTokensRangeHandler)), Shared] internal sealed class SemanticTokensRangeHandlerFactory : ILspServiceFactory { private readonly IGlobalOptionService _globalOptions; diff --git a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs index 50c0c0884fe42..afe0b832bc40a 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs @@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - [ExportRoslynStatelessLspService(typeof(SignatureHelpHandler)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(SignatureHelpHandler)), Shared] [Method(LSP.Methods.TextDocumentSignatureHelpName)] internal class SignatureHelpHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs index de1c4107202ea..be552fd44e98e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/DocumentSpellCheckHandlerFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { - [ExportRoslynLspServiceFactory(typeof(DocumentSpellCheckHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(DocumentSpellCheckHandler)), Shared] internal class DocumentSpellCheckHandlerFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs index e674d291c14b5..8cf8978d354f2 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SpellCheck/WorkspaceSpellCheckHandlerFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SpellCheck { - [ExportRoslynLspServiceFactory(typeof(WorkspaceSpellCheckHandler)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(WorkspaceSpellCheckHandler)), Shared] internal class WorkspaceSpellCheckHandlerFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs index ac31a6b36a41e..d7aa7adc9d846 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportLspServiceFactoryAttribute.cs @@ -36,7 +36,7 @@ internal class ExportLspServiceFactoryAttribute : ExportAttribute /// public bool IsStateless { get; } = false; - public ExportLspServiceFactoryAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspServiceFactory)) + public ExportLspServiceFactoryAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.Any) : base(contractName, typeof(ILspServiceFactory)) { Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); Type = type; diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs deleted file mode 100644 index 2df575f12896f..0000000000000 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportRoslynLspServiceFactoryAttribute.cs +++ /dev/null @@ -1,22 +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.Composition; -using System.Linq; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler; - -/// -/// Defines an easy to use subclass for with the roslyn languages contract name. -/// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] -internal class ExportRoslynLspServiceFactoryAttribute : ExportLspServiceFactoryAttribute -{ - public ExportRoslynLspServiceFactoryAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) - { - } -} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs index 9a75660993287..7b4ac98e2d954 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportStatelessLspServiceAttribute.cs @@ -36,7 +36,7 @@ internal class ExportStatelessLspServiceAttribute : ExportAttribute /// public bool IsStateless { get; } = true; - public ExportStatelessLspServiceAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.NotSpecified) : base(contractName, typeof(ILspService)) + public ExportStatelessLspServiceAttribute(Type type, string contractName, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.Any) : base(contractName, typeof(ILspService)) { Contract.ThrowIfFalse(type.GetInterfaces().Contains(typeof(ILspService)), $"{type.Name} does not inherit from {nameof(ILspService)}"); Type = type; diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs index dba317b36ffeb..243a5c46f2729 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServiceMetadataView.cs @@ -27,7 +27,7 @@ public LspServiceMetadataView(IDictionary metadata) public LspServiceMetadataView(Type type) { Type = type; - ServerKind = WellKnownLspServerKinds.NotSpecified; + ServerKind = WellKnownLspServerKinds.Any; IsStateless = false; } } diff --git a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs index c795f5d568e43..9f4a6dcc21eab 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/LspServices.cs @@ -36,7 +36,7 @@ public LspServices( var services = mefLspServices.Concat(servicesFromFactories); // Make sure that we only include services exported for the specified server kind (or NotSpecified). - services = services.Where(lazyService => lazyService.Metadata.ServerKind == serverKind || lazyService.Metadata.ServerKind == WellKnownLspServerKinds.NotSpecified); + services = services.Where(lazyService => lazyService.Metadata.ServerKind == serverKind || lazyService.Metadata.ServerKind == WellKnownLspServerKinds.Any); // Include the base level services that were passed in. services = services.Concat(baseServices); diff --git a/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs index 646a47dee1226..0e9f3a314a906 100644 --- a/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs +++ b/src/Features/LanguageServer/Protocol/LspServices/RoslynLspServiceProvider.cs @@ -10,12 +10,12 @@ namespace Microsoft.CodeAnalysis.LanguageServer; -[Export(typeof(RoslynLspServiceProvider)), Shared] -internal class RoslynLspServiceProvider : AbstractLspServiceProvider +[Export(typeof(CSharpVisualBasicLspServiceProvider)), Shared] +internal class CSharpVisualBasicLspServiceProvider : AbstractLspServiceProvider { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RoslynLspServiceProvider( + public CSharpVisualBasicLspServiceProvider( [ImportMany(ProtocolConstants.RoslynLspLanguagesContract)] IEnumerable> lspServices, [ImportMany(ProtocolConstants.RoslynLspLanguagesContract)] IEnumerable> lspServiceFactories) : base(lspServices, lspServiceFactories) { diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs index 6c17f43718e01..ac967b0166596 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcherFactory.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - [ExportRoslynLspServiceFactory(typeof(RequestDispatcher)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(RequestDispatcher)), Shared] internal class RequestDispatcherFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs index 85a267b5dfc06..12054488eb478 100644 --- a/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs +++ b/src/Features/LanguageServer/Protocol/WellKnownLspServerKinds.cs @@ -46,7 +46,7 @@ internal enum WellKnownLspServerKinds /// Flag representing any LSP server - used by /// to specify that something applies to any LSP server. /// - NotSpecified, + Any, } internal static class WellKnownLspServerExtensions diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs index a842e103738ce..503ac5913a1a5 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspMiscellaneousFilesWorkspaceFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; -[ExportRoslynLspServiceFactory(typeof(LspMiscellaneousFilesWorkspace), WellKnownLspServerKinds.CSharpVisualBasicLspServer), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(LspMiscellaneousFilesWorkspace), WellKnownLspServerKinds.CSharpVisualBasicLspServer), Shared] internal class LspMiscellaneousFilesWorkspaceFactory : ILspServiceFactory { [ImportingConstructor] diff --git a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs index 07f50399708dc..70c4abd832a50 100644 --- a/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManagerFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; -[ExportRoslynLspServiceFactory(typeof(LspWorkspaceManager)), Shared] +[ExportCSharpVisualBasicLspServiceFactory(typeof(LspWorkspaceManager)), Shared] internal class LspWorkspaceManagerFactory : ILspServiceFactory { private readonly LspWorkspaceRegistrationService _workspaceRegistrationService; diff --git a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs index 2061aa6545885..ad734e817ed6a 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs @@ -100,7 +100,7 @@ private static async Task AssertServerQueueClosed(TestLspServer server) Assert.True(server.GetQueueAccessor().IsComplete()); } - [ExportRoslynLspServiceFactory(typeof(StatefulLspService)), Shared] + [ExportCSharpVisualBasicLspServiceFactory(typeof(StatefulLspService)), Shared] internal class StatefulLspServiceFactory : ILspServiceFactory { [ImportingConstructor] @@ -121,7 +121,7 @@ public void Dispose() } } - [ExportRoslynStatelessLspService(typeof(StatelessLspService)), Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(StatelessLspService)), Shared] internal class StatelessLspService : ILspService, IDisposable { [ImportingConstructor] diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs index a886cd60d915a..3c1534b58ca63 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingMutatingRequestHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(FailingMutatingRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FailingMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class FailingMutatingRequestHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs index ab327838dad05..fbfe182553cee 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/FailingRequestHandler.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(FailingRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(FailingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class FailingRequestHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs index 4b41f63556582..ce693dc292e61 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/LongRunningNonMutatingRequestHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(LongRunningNonMutatingRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(LongRunningNonMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class LongRunningNonMutatingRequestHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs index 715e982f352a4..8df05116b94e4 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/MutatingRequestHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(MutatingRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(MutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class MutatingRequestHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs index 8345b74c6f053..498d899349f17 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonLSPSolutionRequestHandlerProvider.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(NonLSPSolutionRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(NonLSPSolutionRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class NonLSPSolutionRequestHandler : IRequestHandler { diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs index 3ae41bd5a38ba..5b9c35abbba2d 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/NonMutatingRequestHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.RequestOrdering { - [ExportRoslynStatelessLspService(typeof(NonMutatingRequestHandler)), PartNotDiscoverable, Shared] + [ExportCSharpVisualBasicStatelessLspService(typeof(NonMutatingRequestHandler)), PartNotDiscoverable, Shared] [Method(MethodName)] internal class NonMutatingRequestHandler : IRequestHandler { From f63f3de6da9b8cc4b0e2f17648a4b85619b04ad0 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 16 May 2022 10:56:29 -0700 Subject: [PATCH 6/8] correctness --- .../Core/LanguageServer/Handlers/Hover/HoverHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs index ac4b769539980..03bab585bfc54 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/Hover/HoverHandler.cs @@ -27,7 +27,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler /// no longer references VS icon or classified text run types. /// See https://github.com/dotnet/roslyn/issues/55142 /// - [ExportCSharpVisualBasicStatelessLspService(typeof(HoverHandler))] + [ExportCSharpVisualBasicStatelessLspService(typeof(HoverHandler)), Shared] [Method(Methods.TextDocumentHoverName)] internal sealed class HoverHandler : IRequestHandler { From 0f2abd6ed07249fd76c6a8085c062f1dce186d10 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 16 May 2022 11:35:36 -0700 Subject: [PATCH 7/8] fix git add --- ...rpVisualBasicLspServiceFactoryAttribute.cs | 22 +++++++++++++++++++ ...VisualBasicStatelessLspServiceAttribute.cs | 16 ++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicLspServiceFactoryAttribute.cs create mode 100644 src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicStatelessLspServiceAttribute.cs diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicLspServiceFactoryAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicLspServiceFactoryAttribute.cs new file mode 100644 index 0000000000000..641e7f1953f1d --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicLspServiceFactoryAttribute.cs @@ -0,0 +1,22 @@ +// 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.Composition; +using System.Linq; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + +/// +/// Defines an easy to use subclass for with the roslyn languages contract name. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportCSharpVisualBasicLspServiceFactoryAttribute : ExportLspServiceFactoryAttribute +{ + public ExportCSharpVisualBasicLspServiceFactoryAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.Any) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) + { + } +} diff --git a/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicStatelessLspServiceAttribute.cs b/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicStatelessLspServiceAttribute.cs new file mode 100644 index 0000000000000..f17276c139431 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspServices/ExportCSharpVisualBasicStatelessLspServiceAttribute.cs @@ -0,0 +1,16 @@ +// 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; + +namespace Microsoft.CodeAnalysis.LanguageServer.Handler; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] +internal class ExportCSharpVisualBasicStatelessLspServiceAttribute : ExportStatelessLspServiceAttribute +{ + public ExportCSharpVisualBasicStatelessLspServiceAttribute(Type type, WellKnownLspServerKinds serverKind = WellKnownLspServerKinds.Any) : base(type, ProtocolConstants.RoslynLspLanguagesContract, serverKind) + { + } +} From f48d76c1cbfc41108711337708a241bd92936077 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 16 May 2022 13:54:34 -0700 Subject: [PATCH 8/8] more correctness warnings --- .../Handler/CodeActions/CodeActionsHandlerProvider.cs | 6 +++--- .../Handler/Commands/CreateEventCommandHandler.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs index a55d9aee3445e..16128bb031d60 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/CodeActions/CodeActionsHandlerProvider.cs @@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler { - [ExportStatelessXamlLspService(typeof(CodeActionsHandler))] + [ExportStatelessXamlLspService(typeof(CodeActionsHandler)), Shared] internal class XamlCodeActionsHandler : CodeActionsHandler { [ImportingConstructor] @@ -32,7 +32,7 @@ public XamlCodeActionsHandler( } } - [ExportStatelessXamlLspService(typeof(CodeActionResolveHandler))] + [ExportStatelessXamlLspService(typeof(CodeActionResolveHandler)), Shared] internal class XamlCodeActionResolveHandler : CodeActionResolveHandler { [ImportingConstructor] @@ -45,7 +45,7 @@ public XamlCodeActionResolveHandler( } } - [ExportStatelessXamlLspService(typeof(RunCodeActionHandler))] + [ExportStatelessXamlLspService(typeof(RunCodeActionHandler)), Shared] internal class XamlRunCodeActionHandler : RunCodeActionHandler { [ImportingConstructor] diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs index 36ac9e22200eb..ea5a9abe25cc5 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Commands/CreateEventCommandHandler.cs @@ -23,7 +23,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Xaml.LanguageServer.Handler /// /// Handle the command that adds an event handler method in code /// - [ExportStatelessXamlLspService(typeof(CreateEventCommandHandler))] + [ExportStatelessXamlLspService(typeof(CreateEventCommandHandler)), Shared] [Command(StringConstants.CreateEventHandlerCommand)] internal class CreateEventCommandHandler : AbstractExecuteWorkspaceCommandHandler {