diff options
-rw-r--r-- | runtime/doc/lsp.txt | 11 | ||||
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 43 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 14 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 5 |
5 files changed, 41 insertions, 34 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index d1fd84669a..a0d0b75407 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -869,12 +869,14 @@ start({config}, {opts}) *vim.lsp.start()* |vim.lsp.ClientConfig|. • {opts} (`table?`) Optional keyword arguments • {reuse_client} - (`fun(client: vim.lsp.Client, config: table): boolean`) + (`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`) Predicate used to decide if a client should be re-used. Used on all running clients. The default implementation re-uses a client if name and root_dir matches. • {bufnr} (`integer`) Buffer handle to attach to if starting or re-using a client (0 for current). + • {silent} (`boolean`) Suppress error reporting if the LSP + server fails to start (default false). Return: ~ (`integer?`) client_id @@ -886,10 +888,11 @@ start_client({config}) *vim.lsp.start_client()* • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See |vim.lsp.ClientConfig|. - Return: ~ + Return (multiple): ~ (`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may not be fully initialized. Use `on_init` to do any actions once the client has been initialized. + (`string?`) Error message, if any status() *vim.lsp.status()* Consumes the latest progress messages from all clients and formats them as @@ -1073,7 +1076,7 @@ Lua module: vim.lsp.client *lsp-client* *vim.lsp.ClientConfig* Fields: ~ - • {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?`) + • {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`) command string[] that launches the language server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like @@ -2340,7 +2343,7 @@ start({cmd}, {dispatchers}, {extra_spawn_params}) *vim.lsp.rpc.start()* See |vim.system()| Return: ~ - (`vim.lsp.rpc.PublicClient?`) Client RPC object, with these methods: + (`vim.lsp.rpc.PublicClient`) Client RPC object, with these methods: • `notify()` |vim.lsp.rpc.notify()| • `request()` |vim.lsp.rpc.request()| • `is_closing()` returns a boolean indicating if the RPC is closing. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 44d5ea39bf..b2e20e5405 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -243,6 +243,8 @@ The following new APIs and features were added. (e.g. `commitCharacters`). Note that this might affect plugins and language servers that don't support the feature, and in such cases the respective capability can be unset. + • |vim.lsp.start()| accepts a "silent" option for suppressing messages + if an LSP server failed to start. • Treesitter • Bundled parsers and queries (highlight, folds) for Markdown, Python, and diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 8403aa0ee6..fcb1ad5b4b 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -195,10 +195,13 @@ end --- Predicate used to decide if a client should be re-used. Used on all --- running clients. The default implementation re-uses a client if name and --- root_dir matches. ---- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean +--- @field reuse_client fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean --- --- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr integer +--- +--- Suppress error reporting if the LSP server fails to start (default false). +--- @field silent boolean --- Create a new LSP client and start a language server or reuses an already --- running client if one is found matching `name` and `root_dir`. @@ -246,19 +249,25 @@ function lsp.start(config, opts) for _, client in pairs(all_clients) do if reuse_client(client, config) then - lsp.buf_attach_client(bufnr, client.id) - return client.id + if lsp.buf_attach_client(bufnr, client.id) then + return client.id + end end end - local client_id = lsp.start_client(config) + local client_id, err = lsp.start_client(config) + if err then + if not opts.silent then + vim.notify(err, vim.log.levels.WARN) + end + return nil + end - if not client_id then - return -- lsp.start_client will have printed an error + if client_id and lsp.buf_attach_client(bufnr, client_id) then + return client_id end - lsp.buf_attach_client(bufnr, client_id) - return client_id + return nil end --- Consumes the latest progress messages from all clients and formats them as a string. @@ -420,16 +429,18 @@ end --- Starts and initializes a client with the given configuration. --- @param config vim.lsp.ClientConfig Configuration for the server. ---- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be ---- fully initialized. Use `on_init` to do any actions once ---- the client has been initialized. +--- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be +--- fully initialized. Use `on_init` to do any actions once +--- the client has been initialized. +--- @return string? # Error message, if any function lsp.start_client(config) - local client = require('vim.lsp.client').create(config) - - if not client then - return + local ok, res = pcall(require('vim.lsp.client').create, config) + if not ok then + return nil, res --[[@as string]] end + local client = assert(res) + --- @diagnostic disable-next-line: invisible table.insert(client._on_exit_cbs, on_client_exit) @@ -437,7 +448,7 @@ function lsp.start_client(config) client:initialize() - return client.id + return client.id, nil end --- Notify all attached clients that a buffer has changed. diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 98b3cfc762..448f986cd3 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -37,7 +37,7 @@ local validate = vim.validate --- `is_closing` and `terminate`. --- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. --- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| ---- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient --- --- Directory to launch the `cmd` process. Not related to `root_dir`. --- (default: cwd) @@ -506,25 +506,17 @@ function Client.create(config) } -- Start the RPC client. - local rpc --- @type vim.lsp.rpc.PublicClient? local config_cmd = config.cmd if type(config_cmd) == 'function' then - rpc = config_cmd(dispatchers) + self.rpc = config_cmd(dispatchers) else - rpc = lsp.rpc.start(config_cmd, dispatchers, { + self.rpc = lsp.rpc.start(config_cmd, dispatchers, { cwd = config.cmd_cwd, env = config.cmd_env, detached = config.detached, }) end - -- Return nil if the rpc client fails to start - if not rpc then - return - end - - self.rpc = rpc - setmetatable(self, Client) return self diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index d73e46edfb..3c63a12da2 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -722,7 +722,7 @@ end --- @param cmd string[] Command to start the LSP server. --- @param dispatchers? vim.lsp.rpc.Dispatchers --- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams ---- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods: +--- @return vim.lsp.rpc.PublicClient : Client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. @@ -797,8 +797,7 @@ function M.start(cmd, dispatchers, extra_spawn_params) end local msg = string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx) - vim.notify(msg, vim.log.levels.WARN) - return nil + error(msg) end sysobj = sysobj_or_err --[[@as vim.SystemObj]] |