internal static void InitHandlers(ILanguageServer client, CompositeDisposable result, ISupportedCapabilities supportedCapabilities)
 {
     Observable.Concat(
         GetUniqueHandlers <IOnLanguageServerInitialize>(result)
         .Select(handler => Observable.FromAsync(ct => handler.OnInitialize(client, client.ClientSettings, ct)))
         .Merge(),
         GetAllDescriptors(result)
         .Select(item => LspHandlerDescriptorHelpers.InitializeHandler(item, supportedCapabilities, item.Handler))
         .ToObservable()
         .Select(z => Unit.Default),
         GetUniqueHandlers <IOnLanguageServerInitialized>(result)
         .Select(handler => Observable.FromAsync(ct => handler.OnInitialized(client, client.ClientSettings, client.ServerSettings, ct)))
         .Merge(),
         GetUniqueHandlers <IOnLanguageServerStarted>(result)
         .Select(handler => Observable.FromAsync(ct => handler.OnStarted(client, ct)))
         .Merge()
         ).Subscribe();
 }
Exemple #2
0
        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);
        }