aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/util.lua
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2021-09-16 14:23:42 -0700
committerGitHub <noreply@github.com>2021-09-16 14:23:42 -0700
commit2e8103475e18d1e4aa0d6355107f393815a886a6 (patch)
tree3bca29fcd412cd4ce942a662229aa541977a63d6 /runtime/lua/vim/lsp/util.lua
parent7d21b958691c06ed6b40aa1909cd81c37a67844e (diff)
parent4fca63dbf722f60f9096ef32c0dbecc2055c4a9a (diff)
downloadrneovim-2e8103475e18d1e4aa0d6355107f393815a886a6.tar.gz
rneovim-2e8103475e18d1e4aa0d6355107f393815a886a6.tar.bz2
rneovim-2e8103475e18d1e4aa0d6355107f393815a886a6.zip
Merge #15585 refactor: move vim.lsp.diagnostic to vim.diagnostic
## 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.
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
-rw-r--r--runtime/lua/vim/lsp/util.lua51
1 files changed, 7 insertions, 44 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 5a22a311e0..9a3ce185a0 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -31,16 +31,6 @@ local default_border = {
{" ", "NormalFloat"},
}
-
-local DiagnosticSeverity = protocol.DiagnosticSeverity
-local loclist_type_map = {
- [DiagnosticSeverity.Error] = 'E',
- [DiagnosticSeverity.Warning] = 'W',
- [DiagnosticSeverity.Information] = 'I',
- [DiagnosticSeverity.Hint] = 'I',
-}
-
-
---@private
--- Check the border given by opts or the default border for the additional
--- size it adds to a float.
@@ -1543,6 +1533,9 @@ end
--- Returns the items with the byte position calculated correctly and in sorted
--- order, for display in quickfix and location lists.
---
+--- The result can be passed to the {list} argument of |setqflist()| or
+--- |setloclist()|.
+---
---@param locations (table) list of `Location`s or `LocationLink`s
---@returns (table) list of items
function M.locations_to_items(locations)
@@ -1601,6 +1594,8 @@ end
--- Can be obtained with e.g. |vim.lsp.util.locations_to_items()|.
--- Defaults to current window.
---
+---@deprecated Use |setloclist()|
+---
---@param items (table) list of items
function M.set_loclist(items, win_id)
vim.fn.setloclist(win_id or 0, {}, ' ', {
@@ -1612,6 +1607,8 @@ end
--- Fills quickfix list with given list of items.
--- Can be obtained with e.g. |vim.lsp.util.locations_to_items()|.
---
+---@deprecated Use |setqflist()|
+---
---@param items (table) list of items
function M.set_qflist(items)
vim.fn.setqflist({}, ' ', {
@@ -1869,40 +1866,6 @@ function M.lookup_section(settings, section)
return settings
end
-
---- Convert diagnostics grouped by bufnr to a list of items for use in the
---- quickfix or location list.
----
----@param diagnostics_by_bufnr table bufnr -> Diagnostic[]
----@param predicate an optional function to filter the diagnostics.
---- If present, only diagnostic items matching will be included.
----@return table (A list of items)
-function M.diagnostics_to_items(diagnostics_by_bufnr, predicate)
- local items = {}
- for bufnr, diagnostics in pairs(diagnostics_by_bufnr or {}) do
- for _, d in pairs(diagnostics) do
- if not predicate or predicate(d) then
- table.insert(items, {
- bufnr = bufnr,
- lnum = d.range.start.line + 1,
- col = d.range.start.character + 1,
- text = d.message,
- type = loclist_type_map[d.severity or DiagnosticSeverity.Error] or 'E'
- })
- end
- end
- end
- table.sort(items, function(a, b)
- if a.bufnr == b.bufnr then
- return a.lnum < b.lnum
- else
- return a.bufnr < b.bufnr
- end
- end)
- return items
-end
-
-
M._get_line_byte_from_position = get_line_byte_from_position
M._warn_once = warn_once