internal LanguageServerTarget( AbstractRequestDispatcherFactory requestDispatcherFactory, JsonRpc jsonRpc, ICapabilitiesProvider capabilitiesProvider, ILspWorkspaceRegistrationService workspaceRegistrationService, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, ILspLogger logger, ImmutableArray <string> supportedLanguages, string?clientName, string userVisibleServerName, string telemetryServerTypeName) { GlobalOptions = globalOptions; RequestDispatcher = requestDispatcherFactory.CreateRequestDispatcher(supportedLanguages); _capabilitiesProvider = capabilitiesProvider; WorkspaceRegistrationService = workspaceRegistrationService; Logger = logger; JsonRpc = jsonRpc; JsonRpc.AddLocalRpcTarget(this); JsonRpc.Disconnected += JsonRpc_Disconnected; Listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); ClientName = clientName; _userVisibleServerName = userVisibleServerName; TelemetryServerName = telemetryServerTypeName; Queue = new RequestExecutionQueue(logger, workspaceRegistrationService, globalOptions, supportedLanguages, userVisibleServerName, TelemetryServerName); Queue.RequestServerShutdown += RequestExecutionQueue_Errored; }
public Task <ResponseType?> ExecuteRequestAsync <RequestType, ResponseType>( RequestExecutionQueue queue, string methodName, RequestType request, LSP.ClientCapabilities clientCapabilities, string?clientName, CancellationToken cancellationToken) where RequestType : class { Contract.ThrowIfNull(request); Contract.ThrowIfTrue(string.IsNullOrEmpty(methodName), "Invalid method name"); if (request is ExecuteCommandParams executeCommandRequest) { // If we have a workspace/executeCommand request, get the request name // from the command name. methodName = AbstractExecuteWorkspaceCommandHandler.GetRequestNameForCommandName(executeCommandRequest.Command); } var handlerEntry = _requestHandlers[methodName]; Contract.ThrowIfNull(handlerEntry, string.Format("Request handler entry not found for method {0}", methodName)); var mutatesSolutionState = handlerEntry.Value.MutatesSolutionState; var requiresLSPSolution = handlerEntry.Value.RequiresLSPSolution; var handler = (IRequestHandler <RequestType, ResponseType>?)handlerEntry.Value; Contract.ThrowIfNull(handler, string.Format("Request handler not found for method {0}", methodName)); return(ExecuteRequestAsync(queue, request, clientCapabilities, clientName, methodName, mutatesSolutionState, requiresLSPSolution, handler, cancellationToken)); }
private static async Task InsertTextAsync( RequestExecutionQueue queue, LanguageServerProtocol server, Document document, int position, string text) { var sourceText = await document.GetTextAsync(); var lineInfo = sourceText.Lines.GetLinePositionSpan(new TextSpan(position, 0)); await server.ExecuteRequestAsync <DidChangeTextDocumentParams, object>( queue, Methods.TextDocumentDidChangeName, new DidChangeTextDocumentParams { TextDocument = ProtocolConversions.DocumentToVersionedTextDocumentIdentifier(document), ContentChanges = new TextDocumentContentChangeEvent[] { new TextDocumentContentChangeEvent { Range = new LSP.Range { Start = ProtocolConversions.LinePositionToPosition(lineInfo.Start), End = ProtocolConversions.LinePositionToPosition(lineInfo.End), }, Text = text, }, }, }, new LSP.ClientCapabilities(), clientName : null, CancellationToken.None); }
public InProcLanguageServer(Stream inputStream, Stream outputStream, AbstractRequestHandlerProvider requestHandlerProvider, CodeAnalysis.Workspace workspace, IDiagnosticService diagnosticService, IAsynchronousOperationListenerProvider listenerProvider, ILspSolutionProvider solutionProvider, string?clientName) { _requestHandlerProvider = requestHandlerProvider; _workspace = workspace; var jsonMessageFormatter = new JsonMessageFormatter(); jsonMessageFormatter.JsonSerializer.Converters.Add(new VSExtensionConverter <TextDocumentIdentifier, VSTextDocumentIdentifier>()); jsonMessageFormatter.JsonSerializer.Converters.Add(new VSExtensionConverter <ClientCapabilities, VSClientCapabilities>()); _jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, jsonMessageFormatter)); _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.StartListening(); _diagnosticService = diagnosticService; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); _clientName = clientName; _diagnosticService.DiagnosticsUpdated += DiagnosticService_DiagnosticsUpdated; _clientCapabilities = new VSClientCapabilities(); _queue = new RequestExecutionQueue(solutionProvider); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; }
internal LanguageServerTarget( AbstractRequestDispatcherFactory requestDispatcherFactory, JsonRpc jsonRpc, ICapabilitiesProvider capabilitiesProvider, LspWorkspaceRegistrationService workspaceRegistrationService, LspMiscellaneousFilesWorkspace?lspMiscellaneousFilesWorkspace, IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider, ILspLogger logger, ImmutableArray <string> supportedLanguages, string?clientName, WellKnownLspServerKinds serverKind) { _requestDispatcher = requestDispatcherFactory.CreateRequestDispatcher(serverKind); _capabilitiesProvider = capabilitiesProvider; _logger = logger; _jsonRpc = jsonRpc; _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.Disconnected += JsonRpc_Disconnected; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); _clientName = clientName; _queue = new RequestExecutionQueue( logger, workspaceRegistrationService, lspMiscellaneousFilesWorkspace, globalOptions, supportedLanguages, serverKind); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; var entryPointMethod = typeof(DelegatingEntryPoint).GetMethod(nameof(DelegatingEntryPoint.EntryPointAsync)); Contract.ThrowIfNull(entryPointMethod, $"{typeof(DelegatingEntryPoint).FullName} is missing method {nameof(DelegatingEntryPoint.EntryPointAsync)}"); foreach (var metadata in _requestDispatcher.GetRegisteredMethods()) { // Instead of concretely defining methods for each LSP method, we instead dynamically construct // the generic method info from the exported handler types. This allows us to define multiple handlers for the same method // but different type parameters. This is a key functionality to support TS external access as we do not want to couple // our LSP protocol version dll to theirs. // // We also do not use the StreamJsonRpc support for JToken as the rpc method parameters because we want // StreamJsonRpc to do the deserialization to handle streaming requests using IProgress<T>. var delegatingEntryPoint = new DelegatingEntryPoint(metadata.MethodName, this); var genericEntryPointMethod = entryPointMethod.MakeGenericMethod(metadata.RequestType, metadata.ResponseType); _jsonRpc.AddLocalRpcMethod(genericEntryPointMethod, delegatingEntryPoint, new JsonRpcMethodAttribute(metadata.MethodName) { UseSingleObjectParameterDeserialization = true }); } }
protected override async Task <ResponseType?> ExecuteRequestAsync <RequestType, ResponseType>( RequestExecutionQueue queue, RequestType request, ClientCapabilities clientCapabilities, string?clientName, string methodName, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler <RequestType, ResponseType> handler, CancellationToken cancellationToken) where RequestType : class where ResponseType : default { var textDocument = handler.GetTextDocumentIdentifier(request); DocumentId?documentId = null; if (textDocument is { Uri : { IsAbsoluteUri : true } documentUri })
internal LanguageServerTarget( AbstractLspServiceProvider lspServiceProvider, JsonRpc jsonRpc, ICapabilitiesProvider capabilitiesProvider, IAsynchronousOperationListenerProvider listenerProvider, ILspLogger logger, ImmutableArray <string> supportedLanguages, WellKnownLspServerKinds serverKind) { _capabilitiesProvider = capabilitiesProvider; _logger = logger; _jsonRpc = jsonRpc; _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.Disconnected += JsonRpc_Disconnected; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); // Add services that require base dependencies (jsonrpc) or are more complex to create to the set manually. _lspServices = lspServiceProvider.CreateServices(serverKind, ImmutableArray.Create( CreateLspServiceInstance <ILanguageServerNotificationManager>(new LanguageServerNotificationManager(_jsonRpc)), CreateLspServiceInstance(logger), CreateLspServiceInstance <IClientCapabilitiesProvider>(this))); _queue = new RequestExecutionQueue( supportedLanguages, serverKind, _lspServices); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; _requestDispatcher = _lspServices.GetRequiredService <RequestDispatcher>(); var entryPointMethod = typeof(DelegatingEntryPoint).GetMethod(nameof(DelegatingEntryPoint.EntryPointAsync)); Contract.ThrowIfNull(entryPointMethod, $"{typeof(DelegatingEntryPoint).FullName} is missing method {nameof(DelegatingEntryPoint.EntryPointAsync)}"); foreach (var metadata in _requestDispatcher.GetRegisteredMethods()) { // Instead of concretely defining methods for each LSP method, we instead dynamically construct the // generic method info from the exported handler types. This allows us to define multiple handlers for // the same method but different type parameters. This is a key functionality to support TS external // access as we do not want to couple our LSP protocol version dll to theirs. // // We also do not use the StreamJsonRpc support for JToken as the rpc method parameters because we want // StreamJsonRpc to do the deserialization to handle streaming requests using IProgress<T>. var delegatingEntryPoint = new DelegatingEntryPoint(metadata.MethodName, this); var genericEntryPointMethod = entryPointMethod.MakeGenericMethod(metadata.RequestType, metadata.ResponseType); _jsonRpc.AddLocalRpcMethod(genericEntryPointMethod, delegatingEntryPoint, new JsonRpcMethodAttribute(metadata.MethodName) { UseSingleObjectParameterDeserialization = true }); }
private static async Task CloseDocumentAsync(RequestExecutionQueue queue, LanguageServerProtocol server, Document document) { await server.ExecuteRequestAsync <DidCloseTextDocumentParams, object>( queue, Methods.TextDocumentDidCloseName, new DidCloseTextDocumentParams { TextDocument = new TextDocumentIdentifier { Uri = document.GetURI(), } }, new LSP.ClientCapabilities(), clientName : null, CancellationToken.None); }
private static async Task OpenDocumentAsync(RequestExecutionQueue queue, LanguageServerProtocol server, Document document) { await server.ExecuteRequestAsync <DidOpenTextDocumentParams, object>( queue, Methods.TextDocumentDidOpenName, new DidOpenTextDocumentParams { TextDocument = new TextDocumentItem { Uri = document.GetURI(), Text = document.GetTextSynchronously(CancellationToken.None).ToString(), } }, new LSP.ClientCapabilities(), clientName : null, CancellationToken.None); }
public Task <ResponseType> ExecuteRequestAsync <RequestType, ResponseType>(RequestExecutionQueue queue, string methodName, RequestType request, LSP.ClientCapabilities clientCapabilities, string?clientName, CancellationToken cancellationToken) where RequestType : class { Contract.ThrowIfNull(request); Contract.ThrowIfTrue(string.IsNullOrEmpty(methodName), "Invalid method name"); var handlerEntry = _requestHandlers[methodName]; Contract.ThrowIfNull(handlerEntry, string.Format("Request handler entry not found for method {0}", methodName)); var mutatesSolutionState = handlerEntry.Metadata.MutatesSolutionState; var handler = (IRequestHandler <RequestType, ResponseType>?)handlerEntry.Value; Contract.ThrowIfNull(handler, string.Format("Request handler not found for method {0}", methodName)); return(queue.ExecuteAsync(mutatesSolutionState, handler, request, clientCapabilities, clientName, cancellationToken)); }
public InProcLanguageServer( AbstractInProcLanguageClient languageClient, Stream inputStream, Stream outputStream, AbstractRequestHandlerProvider requestHandlerProvider, Workspace workspace, IDiagnosticService?diagnosticService, IAsynchronousOperationListenerProvider listenerProvider, ILspSolutionProvider solutionProvider, string?clientName) { _languageClient = languageClient; _requestHandlerProvider = requestHandlerProvider; _workspace = workspace; var jsonMessageFormatter = new JsonMessageFormatter(); jsonMessageFormatter.JsonSerializer.Converters.Add(new VSExtensionConverter <TextDocumentIdentifier, VSTextDocumentIdentifier>()); jsonMessageFormatter.JsonSerializer.Converters.Add(new VSExtensionConverter <ClientCapabilities, VSClientCapabilities>()); _jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, jsonMessageFormatter)); _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.StartListening(); _diagnosticService = diagnosticService; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); _clientName = clientName; _queue = new RequestExecutionQueue(solutionProvider); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; // Dedupe on DocumentId. If we hear about the same document multiple times, we only need to process that id once. _diagnosticsWorkQueue = new AsyncBatchingWorkQueue <DocumentId>( TimeSpan.FromMilliseconds(250), ProcessDiagnosticUpdatedBatchAsync, EqualityComparer <DocumentId> .Default, _listener, _queue.CancellationToken); if (_diagnosticService != null) { _diagnosticService.DiagnosticsUpdated += DiagnosticService_DiagnosticsUpdated; } }
private InProcLanguageServer( AbstractInProcLanguageClient languageClient, RequestDispatcher requestDispatcher, Workspace workspace, IDiagnosticService?diagnosticService, IAsynchronousOperationListenerProvider listenerProvider, ILspWorkspaceRegistrationService lspWorkspaceRegistrationService, string serverTypeName, string?clientName, JsonRpc jsonRpc, LogHubLspLogger?logger) { _languageClient = languageClient; _requestDispatcher = requestDispatcher; _workspace = workspace; _logger = logger; _jsonRpc = jsonRpc; _jsonRpc.AddLocalRpcTarget(this); _jsonRpc.StartListening(); _diagnosticService = diagnosticService; _listener = listenerProvider.GetListener(FeatureAttribute.LanguageServer); _clientName = clientName; _queue = new RequestExecutionQueue(logger ?? NoOpLspLogger.Instance, lspWorkspaceRegistrationService, languageClient.Name, serverTypeName); _queue.RequestServerShutdown += RequestExecutionQueue_Errored; // Dedupe on DocumentId. If we hear about the same document multiple times, we only need to process that id once. _diagnosticsWorkQueue = new AsyncBatchingWorkQueue <DocumentId>( TimeSpan.FromMilliseconds(250), ProcessDiagnosticUpdatedBatchAsync, EqualityComparer <DocumentId> .Default, _listener, _queue.CancellationToken); if (_diagnosticService != null) { _diagnosticService.DiagnosticsUpdated += DiagnosticService_DiagnosticsUpdated; } }
protected virtual Task <ResponseType> ExecuteRequestAsync <RequestType, ResponseType>( RequestExecutionQueue queue, RequestType request, ClientCapabilities clientCapabilities, string?clientName, string methodName, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler <RequestType, ResponseType> handler, CancellationToken cancellationToken ) where RequestType : class { return(queue.ExecuteAsync( mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, clientName, methodName, cancellationToken )); }
public TestAccessor(RequestExecutionQueue queue) => _queue = queue;
protected override Task <ResponseType> ExecuteRequestAsync <RequestType, ResponseType>(RequestExecutionQueue queue, RequestType request, ClientCapabilities clientCapabilities, string?clientName, string methodName, bool mutatesSolutionState, IRequestHandler <RequestType, ResponseType> handler, CancellationToken cancellationToken) { var textDocument = handler.GetTextDocumentIdentifier(request); if (textDocument is { Uri : { IsAbsoluteUri : true } documentUri })
private static async Task DidClose(RequestExecutionQueue queue, Solution solution, LSP.DidCloseTextDocumentParams didCloseParams) { await GetLanguageServer(solution).ExecuteRequestAsync <LSP.DidCloseTextDocumentParams, object>(queue, Methods.TextDocumentDidCloseName, didCloseParams, new LSP.ClientCapabilities(), null, CancellationToken.None); }