private ILspHandlerDescriptor FindDescriptor(string method, JToken @params) { _logger.LogDebug("Finding descriptor for {Method}", method); var descriptor = _collection.FirstOrDefault(x => x.Method == method); if (descriptor is null) { _logger.LogDebug("Unable to find {Method}, methods found include {Methods}", method, string.Join(", ", _collection.Select(x => x.Method + ":" + x.Handler?.GetType()?.FullName))); return(null); } if (@params == null || descriptor.Params == null) { return(descriptor); } var lspHandlerDescriptors = _collection.Where(handler => handler.Method == method).ToList(); if (lspHandlerDescriptors.Count == 1) { return(descriptor); } var paramsValue = @params.ToObject(descriptor.Params, _serializer.JsonSerializer); return(_handlerMatchers.SelectMany(strat => strat.FindHandler(paramsValue, lspHandlerDescriptors)).FirstOrDefault() ?? descriptor); }
private IRequestDescriptor <ILspHandlerDescriptor> FindDescriptor(string method, JToken? @params) { _logger.LogDebug("Finding descriptors for {Method}", method); var descriptor = _collection.FirstOrDefault(x => x.Method == method); if (descriptor is null) { _logger.LogDebug( "Unable to find {Method}, methods found include {Methods}", method, string.Join(", ", _collection.Select(x => x.Method + ":" + x.Handler.GetType().FullName)) ); return(new RequestDescriptor <ILspHandlerDescriptor>()); } if (@params == null || descriptor.Params == null) { return(new RequestDescriptor <ILspHandlerDescriptor>(descriptor)); } object?paramsValue; if (descriptor.IsDelegatingHandler) { var o = @params.ToObject(descriptor.Params.GetGenericArguments()[0], _serializer.JsonSerializer); paramsValue = Activator.CreateInstance(descriptor.Params, o); } else { paramsValue = @params.ToObject(descriptor.Params, _serializer.JsonSerializer); } var lspHandlerDescriptors = _collection.Where(handler => handler.Method == method).ToList(); var matchDescriptor = _handlerMatchers.SelectMany(strat => strat.FindHandler(paramsValue, lspHandlerDescriptors)).ToArray(); if (matchDescriptor.Length > 0) { return(new RequestDescriptor <ILspHandlerDescriptor>(matchDescriptor)); } // execute command is a special case // if no command was found to execute this must error // this is not great coupling but other options require api changes if (paramsValue is IExecuteCommandParams) { return(new RequestDescriptor <ILspHandlerDescriptor>()); } if (lspHandlerDescriptors.Count > 0) { return(new RequestDescriptor <ILspHandlerDescriptor>(lspHandlerDescriptors)); } return(new RequestDescriptor <ILspHandlerDescriptor>()); }
async Task <InitializeResult> IRequestHandler <InitializeParams, InitializeResult> .Handle(InitializeParams request, CancellationToken token) { ClientSettings = request; if (request.Trace == InitializeTrace.Verbose && MinimumLogLevel >= LogLevel.Information) { MinimumLogLevel = LogLevel.Trace; } await Task.WhenAll(_initializeDelegates.Select(c => c(request))); _clientVersion = request.Capabilities.GetClientVersion(); _serializer.SetClientCapabilities(_clientVersion.Value, request.Capabilities); var supportedCapabilites = new List <ISupports>(); if (_clientVersion == ClientVersion.Lsp3) { if (request.Capabilities.TextDocument != null) { supportedCapabilites.AddRange( LspHandlerDescriptorHelpers.GetSupportedCapabilities(request.Capabilities.TextDocument) ); } if (request.Capabilities.Workspace != null) { supportedCapabilites.AddRange( LspHandlerDescriptorHelpers.GetSupportedCapabilities(request.Capabilities.Workspace) ); } } _supportedCapabilities.Add(supportedCapabilites); AddHandlers(_serviceProvider.GetServices <IJsonRpcHandler>().ToArray()); var textDocumentCapabilities = ClientSettings.Capabilities.TextDocument; var workspaceCapabilities = ClientSettings.Capabilities.Workspace; var ccp = new ClientCapabilityProvider(_collection); var serverCapabilities = new ServerCapabilities() { CodeActionProvider = ccp.GetStaticOptions(textDocumentCapabilities.CodeAction).Get <ICodeActionOptions, CodeActionOptions>(CodeActionOptions.Of), CodeLensProvider = ccp.GetStaticOptions(textDocumentCapabilities.CodeLens).Get <ICodeLensOptions, CodeLensOptions>(CodeLensOptions.Of), CompletionProvider = ccp.GetStaticOptions(textDocumentCapabilities.Completion).Get <ICompletionOptions, CompletionOptions>(CompletionOptions.Of), DefinitionProvider = ccp.HasStaticHandler(textDocumentCapabilities.Definition), DocumentFormattingProvider = ccp.HasStaticHandler(textDocumentCapabilities.Formatting), DocumentHighlightProvider = ccp.HasStaticHandler(textDocumentCapabilities.DocumentHighlight), DocumentLinkProvider = ccp.GetStaticOptions(textDocumentCapabilities.DocumentLink).Get <IDocumentLinkOptions, DocumentLinkOptions>(DocumentLinkOptions.Of), DocumentOnTypeFormattingProvider = ccp.GetStaticOptions(textDocumentCapabilities.OnTypeFormatting).Get <IDocumentOnTypeFormattingOptions, DocumentOnTypeFormattingOptions>(DocumentOnTypeFormattingOptions.Of), DocumentRangeFormattingProvider = ccp.HasStaticHandler(textDocumentCapabilities.RangeFormatting), DocumentSymbolProvider = ccp.HasStaticHandler(textDocumentCapabilities.DocumentSymbol), ExecuteCommandProvider = ccp.GetStaticOptions(workspaceCapabilities.ExecuteCommand).Reduce <IExecuteCommandOptions, ExecuteCommandOptions>(ExecuteCommandOptions.Of), HoverProvider = ccp.HasStaticHandler(textDocumentCapabilities.Hover), ReferencesProvider = ccp.HasStaticHandler(textDocumentCapabilities.References), RenameProvider = ccp.GetStaticOptions(textDocumentCapabilities.Rename).Get <IRenameOptions, RenameOptions>(RenameOptions.Of), SignatureHelpProvider = ccp.GetStaticOptions(textDocumentCapabilities.SignatureHelp).Get <ISignatureHelpOptions, SignatureHelpOptions>(SignatureHelpOptions.Of), WorkspaceSymbolProvider = ccp.HasStaticHandler(workspaceCapabilities.Symbol), ImplementationProvider = ccp.GetStaticOptions(textDocumentCapabilities.Implementation).Get <IImplementationOptions, ImplementationOptions>(ImplementationOptions.Of), TypeDefinitionProvider = ccp.GetStaticOptions(textDocumentCapabilities.TypeDefinition).Get <ITypeDefinitionOptions, TypeDefinitionOptions>(TypeDefinitionOptions.Of), ColorProvider = ccp.GetStaticOptions(textDocumentCapabilities.ColorProvider).Get <IColorOptions, ColorOptions>(ColorOptions.Of), FoldingRangeProvider = ccp.GetStaticOptions(textDocumentCapabilities.FoldingRangeProvider).Get <IFoldingRangeOptions, FoldingRangeOptions>(FoldingRangeOptions.Of), }; if (_collection.ContainsHandler(typeof(IDidChangeWorkspaceFoldersHandler))) { serverCapabilities.Workspace = new WorkspaceServerCapabilities() { WorkspaceFolders = new WorkspaceFolderOptions() { Supported = true, ChangeNotifications = Guid.NewGuid().ToString() } }; } var textDocumentSyncKind = _collection.ContainsHandler(typeof(IDidChangeTextDocumentHandler)) ? _collection .Select(x => x.Handler) .OfType <IDidChangeTextDocumentHandler>() .Where(x => x.Change != TextDocumentSyncKind.None) .Min(z => z.Change) : TextDocumentSyncKind.None; if (_clientVersion == ClientVersion.Lsp2) { serverCapabilities.TextDocumentSync = textDocumentSyncKind; } else { serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions() { Change = textDocumentSyncKind, OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)), Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) ? new SaveOptions() { IncludeText = true /* TODO: Make configurable */ } : null, WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)), WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler)) }; } // TODO: Need a call back here // serverCapabilities.Experimental; _reciever.Initialized(); var result = ServerSettings = new InitializeResult() { Capabilities = serverCapabilities }; await Task.WhenAll(_initializedDelegates.Select(c => c(request, result))); // TODO: if (_clientVersion == ClientVersion.Lsp2) { // Small delay to let client respond await Task.Delay(100, token); _initializeComplete.OnNext(result); _initializeComplete.OnCompleted(); } return(result); }
async Task <InitializeResult> IRequestHandler <InitializeParams, InitializeResult> .Handle( InitializeParams request, CancellationToken token) { ClientSettings = request; if (request.Trace == InitializeTrace.Verbose) { var loggerSettings = _serviceProvider.GetService <LanguageServerLoggerSettings>(); if (loggerSettings?.MinimumLogLevel <= LogLevel.Information) { loggerSettings.MinimumLogLevel = LogLevel.Trace; } var optionsMonitor = _serviceProvider.GetService <IOptionsMonitor <LoggerFilterOptions> >() as LanguageServerLoggerFilterOptions; if (optionsMonitor?.CurrentValue.MinLevel <= LogLevel.Information) { optionsMonitor.CurrentValue.MinLevel = LogLevel.Trace; optionsMonitor.Set(optionsMonitor.CurrentValue); } } _clientVersion = request.Capabilities?.GetClientVersion() ?? ClientVersion.Lsp2; _serializer.SetClientCapabilities(_clientVersion.Value, request.Capabilities); var supportedCapabilities = new List <ISupports>(); if (_clientVersion == ClientVersion.Lsp3) { if (request.Capabilities.TextDocument != null) { supportedCapabilities.AddRange( LspHandlerDescriptorHelpers.GetSupportedCapabilities(request.Capabilities.TextDocument) ); } if (request.Capabilities.Workspace != null) { supportedCapabilities.AddRange( LspHandlerDescriptorHelpers.GetSupportedCapabilities(request.Capabilities.Workspace) ); } } _supportedCapabilities.Add(supportedCapabilities); ClientSettings.Capabilities ??= new ClientCapabilities(); var textDocumentCapabilities = ClientSettings.Capabilities.TextDocument ??= new TextDocumentClientCapabilities(); var workspaceCapabilities = ClientSettings.Capabilities.Workspace ??= new WorkspaceClientCapabilities(); var windowCapabilities = ClientSettings.Capabilities.Window ??= new WindowClientCapabilities(); _serverWorkDoneManager.Initialized(windowCapabilities); { RegisterHandlers(_collection); } await Task.WhenAll(_initializeDelegates.Select(c => c(this, request, token))); var ccp = new ClientCapabilityProvider(_collection, windowCapabilities.WorkDoneProgress); var serverCapabilities = new ServerCapabilities() { CodeActionProvider = ccp.GetStaticOptions(textDocumentCapabilities.CodeAction) .Get <ICodeActionOptions, CodeActionOptions>(CodeActionOptions.Of), CodeLensProvider = ccp.GetStaticOptions(textDocumentCapabilities.CodeLens) .Get <ICodeLensOptions, CodeLensOptions>(CodeLensOptions.Of), CompletionProvider = ccp.GetStaticOptions(textDocumentCapabilities.Completion) .Get <ICompletionOptions, CompletionOptions>(CompletionOptions.Of), DefinitionProvider = ccp.GetStaticOptions(textDocumentCapabilities.Definition) .Get <IDefinitionOptions, DefinitionOptions>(DefinitionOptions.Of), DocumentFormattingProvider = ccp.GetStaticOptions(textDocumentCapabilities.Formatting) .Get <IDocumentFormattingOptions, DocumentFormattingOptions>(DocumentFormattingOptions.Of), DocumentHighlightProvider = ccp.GetStaticOptions(textDocumentCapabilities.DocumentHighlight) .Get <IDocumentHighlightOptions, DocumentHighlightOptions>(DocumentHighlightOptions.Of), DocumentLinkProvider = ccp.GetStaticOptions(textDocumentCapabilities.DocumentLink) .Get <IDocumentLinkOptions, DocumentLinkOptions>(DocumentLinkOptions.Of), DocumentOnTypeFormattingProvider = ccp.GetStaticOptions(textDocumentCapabilities.OnTypeFormatting) .Get <IDocumentOnTypeFormattingOptions, DocumentOnTypeFormattingOptions>( DocumentOnTypeFormattingOptions.Of), DocumentRangeFormattingProvider = ccp.GetStaticOptions(textDocumentCapabilities.RangeFormatting) .Get <IDocumentRangeFormattingOptions, DocumentRangeFormattingOptions>(DocumentRangeFormattingOptions .Of), DocumentSymbolProvider = ccp.GetStaticOptions(textDocumentCapabilities.DocumentSymbol) .Get <IDocumentSymbolOptions, DocumentSymbolOptions>(DocumentSymbolOptions.Of), ExecuteCommandProvider = ccp.GetStaticOptions(workspaceCapabilities.ExecuteCommand) .Reduce <IExecuteCommandOptions, ExecuteCommandOptions>(ExecuteCommandOptions.Of), TextDocumentSync = ccp.GetStaticOptions(textDocumentCapabilities.Synchronization) .Reduce <ITextDocumentSyncOptions, TextDocumentSyncOptions>(TextDocumentSyncOptions.Of), HoverProvider = ccp.GetStaticOptions(textDocumentCapabilities.Hover) .Get <IHoverOptions, HoverOptions>(HoverOptions.Of), ReferencesProvider = ccp.GetStaticOptions(textDocumentCapabilities.References) .Get <IReferencesOptions, ReferencesOptions>(ReferencesOptions.Of), RenameProvider = ccp.GetStaticOptions(textDocumentCapabilities.Rename) .Get <IRenameOptions, RenameOptions>(RenameOptions.Of), SignatureHelpProvider = ccp.GetStaticOptions(textDocumentCapabilities.SignatureHelp) .Get <ISignatureHelpOptions, SignatureHelpOptions>(SignatureHelpOptions.Of), WorkspaceSymbolProvider = ccp.GetStaticOptions(workspaceCapabilities.Symbol) .Get <IWorkspaceSymbolOptions, WorkspaceSymbolOptions>(WorkspaceSymbolOptions.Of), ImplementationProvider = ccp.GetStaticOptions(textDocumentCapabilities.Implementation) .Get <IImplementationOptions, ImplementationOptions>(ImplementationOptions.Of), TypeDefinitionProvider = ccp.GetStaticOptions(textDocumentCapabilities.TypeDefinition) .Get <ITypeDefinitionOptions, TypeDefinitionOptions>(TypeDefinitionOptions.Of), ColorProvider = ccp.GetStaticOptions(textDocumentCapabilities.ColorProvider) .Get <IDocumentColorOptions, DocumentColorOptions>(DocumentColorOptions.Of), FoldingRangeProvider = ccp.GetStaticOptions(textDocumentCapabilities.FoldingRange) .Get <IFoldingRangeOptions, FoldingRangeOptions>(FoldingRangeOptions.Of), SelectionRangeProvider = ccp.GetStaticOptions(textDocumentCapabilities.FoldingRange) .Get <ISelectionRangeOptions, SelectionRangeOptions>(SelectionRangeOptions.Of), DeclarationProvider = ccp.GetStaticOptions(textDocumentCapabilities.Declaration) .Get <IDeclarationOptions, DeclarationOptions>(DeclarationOptions.Of), #pragma warning disable 618 CallHierarchyProvider = ccp.GetStaticOptions(textDocumentCapabilities.CallHierarchy) .Get <ICallHierarchyOptions, CallHierarchyOptions>(CallHierarchyOptions.Of), SemanticTokensProvider = ccp.GetStaticOptions(textDocumentCapabilities.SemanticTokens) .Get <ISemanticTokensOptions, SemanticTokensOptions>(SemanticTokensOptions.Of), #pragma warning restore 618 }; if (_collection.ContainsHandler(typeof(IDidChangeWorkspaceFoldersHandler))) { serverCapabilities.Workspace = new WorkspaceServerCapabilities() { WorkspaceFolders = new WorkspaceFolderOptions() { Supported = true, ChangeNotifications = Guid.NewGuid().ToString() } }; } if (ccp.HasStaticHandler(textDocumentCapabilities.Synchronization)) { var textDocumentSyncKind = TextDocumentSyncKind.None; if (_collection.ContainsHandler(typeof(IDidChangeTextDocumentHandler))) { var kinds = _collection .Select(x => x.Handler) .OfType <IDidChangeTextDocumentHandler>() .Select(x => x.GetRegistrationOptions()?.SyncKind ?? TextDocumentSyncKind.None) .Where(x => x != TextDocumentSyncKind.None) .ToArray(); if (kinds.Any()) { textDocumentSyncKind = kinds.Min(z => z); } } if (_clientVersion == ClientVersion.Lsp2) { serverCapabilities.TextDocumentSync = textDocumentSyncKind; } else { serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions() { Change = textDocumentSyncKind, OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)), Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) ? new SaveOptions() { IncludeText = true /* TODO: Make configurable */ } : null, WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)), WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler)) }; } } // TODO: Need a call back here // serverCapabilities.Experimental; _serverReceiver.Initialized(); var result = ServerSettings = new InitializeResult() { Capabilities = serverCapabilities, ServerInfo = _serverInfo ?? new ServerInfo() { Name = Assembly.GetEntryAssembly()?.GetName().Name, Version = Assembly.GetEntryAssembly()?.GetCustomAttribute <AssemblyInformationalVersionAttribute>() ?.InformationalVersion ?? Assembly.GetEntryAssembly()?.GetCustomAttribute <AssemblyVersionAttribute>()?.Version } }; await Task.WhenAll(_initializedDelegates.Select(c => c(this, request, result, token))); foreach (var item in _collection) { LspHandlerDescriptorHelpers.InitializeHandler(item, _supportedCapabilities, item.Handler); } // TODO: if (_clientVersion == ClientVersion.Lsp2) { _initializeComplete.OnNext(result); _initializeComplete.OnCompleted(); } return(result); }
private ILspHandlerDescriptor FindDescriptor(string method, JToken @params) { _logger.LogDebug("Finding descriptor for {Method}", method); var descriptor = _collection.FirstOrDefault(x => x.Method == method); if (descriptor is null) { _logger.LogDebug("Unable to find {Method}, methods found include {Methods}", method, string.Join(", ", _collection.Select(x => x.Method + ":" + x.Handler.GetType().FullName))); return(null); } if (@params != null && descriptor.Params != null) { var paramsValue = @params.ToObject(descriptor.Params); if (paramsValue is ITextDocumentIdentifierParams textDocumentIdentifierParams) { var attributes = GetTextDocumentAttributes(textDocumentIdentifierParams.TextDocument.Uri); _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.LanguageId}:{x.Scheme}:{x.Uri}")); return(GetHandler(method, attributes)); } else if (paramsValue is DidOpenTextDocumentParams openTextDocumentParams) { var attributes = new TextDocumentAttributes(openTextDocumentParams.TextDocument.Uri, openTextDocumentParams.TextDocument.LanguageId); _logger.LogTrace("Created attribute {Attribute}", $"{attributes.LanguageId}:{attributes.Scheme}:{attributes.Uri}"); return(GetHandler(method, attributes)); } else if (paramsValue is DidChangeTextDocumentParams didChangeDocumentParams) { // TODO: Do something with document version here? var attributes = GetTextDocumentAttributes(didChangeDocumentParams.TextDocument.Uri); _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.LanguageId}:{x.Scheme}:{x.Uri}")); return(GetHandler(method, attributes)); } } // TODO: How to split these // Do they fork and join? return(descriptor); }