diff options
Diffstat (limited to 'runtime/doc/lsp.txt')
-rw-r--r-- | runtime/doc/lsp.txt | 295 |
1 files changed, 107 insertions, 188 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 26850b3683..c4c164ab6c 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1,18 +1,18 @@ -*lsp.txt* The Language Server Protocol +*lsp.txt* Nvim LSP API - NVIM REFERENCE MANUAL + NVIM REFERENCE MANUAL -Neovim Language Server Protocol (LSP) API +Nvim Language Server Protocol (LSP) API *lsp* -Neovim exposes a powerful API that conforms to Microsoft's published Language -Server Protocol specification. The documentation can be found here: +Nvim is a client to the Language Server Protocol: https://microsoft.github.io/language-server-protocol/ + Type |gO| to see the table of contents. ================================================================================ - *lsp-api* +LSP API *lsp-api* Neovim exposes a API for the language server protocol. To get the real benefits of this API, a language server must be installed. @@ -24,106 +24,15 @@ After installing a language server to your machine, you must let Neovim know how to start and interact with that language server. To do so, you can either: -- Use the |vim.lsp.add_filetype_config()|, which solves the common use-case of - a single server for one or more filetypes. This can also be used from vim - via |lsp#add_filetype_config()|. +- Use https://github.com/neovim/nvim-lsp and one of the existing servers there + or set up a new one using the `nvim_lsp/skeleton` interface (and contribute + it if you find it useful). This uses |vim.lsp.start_client()| under the + hood. - Or |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()|. These are the backbone of the LSP API. These are easy to use enough for basic or more complex configurations such as in |lsp-advanced-js-example|. ================================================================================ - *lsp-filetype-config* - -These are utilities specific to filetype based configurations. - - *lsp#add_filetype_config()* - *vim.lsp.add_filetype_config()* -lsp#add_filetype_config({config}) for Vim. -vim.lsp.add_filetype_config({config}) for Lua - - These are functions which can be used to create a simple configuration which - will start a language server for a list of filetypes based on the |FileType| - event. - It will lazily start start the server, meaning that it will only start once - a matching filetype is encountered. - - The {config} options are the same as |vim.lsp.start_client()|, but - with a few additions and distinctions: - - Additional parameters:~ - `filetype` - {string} or {list} of filetypes to attach to. - `name` - A unique identifying string among all other servers configured with - |vim.lsp.add_filetype_config|. - - Differences:~ - `root_dir` - Will default to |getcwd()| instead of being required. - - NOTE: the function options in {config} like {config.on_init} are for Lua - callbacks, not Vim callbacks. -> - " Go example - call lsp#add_filetype_config({ - \ 'filetype': 'go', - \ 'name': 'gopls', - \ 'cmd': 'gopls' - \ }) - " Python example - call lsp#add_filetype_config({ - \ 'filetype': 'python', - \ 'name': 'pyls', - \ 'cmd': 'pyls' - \ }) - " Rust example - call lsp#add_filetype_config({ - \ 'filetype': 'rust', - \ 'name': 'rls', - \ 'cmd': 'rls', - \ 'capabilities': { - \ 'clippy_preference': 'on', - \ 'all_targets': v:false, - \ 'build_on_save': v:true, - \ 'wait_to_build': 0 - \ }}) -< -> - -- From Lua - vim.lsp.add_filetype_config { - name = "clangd"; - filetype = {"c", "cpp"}; - cmd = "clangd -background-index"; - capabilities = { - offsetEncoding = {"utf-8", "utf-16"}; - }; - on_init = vim.schedule_wrap(function(client, result) - if result.offsetEncoding then - client.offset_encoding = result.offsetEncoding - end - end) - } -< - *vim.lsp.copy_filetype_config()* -vim.lsp.copy_filetype_config({existing_name}, [{override_config}]) - - You can use this to copy an existing filetype configuration and change it by - specifying {override_config} which will override any properties in the - existing configuration. If you don't specify a new unique name with - {override_config.name} then it will try to create one and return it. - - Returns:~ - `name` the new configuration name. - - *vim.lsp.get_filetype_client_by_name()* -vim.lsp.get_filetype_client_by_name({name}) - - Use this to look up a client by its name created from - |vim.lsp.add_filetype_config()|. - - Returns nil if the client is not active or the name is not valid. - -================================================================================ *lsp-core-api* These are the core api functions for working with clients. You will mainly be using |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()| for operations @@ -178,8 +87,8 @@ vim.lsp.start_client({config}) `callbacks` A {table} of whose keys are language server method names and the values are `function(err, method, params, client_id)` See |lsp-callbacks| for - more. This will be combined with |lsp-builtin-callbacks| to provide - defaults. + more. This will be combined with |lsp-default-callbacks| to resolve + the callbacks for a client as a fallback. `init_options` A {table} of values to pass in the initialization request as @@ -203,6 +112,12 @@ vim.lsp.start_client({config}) `vim.lsp.client_errors[code]` can be used to retrieve a human understandable string. + `before_init(initialize_params, config)` + A function which is called *before* the request `initialize` is completed. + `initialize_params` contains the parameters we are sending to the server + and `config` is the config that was passed to `start_client()` for + convenience. You can use this to modify parameters before they are sent. + `on_init(client, initialize_result)` A function which is called after the request `initialize` is completed. `initialize_result` contains `capabilities` and anything else the server @@ -346,75 +261,81 @@ vim.lsp.rpc_response_error({code}, [{message}], [{data}]) the server. ================================================================================ - *vim.lsp.builtin_callbacks* - -The |vim.lsp.builtin_callbacks| table contains the default |lsp-callbacks| -that are used when creating a new client. The keys are the LSP method names. - -The following requests and notifications have built-in callbacks defined to -handle the response in an idiomatic way. - - textDocument/completion - textDocument/declaration - textDocument/definition - textDocument/hover - textDocument/implementation - textDocument/rename - textDocument/signatureHelp - textDocument/typeDefinition +LSP CALLBACKS *lsp-callbacks* + +DEFAULT CALLBACKS ~ + *vim.lsp.default_callbacks* +The `vim.lsp.default_callbacks` table defines default callbacks used when +creating a new client. Keys are LSP method names: > + + :lua print(vim.inspect(vim.tbl_keys(vim.lsp.default_callbacks))) + +These LSP requests/notifications are defined by default: + + textDocument/publishDiagnostics window/logMessage window/showMessage -You can check these via `vim.tbl_keys(vim.lsp.builtin_callbacks)`. +You can check these via `vim.tbl_keys(vim.lsp.default_callbacks)`. -These will be automatically used and can be overridden by users (either by -modifying the |vim.lsp.builtin_callbacks| object or on a per-client basis -by passing in a table via the {callbacks} parameter on |vim.lsp.start_client| -or |vim.lsp.add_filetype_config|. +These will be used preferrentially in `vim.lsp.buf` methods when handling +requests. They will also be used when responding to server requests and +notifications. -More information about callbacks can be found in |lsp-callbacks|. +Use cases: +- Users can modify this to customize to their preferences. +- UI plugins can modify this by assigning to + `vim.lsp.default_callbacks[method]` so as to provide more specialized + handling, allowing you to leverage the UI capabilities available. UIs should + try to be conscientious of any existing changes the user may have set + already by checking for existing values. -================================================================================ - *lsp-callbacks* +Any callbacks passed directly to `request` methods on a server client will +have the highest precedence, followed by the `default_callbacks`. + +You can override the default handlers, +- globally: by modifying the `vim.lsp.default_callbacks` table +- per-client: by passing the {callbacks} table parameter to + |vim.lsp.start_client| + +Each handler has this signature: > + + function(err, method, params, client_id) Callbacks are functions which are called in a variety of situations by the client. Their signature is `function(err, method, params, client_id)` They can -be set by the {callbacks} parameter for |vim.lsp.start_client| and -|vim.lsp.add_filetype_config| or via the |vim.lsp.builtin_callbacks|. - -This will be called for: -- notifications from the server, where `err` will always be `nil` -- requests initiated by the server. The parameter `err` will be `nil` here as - well. - For these, you can respond by returning two values: `result, err` The - err must be in the format of an RPC error, which is - `{ code, message, data? }` - You can use |vim.lsp.rpc_response_error()| to help with creating this object. -- as a callback for requests initiated by the client if the request doesn't - explicitly specify a callback (such as in |vim.lsp.buf_request|). +be set by the {callbacks} parameter for |vim.lsp.start_client| or via the +|vim.lsp.default_callbacks|. + +Handlers are called for: +- Notifications from the server (`err` is always `nil`). +- Requests initiated by the server (`err` is always `nil`). + The handler can respond by returning two values: `result, err` + where `err` must be shaped like an RPC error: + `{ code, message, data? }` + You can use |vim.lsp.rpc_response_error()| to create this object. +- Handling requests initiated by the client if the request doesn't explicitly + specify a callback (such as in |vim.lsp.buf_request|). ================================================================================ - *vim.lsp.protocol* -vim.lsp.protocol +VIM.LSP.PROTOCOL *vim.lsp.protocol* - Contains constants as described in the Language Server Protocol - specification and helper functions for creating protocol related objects. +The `vim.lsp.protocol` module provides constants defined in the LSP +specification, and helper functions for creating protocol-related objects. https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md - Useful examples are `vim.lsp.protocol.ErrorCodes`. These objects allow - reverse lookup by either the number or string name. +Useful examples are `vim.lsp.protocol.ErrorCodes`. These objects allow reverse +lookup by either the number or string name. e.g. vim.lsp.protocol.TextDocumentSyncKind.Full == 1 vim.lsp.protocol.TextDocumentSyncKind[1] == "Full" Utility functions used internally are: - `vim.lsp.make_client_capabilities()` + `vim.lsp.protocol.make_client_capabilities()` Make a ClientCapabilities object. These are the builtin capabilities. - `vim.lsp.make_text_document_position_params()` - Make a TextDocumentPositionParams object. - `vim.lsp.resolve_capabilities(server_capabilites)` + `vim.lsp.protocol.resolve_capabilities(server_capabilites)` Creates a normalized object describing capabilities from the server capabilities. @@ -482,18 +403,16 @@ vim.lsp.buf_notify({bufnr}, {method}, {params}) ================================================================================ *lsp-logging* - *lsp#set_log_level()* -lsp#set_log_level({level}) + *vim.lsp.set_log_level()* +vim.lsp.set_log_level({level}) You can set the log level for language server client logging. Possible values: "trace", "debug", "info", "warn", "error" Default: "warn" - Example: `call lsp#set_log_level("debug")` + Example: `lua vim.lsp.set_log_level("debug")` - *lsp#get_log_path()* *vim.lsp.get_log_path()* -lsp#get_log_path() vim.lsp.get_log_path() Returns the path that LSP logs are written. @@ -508,46 +427,46 @@ vim.lsp.log_levels ================================================================================ *lsp-omnifunc* *vim.lsp.omnifunc()* - *lsp#omnifunc* -lsp#omnifunc({findstart}, {base}) vim.lsp.omnifunc({findstart}, {base}) To configure omnifunc, add the following in your init.vim: > - set omnifunc=lsp#omnifunc + " Configure for python + autocmd Filetype python setl omnifunc=v:lua.vim.lsp.omnifunc + + " Or with on_attach + start_client { + ... + on_attach = function(client, bufnr) + vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + end; + } - " This is optional, but you may find it useful - autocmd CompleteDone * pclose + " This is optional, but you may find it useful + autocmd CompleteDone * pclose < ================================================================================ - *lsp-vim-functions* +LSP FUNCTIONS *lsp-vim-functions* + +To use the functions from vim, it is recommended to use |v:lua| to interface +with the Lua functions. No direct vim functions are provided, but the +interface is still easy to use from mappings. These methods can be used in mappings and are the equivalent of using the request from lua as follows: > - lua vim.lsp.buf_request(0, "textDocument/hover", vim.lsp.protocol.make_text_document_position_params()) -< - - lsp#text_document_declaration() - lsp#text_document_definition() - lsp#text_document_hover() - lsp#text_document_implementation() - lsp#text_document_signature_help() - lsp#text_document_type_definition() - -> " Example config - autocmd Filetype rust,python,go,c,cpp setl omnifunc=lsp#omnifunc - nnoremap <silent> ;dc :call lsp#text_document_declaration()<CR> - nnoremap <silent> ;df :call lsp#text_document_definition()<CR> - nnoremap <silent> ;h :call lsp#text_document_hover()<CR> - nnoremap <silent> ;i :call lsp#text_document_implementation()<CR> - nnoremap <silent> ;s :call lsp#text_document_signature_help()<CR> - nnoremap <silent> ;td :call lsp#text_document_type_definition()<CR> + autocmd Filetype rust,python,go,c,cpp setl omnifunc=v:lua.vim.lsp.omnifunc + nnoremap <silent> ;dc <cmd>lua vim.lsp.buf.declaration()<CR> + nnoremap <silent> ;df <cmd>lua vim.lsp.buf.definition()<CR> + nnoremap <silent> ;h <cmd>lua vim.lsp.buf.hover()<CR> + nnoremap <silent> ;i <cmd>lua vim.lsp.buf.implementation()<CR> + nnoremap <silent> ;s <cmd>lua vim.lsp.buf.signature_help()<CR> + nnoremap <silent> ;td <cmd>lua vim.lsp.buf.type_definition()<CR> < ================================================================================ - *lsp-advanced-js-example* +LSP EXAMPLE *lsp-advanced-js-example* For more advanced configurations where just filtering by filetype isn't sufficient, you can use the `vim.lsp.start_client()` and @@ -569,7 +488,7 @@ The example will: local stat = vim.loop.fs_stat(filename) return stat and stat.type == 'directory' or false end - + local path_sep = vim.loop.os_uname().sysname == "Windows" and "\\" or "/" -- Asumes filepath is a file. local function dirname(filepath) @@ -580,11 +499,11 @@ The example will: end) return result, is_changed end - + local function path_join(...) return table.concat(vim.tbl_flatten {...}, path_sep) end - + -- Ascend the buffer's path until we find the rootdir. -- is_root_path is a function which returns bool local function buffer_find_root_dir(bufnr, is_root_path) @@ -606,7 +525,7 @@ The example will: end end end - + -- A table to store our root_dir to client_id lookup. We want one LSP per -- root directory, and this is how we assert that. local javascript_lsps = {} @@ -617,14 +536,14 @@ The example will: ["typescript"] = true; ["typescript.jsx"] = true; } - + -- Create a template configuration for a server to start, minus the root_dir -- which we will specify later. local javascript_lsp_config = { name = "javascript"; cmd = { path_join(os.getenv("JAVASCRIPT_LANGUAGE_SERVER_DIRECTORY"), "lib", "language-server-stdio.js") }; } - + -- This needs to be global so that we can call it from the autocmd. function check_start_javascript_lsp() local bufnr = vim.api.nvim_get_current_buf() @@ -641,7 +560,7 @@ The example will: end) -- We couldn't find a root directory, so ignore this file. if not root_dir then return end - + -- Check if we have a client alredy or start and store it. local client_id = javascript_lsps[root_dir] if not client_id then @@ -655,7 +574,7 @@ The example will: -- are already attached. vim.lsp.buf_attach_client(bufnr, client_id) end - + vim.api.nvim_command [[autocmd BufReadPost * lua check_start_javascript_lsp()]] < |