public QueueItem(
                bool mutatesSolutionState,
                bool requiresLSPSolution,
                ClientCapabilities clientCapabilities,
                string methodName,
                TextDocumentIdentifier?textDocument,
                TRequestType request,
                IRequestHandler <TRequestType, TResponseType> handler,
                Guid activityId,
                ILspLogger logger,
                RequestTelemetryLogger telemetryLogger,
                CancellationToken cancellationToken)
            {
                _completionSource = new TaskCompletionSource <TResponseType?>();
                // Set the tcs state to cancelled if the token gets cancelled outside of our callback (for example the server shutting down).
                cancellationToken.Register(() => _completionSource.TrySetCanceled(cancellationToken));

                Metrics = new RequestMetrics(methodName, telemetryLogger);

                _handler = handler;
                _logger  = logger;
                _request = request;

                ActivityId           = activityId;
                MutatesSolutionState = mutatesSolutionState;
                RequiresLSPSolution  = requiresLSPSolution;
                ClientCapabilities   = clientCapabilities;
                MethodName           = methodName;
                TextDocument         = textDocument;
            }
            public static (IQueueItem, Task <TResponseType?>) Create(
                bool mutatesSolutionState,
                bool requiresLSPSolution,
                ClientCapabilities clientCapabilities,
                string methodName,
                TextDocumentIdentifier?textDocument,
                TRequestType request,
                IRequestHandler <TRequestType, TResponseType> handler,
                Guid activityId,
                ILspLogger logger,
                RequestTelemetryLogger telemetryLogger,
                CancellationToken cancellationToken)
            {
                var queueItem = new QueueItem <TRequestType, TResponseType>(
                    mutatesSolutionState,
                    requiresLSPSolution,
                    clientCapabilities,
                    methodName,
                    textDocument,
                    request,
                    handler,
                    activityId,
                    logger,
                    telemetryLogger,
                    cancellationToken);

                return(queueItem, queueItem._completionSource.Task);
            }
Exemplo n.º 3
0
            public QueueItem(
                bool mutatesSolutionState,
                bool requiresLSPSolution,
                ClientCapabilities clientCapabilities,
                string?clientName,
                string methodName,
                TextDocumentIdentifier?textDocument,
                Guid activityId,
                ILspLogger logger,
                RequestTelemetryLogger telemetryLogger,
                Action <Exception> handleQueueFailure,
                Func <RequestContext?, CancellationToken, Task> callbackAsync,
                CancellationToken cancellationToken)
            {
                Metrics = new RequestMetrics(methodName, telemetryLogger);

                _callbackAsync = callbackAsync;
                _logger        = logger;

                ActivityId           = activityId;
                MutatesSolutionState = mutatesSolutionState;
                RequiresLSPSolution  = requiresLSPSolution;
                ClientCapabilities   = clientCapabilities;
                ClientName           = clientName;
                MethodName           = methodName;
                TextDocument         = textDocument;
                HandleQueueFailure   = handleQueueFailure;
                CancellationToken    = cancellationToken;
            }
Exemplo n.º 4
0
        public RequestExecutionQueue(
            ILspLogger logger,
            LspWorkspaceRegistrationService lspWorkspaceRegistrationService,
            LspMiscellaneousFilesWorkspace?lspMiscellaneousFilesWorkspace,
            IGlobalOptionService globalOptions,
            ImmutableArray <string> supportedLanguages,
            string serverName,
            string serverTypeName)
        {
            _logger             = logger;
            _globalOptions      = globalOptions;
            _supportedLanguages = supportedLanguages;
            _serverName         = serverName;

            _queue        = new AsyncQueue <QueueItem>();
            _cancelSource = new CancellationTokenSource();

            // 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(serverTypeName);

            _lspWorkspaceManager = new LspWorkspaceManager(logger, lspMiscellaneousFilesWorkspace, lspWorkspaceRegistrationService, _requestTelemetryLogger);

            // Start the queue processing
            _ = ProcessQueueAsync();
        }
Exemplo n.º 5
0
 public static RequestContext Create(
     bool requiresLSPSolution,
     TextDocumentIdentifier?textDocument,
     string?clientName,
     ILspLogger _logger,
     RequestTelemetryLogger telemetryLogger,
     ClientCapabilities clientCapabilities,
     ILspWorkspaceRegistrationService lspWorkspaceRegistrationService,
     Dictionary <Workspace, (Solution workspaceSolution, Solution lspSolution)>?solutionCache,
Exemplo n.º 6
0
 public RequestMetrics(string methodName, RequestTelemetryLogger requestTelemetryLogger)
 {
     _methodName             = methodName;
     _requestTelemetryLogger = requestTelemetryLogger;
     _sharedStopWatch        = SharedStopwatch.StartNew();
 }
Exemplo n.º 7
0
        internal LanguageServerTarget(
            AbstractRequestDispatcherFactory requestDispatcherFactory,
            JsonRpc jsonRpc,
            ICapabilitiesProvider capabilitiesProvider,
            LspWorkspaceRegistrationService workspaceRegistrationService,
            LspMiscellaneousFilesWorkspace?lspMiscellaneousFilesWorkspace,
            IGlobalOptionService globalOptions,
            IAsynchronousOperationListenerProvider listenerProvider,
            ILspLogger logger,
            ImmutableArray <string> supportedLanguages,
            WellKnownLspServerKinds serverKind)
        {
            _requestDispatcher = requestDispatcherFactory.CreateRequestDispatcher(serverKind);

            _capabilitiesProvider = capabilitiesProvider;
            _logger = logger;

            _jsonRpc = jsonRpc;
            _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);

            _queue = new RequestExecutionQueue(
                logger,
                globalOptions,
                supportedLanguages,
                serverKind,
                _requestTelemetryLogger,
                _lspWorkspaceManager,
                _notificationManager);
            _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
                });
            }
        }