aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp.lua
Commit message (Collapse)AuthorAge
...
* fix(lsp): correct prefix when filterText is present (#17051)Lajos Koszti2022-02-11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | LSP server might return an item which would replace a token to another. For example in typescript for a `jest.Mock` object `getProductsMock.` text I get the following response: ``` { commitCharacters = { ".", ",", "(" }, data = { entryNames = { "Symbol" }, file = "/foo/bar/baz.service.spec.ts", line = 268, offset = 17 }, filterText = ".Symbol", kind = 6, label = "Symbol", sortText = "11", textEdit = { newText = "[Symbol]", range = { end = { character = 16, line = 267 }, start = { character = 15, line = 267 } } } }, ``` In `lsp.omnifunc` to get a `prefix` we call the `adjust_start_col` which then returns the `textEdit.range.start.character`. Th `prefix` then be the `.` character. Then when filter the items with `remove_unmatch_completion_items`, every item will be filtered out, since no completion word starts `.`. To fix we return the `end.character`, which in that particular case will be the position after the `.`.
* perf(lsp): request only changed portions of the buffer in changetracking ↵Michael Lingelbach2022-01-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#17118) This commits introduces two performance improvements in incremental sync: * avoiding expensive lua string reallocations on each on_lines call by requesting only the changed chunk of the buffer as reported by firstline and new_lastline parameters of on_lines * re-using already allocated tables for storing the resulting lines to reduce the load on the garbage collector The majority of the performance improvement is from requesting only changed chunks of the buffer. Benchmark: The following code measures the time required to perform a buffer edit to that operates individually on each line, common to plugins such as vim-commentary. set rtp+=~/.config/nvim/plugged/nvim-lspconfig set rtp+=~/.config/nvim/plugged/vim-commentary lua require('lspconfig')['ccls'].setup({}) function! Benchmark(tries) abort let results_comment = [] let results_undo = [] for i in range(a:tries) echo printf('run %d', i+1) let begin = reltime() normal gggcG call add(results_comment, reltimefloat(reltime(begin))) let begin = reltime() silent! undo call add(results_undo, reltimefloat(reltime(begin))) redraw endfor let avg_comment = 0.0 let avg_undo = 0.0 for i in range(a:tries) echomsg printf('run %3d: comment=%fs undo=%fs', i+1, results_comment[i], results_undo[i]) let avg_comment += results_comment[i] let avg_undo += results_undo[i] endfor echomsg printf('average: comment=%fs undo=%fs', avg_comment / a:tries, avg_undo / a:tries) endfunction command! -bar Benchmark call Benchmark(10) All text changes will be recorded within a single undo operation. Both the comment operation itself and the undo operation will generate an on_lines event for each changed line. Formatter plugins using setline() have also been found to exhibit the same problem (neoformat, :RustFmt in rust.vim), as this function too generates an on_lines event for every line it changes. Using the neovim codebase as an example (commit 2ecf0a4) with neovim itself built at 2ecf0a4 with CMAKE_BUILD_TYPE=Release shows the following performance improvement: src/nvim/lua/executor.c, 1432 lines: - baseline, no optimizations: comment=0.540587s undo=0.440249s - without double-buffering optimization: comment=0.183314s undo=0.060663s - all optimizations in this commit: comment=0.174850s undo=0.052789s src/nvim/search.c, 5467 lines: - baseline, no optimizations: comment=7.420446s undo=7.656624s - without double-buffering optimization: comment=0.889048s undo=0.486026s - all optimizations in this commit: comment=0.662899s undo=0.243628s src/nvim/eval.c, 11355 lines: - baseline, no optimizations: comment=41.775695s undo=44.583374s - without double-buffering optimization: comment=3.643933s undo=2.817158s - all optimizations in this commit: comment=1.510886s undo=0.707928s Co-authored-by: Dmytro Meleshko <dmytro.meleshko@gmail.com>
* refactor(lsp): debounce timer per buf and unify with non-debounce (#17016)Mathias Fußenegger2022-01-11
| | | | | | | | | | | | | | | | Part of the `pending_change` closure in the `changetracking.prepare` was a bit confusing because it has access to `bufnr` and `uri` but it could actually contain pending changes batched for multiple buffers. (We accounted for that by grouping `pending_changes` by a `uri`, but it's not obvious what's going on) This commit changes the approach to do everything per buffer to avoid any ambiguity. It also brings the debounce/no-debounce a bit closer together: The only difference is now whether a timer is used or if it is triggered immediately
* fix(lsp): ensure pending changes are flushed on skipped debounce (#17015)Mathias Fußenegger2022-01-10
| | | | | | | | | Follow up to https://github.com/neovim/neovim/pull/16881 Document changes could get sent out of order to the server: 1. on_lines: debounce > 0; add to pending changes; setup timer 2. on_lines: debounce = 0; send new changes immediately 3. timer triggers, sending changes from 1.
* feat(lsp): skip or reduce debounce after idle (#16881)Mathias Fußenegger2022-01-07
| | | | | | | | | | The idea of the debounce is to avoid overloading a server with didChange notifications. So far this used a constant value to group changes within an interval together and send a single notification. A side effect of this is that when you were idle, notifications are still delayed. This commit changes the logic to take the time the last notification happened into consideration, if it has been greater than the debounce interval, the debouncing is skipped or at least reduced.
* feat(lsp): enable default debounce of 150 ms (#16908)Michael Lingelbach2022-01-05
|
* chore: fix typos (#16816)dundargoc2022-01-04
| | | | | | | Co-authored-by: Sean Dewar <seandewar@users.noreply.github.com> Co-authored-by: Gregory Anders <greg@gpanders.com> Co-authored-by: Sebastian Volland <seb@baunz.net> Co-authored-by: Lewis Russell <lewis6991@gmail.com> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
* fix(lsp): explicitly pass bufnr in didSave handler (#16906)Michael Lingelbach2022-01-03
| | | | Addresses a regression introduced by the stricter type checking in lua api functions from https://github.com/neovim/neovim/pull/16745
* chore: fix typos (#16506)dundargoc2021-12-28
| | | | | | | | | Co-authored-by: Gregory Anders <8965202+gpanders@users.noreply.github.com> Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com> Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: Christoph Hasse <hassec@users.noreply.github.com> Co-authored-by: Alef Pereira <ealefpereira@gmail.com> Co-authored-by: AusCyber <willp@outlook.com.au> Co-authored-by: kylo252 <59826753+kylo252@users.noreply.github.com>
* feat(lsp): add buf_detach_client (#16250)Michael Lingelbach2021-12-21
| | | | | This allows the user to detach an active buffer from the language client. If no clients remain attached to a buffer, the on_lines callback is used to cancel nvim_buf_attach.
* fix(lsp): avoid attaching to unloaded buffers (#16723)Michael Lingelbach2021-12-19
| | | | | | | | | | | Closes https://github.com/neovim/neovim/issues/16562 https://github.com/neovim/neovim/issues/16249 https://github.com/neovim/neovim/issues/16297 * buf_attach_client can be called on an unloaded buffer * on_attach will prematurely fail, while the language server client tracks this buffer as attached * The language server client will track this buffer as attached despite textDocument/didChange notifications not being sent to the server * Instead, check if the buffer is loaded and return early, warning via the lsp logger that buf_attach_client was called on an invalid buffer
* fix(lsp): call config on_exit handler before context is cleared (#16638)Gregory Anders2021-12-17
| | | | | | The on_exit handler provided to the client configuration is called after the client's context is cleared (e.g. which buffers the client was attached to). Calling the handler sooner allows these handlers to access the client object and do their own cleanup with the full context.
* fix(lsp): create lsp requests with position offsets considering client ↵Rishikesh Vaishnav2021-12-10
| | | | | | encoding (#16382) Co-authored-by: black-desk <clx814727823@gmail.com> Co-authored-by: Mathias Fußenegger <mfussenegger@users.noreply.github.com>
* refactor(lsp): remove usage of deprecated function (#16539)Gregory Anders2021-12-07
|
* docs(lsp): re-add client.requests documentation (#16530)Anshuman Medhi2021-12-05
| | | | | | | Closes #16528 Added in this PR: https://github.com/neovim/neovim/commit/d1c470957b49380ec5ceba603dbd85a14f60f09b#diff-6b5f3071d65558aab177912061ac6a2f5312660655a449276c83697686f28e72R627 Removed by regeneration in this PR: https://github.com/neovim/neovim/commit/2d340a3746dd5d6caf17b2c2e78380fa423409e8#diff-6b5f3071d65558aab177912061ac6a2f5312660655a449276c83697686f28e72L631
* docs(lsp): add annotations for private functionsGregory Anders2021-11-30
|
* chore: fix typos (#16361)dundargoc2021-11-27
| | | | | | | | | | | | | | | | | | | | | | | | | | Co-authored-by: Brede Yabo Sherling Kristensen <bredeyabo@hotmail.com> Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: István Donkó <istvan.donko@gmail.com> Co-authored-by: Julian Berman <Julian@GrayVines.com> Co-authored-by: bryant <bryant@users.noreply.github.com> Co-authored-by: Michael Lingelbach <m.j.lbach@gmail.com> Co-authored-by: nlueb <9465658+nlueb@users.noreply.github.com> Co-authored-by: Leonhard Saam <leonhard.saam@yahoo.com> Co-authored-by: Jesse Wertheim <jaawerth@gmail.com> Co-authored-by: dm1try <me@dmitry.it> Co-authored-by: Jakub Łuczyński <doubleloop@o2.pl> Co-authored-by: Louis Lebrault <louis.lebrault@gmail.com> Co-authored-by: Brede Yabo Sherling Kristensen <bredeyabo@hotmail.com> Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: István Donkó <istvan.donko@gmail.com> Co-authored-by: Julian Berman <Julian@GrayVines.com> Co-authored-by: bryant <bryant@users.noreply.github.com> Co-authored-by: Michael Lingelbach <m.j.lbach@gmail.com> Co-authored-by: nlueb <9465658+nlueb@users.noreply.github.com> Co-authored-by: Leonhard Saam <leonhard.saam@yahoo.com> Co-authored-by: Jesse Wertheim <jaawerth@gmail.com> Co-authored-by: dm1try <me@dmitry.it> Co-authored-by: Jakub Łuczyński <doubleloop@o2.pl> Co-authored-by: Louis Lebrault <louis.lebrault@gmail.com>
* fix(lsp): send textDocument/didChange for each buffer (#16431)Michael Lingelbach2021-11-26
| | | Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net>
* feat(lsp): use uv_spawn to check if server executable (#16430)Michael Lingelbach2021-11-25
| | | | | | | | Previously, the built-in language server client checked if the first argument of cmd was executable via vim.fn.executable. This ignores PATH injected via cmd_env. Instead, we now start the client via uv.spawn, and handle the failure mode, reporting the error back to the user. Co-authored-by: Mathias Fußenegger <mfussenegger@users.noreply.github.com>
* fix(lsp): avoid indexing vim.NIL for null workspaceFolders (#16404)Michael Lingelbach2021-11-22
| | | | * internally represent no workspaceFolders as nil instead of vim.NIL * rename workspaceFolders -> workspace_folders for consistency
* fix(lsp): send buffer contents joined on fileformat-specific linebreak (#16334)Dmytro Meleshko2021-11-21
|
* chore(lsp): clean up initialization process (#16369)Michael Lingelbach2021-11-21
| | | | | * send vim.NIL instead of not sending workspaceFolders * read fallback rootPath and rootUri from workspaceFolders * update documentation
* docs: mark tagfunc.lua methods as privateGregory Anders2021-11-18
|
* feat(lsp): add tagfunc (#16103)Michael Lingelbach2021-11-18
|
* fix(lsp): ensure buffers are re-attached on rename (#16266)Mathias Fußenegger2021-11-14
| | | | | | | | | If a LSP server sent a workspace edit containing a rename the buffers file name changed without the server receiving a close notification for the old buffer and without the client properly re-attaching on the new file. This affected `Move` code-actions in nvim-jdtls, but also `vim.lsp.buf.rename` on a class level.
* fix(lsp): rewrite incremental sync (#16252)Michael Lingelbach2021-11-09
| | | | | | * use codeunits/points instead of byte ranges when applicable * take into account different file formats when computing range and sending text (dos, unix, and mac supported) * add tests of incremental sync
* docs(lsp): correct usage examples of formatexpr (#16216)Michael Lingelbach2021-11-02
|
* feat(lsp): add per-client commands (#16101)Michael Lingelbach2021-11-01
|
* fix(lsp): don't update active_clients on exit_timeout (#16192)David Hotham2021-10-31
|
* feat(lsp): add formatexpr (#16186)Michael Lingelbach2021-10-31
| | | | Co-authored-by: Meck <yesmeck@gmail.com> Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
* fix(lsp): add placeholder cancel function (#16189)Michael Lingelbach2021-10-31
| | | | | | | | | | Fixes a bug introduced by https://github.com/neovim/neovim/pull/15949 When no supported clients for a given method are available, buf_request returns early with a nil value. If buf_request_sync is called on a buffer with no clients that support a given method, the returned `cancel` method (which is nil), is invoked, resulting in an error. Solution: return an empty function handle
* feat(lsp): track pending+cancel requests on client object #15949jdrouhard2021-10-29
|
* feat(lsp): add exit_timeout flag (#16070)Michael Lingelbach2021-10-21
| | | | | | | * This flag allows customizing the time before sending kill -15 to the server. If set to false, neovim exits immediately after sending request('shutdown'). Otherwise, polls until all servers have shutdown, and then kills remaining servers via kill -15 at exit_timeout duration. Defaults to 500 ms.
* fix(lsp): avoid duplicates in client attached buffers (#16099)Michael Lingelbach2021-10-20
| | | | | | | closes https://github.com/neovim/neovim/issues/16058 * add client.attached_buffers * only update client.attached_buffers in on_attach * use table instead of list for attached_buffers to avoid duplication
* fix(gen_vimdoc.py): spacing around inline elements #16092Gregory Anders2021-10-19
| | | | | The spacing fix drew attention to a couple of places that were using incorrect formatting such as the key listing for `nvim_open_win`, so those were fixed too.
* fix(lsp): maintain client_ids table structure when filtering (#15991)Jose Alvarez2021-10-11
|
* fix(lsp): do not invoke handlers for unsupported methods (#15926)Michael Lingelbach2021-10-10
| | | | | | | Closes https://github.com/neovim/neovim/issues/15174 Instead of invoking handlers with unsupported methods, pre-compute which clients support a given method and only notify the user if no clients support the given method.
* fix(lsp): add textDocument/prepareRename to capability map (#15961)francisco souza2021-10-08
| | | | | | | | | | This is a simple fix for #15899, as it should at least stop calling `prepareRename` on servers that don't support renaming. I imagine a better fix would be to inspect the actual value for, but that requires some plumbing changes on how capabilities are evaluated before sending requests out. Co-authored-by: francisco souza <fsouza@users.noreply.github.com>
* feat(lsp): utilize textEdit.range for startbyte in omnifunc (#15957)Mathias Fußenegger2021-10-08
| | | Closes https://github.com/neovim/neovim/issues/15784
* feat(lsp): use cjson for lsp rpc (#15759)Michael Lingelbach2021-09-26
|
* feat(lsp): add a registry for client side code action commandsMathias Fussenegger2021-09-20
| | | | | This builds on https://github.com/neovim/neovim/pull/14112 and closes https://github.com/neovim/neovim/issues/12326
* feat(lsp): include original request params in handler ctxMathias Fussenegger2021-09-20
| | | | | | | | | | | This is mostly motivated by https://github.com/neovim/neovim/issues/12326 Client side commands might need to access the original request parameters. Currently this is already possible by using closures with `vim.lsp.buf_request`, but the global handlers so far couldn't access the request parameters.
* Merge #15585 refactor: move vim.lsp.diagnostic to vim.diagnosticJustin M. Keyes2021-09-16
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## Overview - Move vim.lsp.diagnostic to vim.diagnostic - Refactor client ids to diagnostic namespaces - Update tests - Write/update documentation and function signatures Currently, non-LSP diagnostics in Neovim must hook into the LSP subsystem. This is what e.g. null-ls and nvim-lint do. This is necessary because none of the diagnostic API is exposed separately from the LSP subsystem. This commit addresses this by generalizing the diagnostic subsystem beyond the scope of LSP. The `vim.lsp.diagnostic` module is now simply a specific diagnostic producer and primarily maintains the interface between LSP clients and the broader diagnostic API. The current diagnostic API uses "client ids" which only makes sense in the context of LSP. We replace "client ids" with standard API namespaces generated from `nvim_create_namespace`. This PR is *mostly* backward compatible (so long as plugins are only using the publicly documented API): LSP diagnostics will continue to work as usual, as will pseudo-LSP clients like null-ls and nvim-lint. However, the latter can now use the new interface, which looks something like this: ```lua -- The namespace *must* be given a name. Anonymous namespaces will not work with diagnostics local ns = vim.api.nvim_create_namespace("foo") -- Generate diagnostics local diagnostics = generate_diagnostics() -- Set diagnostics for the current buffer vim.diagnostic.set(ns, diagnostics, bufnr) ``` Some public facing API utility methods were removed and internalized directly in `vim.diagnostic`: * `vim.lsp.util.diagnostics_to_items` ## API Design `vim.diagnostic` contains most of the same API as `vim.lsp.diagnostic` with `client_id` simply replaced with `namespace`, with some differences: * Generally speaking, functions that modify or add diagnostics require a namespace as their first argument, e.g. ```lua vim.diagnostic.set({namespace}, {bufnr}, {diagnostics}[, {opts}]) ``` while functions that read or query diagnostics do not (although in many cases one may be supplied optionally): ```lua vim.diagnostic.get({bufnr}[, {namespace}]) ``` * We use our own severity levels to decouple `vim.diagnostic` from LSP. These are designed similarly to `vim.log.levels` and currently include: ```lua vim.diagnostic.severity.ERROR vim.diagnostic.severity.WARN vim.diagnostic.severity.INFO vim.diagnostic.severity.HINT ``` In practice, these match the LSP diagnostic severity levels exactly, but we should treat this as an interface and not assume that they are the same. The "translation" between the two severity types is handled transparently in `vim.lsp.diagnostic`. * The actual "diagnostic" data structure is: (**EDIT:** Updated 2021-09-09): ```lua { lnum = <number>, col = <number>, end_lnum = <number>, end_col = <number>, severity = <vim.diagnostic.severity>, message = <string> } ``` This differs from the LSP definition of a diagnostic, so we transform them in the handler functions in vim.lsp.diagnostic. ## Configuration The `vim.lsp.with` paradigm still works for configuring how LSP diagnostics are displayed, but this is a specific use-case for the `publishDiagnostics` handler. Configuration with `vim.diagnostic` is instead done with the `vim.diagnostic.config` function: ```lua vim.diagnostic.config({ virtual_text = true, signs = false, underline = true, update_in_insert = true, severity_sort = false, }[, namespace]) ``` (or alternatively passed directly to `set()` or `show()`.) When the `namespace` argument is `nil`, settings are set globally (i.e. for *all* diagnostic namespaces). This is what user's will typically use for their local configuration. Diagnostic producers can also set configuration options for their specific namespace, although this is generally discouraged in order to respect the user's global settings. All of the values in the table passed to `vim.diagnostic.config()` are resolved in the same way that they are in `on_publish_diagnostics`; that is, the value can be a boolean, a table, or a function: ```lua vim.diagnostic.config({ virtual_text = function(namespace, bufnr) -- Only enable virtual text in buffer 3 return bufnr == 3 end, }) ``` ## Misc Notes * `vim.diagnostic` currently depends on `vim.lsp.util` for floating window previews. I think this is okay for now, although ideally we'd want to decouple these completely.
| * refactor: move vim.lsp.diagnostic to vim.diagnosticGregory Anders2021-09-15
| | | | | | | | | | | | | | | | | | | | | | This generalizes diagnostic handling outside of just the scope of LSP. LSP clients are now a specific case of a diagnostic producer, but the diagnostic subsystem is decoupled from the LSP subsystem (or will be, eventually). More discussion at [1]. [1]: https://github.com/neovim/neovim/pull/15585
* | feat(lsp): improve logging (#15636)Michael Lingelbach2021-09-15
|/ | | | | | | * Simplify rpc encode/decode messages to rpc.send/rcp.receive * Make missing handlers message throw a warning * Clean up formatting style in log * Move all non-RPC loop messages to trace instead of debug * Add format func option to log to allow newlines in per log entry
* Merge pull request #15504 from mjlbach/feat/change-handler-signatureMichael Lingelbach2021-09-05
|\ | | | | feat(lsp)!: change handler signature
| * feat(lsp)!: change handler signatureMichael Lingelbach2021-09-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, the handler signature was: function(err, method, params, client_id, bufnr, config) In order to better support external plugins that wish to extend the protocol, there is other information which would be advantageous to forward to the client, such as the original params of the request that generated the callback. In order to do this, we would need to break symmetry of the handlers, to add an additional "params" as the 7th argument. Instead, this PR changes the signature of the handlers to: function(err, result, ctx, config) where ctx (the context) includes params, client_id, and bufnr. This also leaves flexibility for future use-cases. BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring updating handler calls
* | fix(lsp): resolve bufnr in buf_is_attached (#15523)Jose Alvarez2021-08-30
| |
* | fix(lsp): check if buffer is valid in changetracking (#15505)Jose Alvarez2021-08-28
|/
* docs: make Lua docstrings consistent #15255Gregory Anders2021-08-22
| | | | | | | | | | | | The official developer documentation in in :h dev-lua-doc specifies to use "--@" for special/magic tokens. However, this format is not consistent with EmmyLua notation (used by some Lua language servers) nor with the C version of the magic docstring tokens which use three comment characters. Further, the code base is currently split between usage of "--@", "---@", and "--- @". In an effort to remain consistent, change all Lua magic tokens to use "---@" and update the developer documentation accordingly.