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); }
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; }
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(); }
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,
public RequestMetrics(string methodName, RequestTelemetryLogger requestTelemetryLogger) { _methodName = methodName; _requestTelemetryLogger = requestTelemetryLogger; _sharedStopWatch = SharedStopwatch.StartNew(); }
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 }); } }