Exemple #1
0
        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;
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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;
        }
Exemple #5
0
        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 })
Exemple #7
0
        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
                });
            }
Exemple #8
0
 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);
 }
Exemple #9
0
 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);
 }
Exemple #10
0
        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;
            }
        }
Exemple #12
0
        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;
            }
        }
Exemple #13
0
 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
                ));
 }
Exemple #14
0
 public TestAccessor(RequestExecutionQueue queue)
 => _queue = queue;
Exemple #15
0
        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);
 }