diff options
author | Gregory Anders <8965202+gpanders@users.noreply.github.com> | 2021-10-17 08:18:35 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-17 07:18:35 -0700 |
commit | d2d30dfabdaacfd53b081354248402c797576482 (patch) | |
tree | 74f47005521367951803f1275b82aac37b4b0d4f | |
parent | 30af69509dc91552dc41451857b18907f018c1bd (diff) | |
download | rneovim-d2d30dfabdaacfd53b081354248402c797576482.tar.gz rneovim-d2d30dfabdaacfd53b081354248402c797576482.tar.bz2 rneovim-d2d30dfabdaacfd53b081354248402c797576482.zip |
fix(diagnostic): do not override existing config settings #16043
When using `true` as the value of a configuration option, the option is
configured to use default values. For example, if a user configures
virtual text to include the source globally (using
vim.diagnostic.config) and a specific namespace or producer configures
virtual text with `virt_text = true`, the user's global configuration is
overriden.
Instead, interpret a value of `true` to mean "use existing settings if
defined, otherwise use defaults".
-rw-r--r-- | runtime/doc/diagnostic.txt | 24 | ||||
-rw-r--r-- | runtime/lua/vim/diagnostic.lua | 80 | ||||
-rw-r--r-- | test/functional/lua/diagnostic_spec.lua | 72 |
3 files changed, 148 insertions, 28 deletions
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 75c8a2ad6f..17d317522b 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -254,12 +254,31 @@ config({opts}, {namespace}) *vim.diagnostic.config()* Configure diagnostic options globally or for a specific diagnostic namespace. + Configuration can be specified globally, per-namespace, or + ephemerally (i.e. only for a single call to + |vim.diagnostic.set()| or |vim.diagnostic.show()|). Ephemeral + configuration has highest priority, followed by namespace + configuration, and finally global configuration. + + For example, if a user enables virtual text globally with > + + vim.diagnostic.config({virt_text = true}) +< + + and a diagnostic producer sets diagnostics with > + + vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false}) +< + + then virtual text will not be enabled for those diagnostics. + Note: Each of the configuration options below accepts one of the following: • `false` : Disable this feature • `true` : Enable this feature, use default settings. - • `table` : Enable this feature with overrides. + • `table` : Enable this feature with overrides. Use an + empty table to use default values. • `function` : Function with signature (namespace, bufnr) that returns any of the above. @@ -460,8 +479,9 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults}) For example, consider a line of output from a linter: > WARNING filename:27:3: Variable 'foo' does not exist +< - < This can be parsed into a diagnostic |diagnostic-structure| + This can be parsed into a diagnostic |diagnostic-structure| with: > local s = "WARNING filename:27:3: Variable 'foo' does not exist" diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index e8aba6b7a3..326932d982 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -93,28 +93,6 @@ local function reformat_diagnostics(format, diagnostics) return formatted end ----@private -local function resolve_optional_value(option, namespace, bufnr) - local enabled_val = {} - - if not option then - return false - elseif option == true then - return enabled_val - elseif type(option) == 'function' then - local val = option(namespace, bufnr) - if val == true then - return enabled_val - else - return val - end - elseif type(option) == 'table' then - return option - else - error("Unexpected option type: " .. vim.inspect(option)) - end -end - local all_namespaces = {} ---@private @@ -140,12 +118,46 @@ local function get_namespace(ns) end ---@private +local function enabled_value(option, namespace) + local ns = get_namespace(namespace) + if type(ns.opts[option]) == "table" then + return ns.opts[option] + end + + if type(global_diagnostic_options[option]) == "table" then + return global_diagnostic_options[option] + end + + return {} +end + +---@private +local function resolve_optional_value(option, value, namespace, bufnr) + if not value then + return false + elseif value == true then + return enabled_value(option, namespace) + elseif type(value) == 'function' then + local val = value(namespace, bufnr) + if val == true then + return enabled_value(option, namespace) + else + return val + end + elseif type(value) == 'table' then + return value + else + error("Unexpected option type: " .. vim.inspect(value)) + end +end + +---@private local function get_resolved_options(opts, namespace, bufnr) local ns = get_namespace(namespace) local resolved = vim.tbl_extend('keep', opts or {}, ns.opts, global_diagnostic_options) for k in pairs(global_diagnostic_options) do if resolved[k] ~= nil then - resolved[k] = resolve_optional_value(resolved[k], namespace, bufnr) + resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr) end end return resolved @@ -542,10 +554,27 @@ end --- Configure diagnostic options globally or for a specific diagnostic --- namespace. --- +--- Configuration can be specified globally, per-namespace, or ephemerally +--- (i.e. only for a single call to |vim.diagnostic.set()| or +--- |vim.diagnostic.show()|). Ephemeral configuration has highest priority, +--- followed by namespace configuration, and finally global configuration. +--- +--- For example, if a user enables virtual text globally with +--- <pre> +--- vim.diagnostic.config({virt_text = true}) +--- </pre> +--- +--- and a diagnostic producer sets diagnostics with +--- <pre> +--- vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false}) +--- </pre> +--- +--- then virtual text will not be enabled for those diagnostics. +--- ---@note Each of the configuration options below accepts one of the following: --- - `false`: Disable this feature --- - `true`: Enable this feature, use default settings. ---- - `table`: Enable this feature with overrides. +--- - `table`: Enable this feature with overrides. Use an empty table to use default values. --- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- ---@param opts table Configuration table with the following keys: @@ -653,8 +682,6 @@ function M.set(namespace, bufnr, diagnostics, opts) if vim.api.nvim_buf_is_loaded(bufnr) then M.show(namespace, bufnr, diagnostics, opts) - elseif opts then - M.config(opts, namespace) end vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged") @@ -1277,6 +1304,7 @@ end --- <pre> --- WARNING filename:27:3: Variable 'foo' does not exist --- </pre> +--- --- This can be parsed into a diagnostic |diagnostic-structure| --- with: --- <pre> diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index a08c8d8681..33469597a1 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -473,6 +473,78 @@ describe('vim.diagnostic', function() end) describe('config()', function() + it('works with global, namespace, and ephemeral options', function() + eq(1, exec_lua [[ + vim.diagnostic.config({ + virtual_text = false, + }) + + vim.diagnostic.config({ + virtual_text = true, + underline = false, + }, diagnostic_ns) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Some Error', 4, 4, 4, 4), + }) + + return count_extmarks(diagnostic_bufnr, diagnostic_ns) + ]]) + + eq(1, exec_lua [[ + vim.diagnostic.config({ + virtual_text = false, + }) + + vim.diagnostic.config({ + virtual_text = false, + underline = false, + }, diagnostic_ns) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Some Error', 4, 4, 4, 4), + }, {virtual_text = true}) + + return count_extmarks(diagnostic_bufnr, diagnostic_ns) + ]]) + + eq(0, exec_lua [[ + vim.diagnostic.config({ + virtual_text = false, + }) + + vim.diagnostic.config({ + virtual_text = {severity=vim.diagnostic.severity.ERROR}, + underline = false, + }, diagnostic_ns) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_warning('Some Warning', 4, 4, 4, 4), + }, {virtual_text = true}) + + return count_extmarks(diagnostic_bufnr, diagnostic_ns) + ]]) + + eq(1, exec_lua [[ + vim.diagnostic.config({ + virtual_text = false, + }) + + vim.diagnostic.config({ + virtual_text = {severity=vim.diagnostic.severity.ERROR}, + underline = false, + }, diagnostic_ns) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_warning('Some Warning', 4, 4, 4, 4), + }, { + virtual_text = {} -- An empty table uses default values + }) + + return count_extmarks(diagnostic_bufnr, diagnostic_ns) + ]]) + end) + it('can use functions for config values', function() exec_lua [[ vim.diagnostic.config({ |