From d104ab22d55499240ea03856a214deca4668f8e1 Mon Sep 17 00:00:00 2001 From: Marc Jakobi Date: Tue, 26 Mar 2024 19:42:50 +0100 Subject: [PATCH] feat(lsp): auto-detect some extra plugin client capabilities --- CHANGELOG.md | 8 +++ lua/rustaceanvim/config/internal.lua | 8 +-- lua/rustaceanvim/config/server.lua | 85 ++++++++++++++++++++++++++++ lua/rustaceanvim/lsp.lua | 36 ------------ 4 files changed, 97 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d50a64f8..c69b0d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- LSP: Automatically detect and register client capabilities for the following plugins, + if installed: + - [cmp-nvim-lsp](https://github.com/hrsh7th/cmp-nvim-lsp) + - [nvim-lsp-selection-range](https://github.com/camilledejoye/nvim-lsp-selection-range) + - [nvim-ufo](https://github.com/kevinhwang91/nvim-ufo) + ### Fixed - Neotest: Correctly mark passed and skipped tests when running a diff --git a/lua/rustaceanvim/config/internal.lua b/lua/rustaceanvim/config/internal.lua index d0a54348..edc89f73 100644 --- a/lua/rustaceanvim/config/internal.lua +++ b/lua/rustaceanvim/config/internal.lua @@ -3,6 +3,7 @@ local compat = require('rustaceanvim.compat') local config = require('rustaceanvim.config') local executors = require('rustaceanvim.executors') local os = require('rustaceanvim.os') +local server_config = require('rustaceanvim.config.server') local RustaceanConfig @@ -263,6 +264,8 @@ local RustaceanDefaultConfig = { ---@diagnostic disable-next-line: undefined-doc-class ---@class RustaceanLspClientConfig: vim.lsp.ClientConfig server = { + ---@type rustaceanvim.ClientCapabilities + capabilities = server_config.create_client_capabilities(), ---@type boolean | fun(bufnr: integer):boolean Whether to automatically attach the LSP client. ---Defaults to `true` if the `rust-analyzer` executable is found. auto_attach = function(bufnr) @@ -292,10 +295,7 @@ local RustaceanDefaultConfig = { ---@type table | (fun(project_root:string|nil, default_settings: table|nil):table) -- The rust-analyzer settings or a function that creates them. settings = function(project_root, default_settings) - return require('rustaceanvim.config.server').load_rust_analyzer_settings( - project_root, - { default_settings = default_settings } - ) + return server_config.load_rust_analyzer_settings(project_root, { default_settings = default_settings }) end, --- @type table diff --git a/lua/rustaceanvim/config/server.lua b/lua/rustaceanvim/config/server.lua index ee9e84c0..ef9a3329 100644 --- a/lua/rustaceanvim/config/server.lua +++ b/lua/rustaceanvim/config/server.lua @@ -63,4 +63,89 @@ function server.load_rust_analyzer_settings(project_root, opts) return default_settings end +---@return rustaceanvim.ClientCapabilities +local function make_rustaceanvim_capabilities() + ---@class rustaceanvim.ClientCapabilities: lsp.ClientCapabilities + local capabilities = vim.lsp.protocol.make_client_capabilities() + + -- snippets + capabilities.textDocument.completion.completionItem.snippetSupport = true + + -- send actions with hover request + ---@class rustaceanvim.ExperimentalCapabilities + capabilities.experimental = { + hoverActions = true, + hoverRange = true, + serverStatusNotification = true, + snippetTextEdit = true, + codeActionGroup = true, + ssr = true, + } + + -- enable auto-import + capabilities.textDocument.completion.completionItem.resolveSupport = { + properties = { 'documentation', 'detail', 'additionalTextEdits' }, + } + + -- rust analyzer goodies + local experimental_commands = { + 'rust-analyzer.runSingle', + 'rust-analyzer.showReferences', + 'rust-analyzer.gotoLocation', + 'editor.action.triggerParameterHints', + } + if package.loaded['dap'] ~= nil then + table.insert(experimental_commands, 'rust-analyzer.debugSingle') + end + + ---@class rustaceanvim.ExperimentalCommandCapabilities + capabilities.experimental.commands = { + commands = experimental_commands, + } + + return capabilities +end + +---@param mod_name string +---@param callback fun(mod: table): lsp.ClientCapabilities +---@return lsp.ClientCapabilities +local function mk_capabilities_if_available(mod_name, callback) + local available, mod = pcall(require, mod_name) + if available and type(mod) == 'table' then + local ok, capabilities = pcall(callback, mod) + if ok then + return capabilities + end + end + return {} +end + +---@return rustaceanvim.ClientCapabilities +function server.create_client_capabilities() + local rs_capabilities = make_rustaceanvim_capabilities() + local cmp_capabilities = mk_capabilities_if_available('cmp_nvim_lsp', function(cmp_nvim_lsp) + return cmp_nvim_lsp.default_capabilities() + end) + local selection_range_capabilities = mk_capabilities_if_available('lsp-selection-range', function(lsp_selection_range) + return lsp_selection_range.update_capabilities {} + end) + local folding_range_capabilities = mk_capabilities_if_available('ufo', function(_) + return { + textDocument = { + foldingRange = { + dynamicRegistration = false, + lineFoldingOnly = true, + }, + }, + } + end) + return vim.tbl_deep_extend( + 'keep', + rs_capabilities, + cmp_capabilities, + selection_range_capabilities, + folding_range_capabilities + ) +end + return server diff --git a/lua/rustaceanvim/lsp.lua b/lua/rustaceanvim/lsp.lua index a77cacd5..1efa5daa 100644 --- a/lua/rustaceanvim/lsp.lua +++ b/lua/rustaceanvim/lsp.lua @@ -135,42 +135,6 @@ M.start = function(bufnr) lsp_start_config.cmd = rust_analyzer_cmd lsp_start_config.name = 'rust-analyzer' lsp_start_config.filetypes = { 'rust' } - local capabilities = vim.lsp.protocol.make_client_capabilities() - - -- snippets - capabilities.textDocument.completion.completionItem.snippetSupport = true - - -- send actions with hover request - capabilities.experimental = { - hoverActions = true, - hoverRange = true, - serverStatusNotification = true, - snippetTextEdit = true, - codeActionGroup = true, - ssr = true, - } - - -- enable auto-import - capabilities.textDocument.completion.completionItem.resolveSupport = { - properties = { 'documentation', 'detail', 'additionalTextEdits' }, - } - - -- rust analyzer goodies - local experimental_commands = { - 'rust-analyzer.runSingle', - 'rust-analyzer.showReferences', - 'rust-analyzer.gotoLocation', - 'editor.action.triggerParameterHints', - } - if package.loaded['dap'] ~= nil then - table.insert(experimental_commands, 'rust-analyzer.debugSingle') - end - - capabilities.experimental.commands = { - commands = experimental_commands, - } - - lsp_start_config.capabilities = vim.tbl_deep_extend('force', capabilities, lsp_start_config.capabilities or {}) local custom_handlers = {} custom_handlers['experimental/serverStatus'] = server_status.handler