mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	feat(diagnostic): format() can filter diagnostics by returning nil #32302
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							3a28930157
						
					
				
				
					commit
					445ecca398
				
			@@ -376,6 +376,10 @@ Where possible, these patterns apply to _both_ Lua and the API:
 | 
				
			|||||||
  - See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()|
 | 
					  - See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()|
 | 
				
			||||||
    for a reference implementation of these "best practices".
 | 
					    for a reference implementation of these "best practices".
 | 
				
			||||||
  - NOTE: open questions: https://github.com/neovim/neovim/issues/28603
 | 
					  - NOTE: open questions: https://github.com/neovim/neovim/issues/28603
 | 
				
			||||||
 | 
					- Transformation functions should also have a filter functionality when
 | 
				
			||||||
 | 
					  appropriate. That is, when the function returns a nil value it "filters" its
 | 
				
			||||||
 | 
					  input, otherwise the transformed value is used.
 | 
				
			||||||
 | 
					  - Example: |vim.diagnostic.config.format()|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
API DESIGN GUIDELINES                                   *dev-api*
 | 
					API DESIGN GUIDELINES                                   *dev-api*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -532,11 +532,13 @@ Lua module: vim.diagnostic                                    *diagnostic-api*
 | 
				
			|||||||
                          the buffer. Otherwise, any truthy value means to
 | 
					                          the buffer. Otherwise, any truthy value means to
 | 
				
			||||||
                          always show the diagnostic source. Overrides the
 | 
					                          always show the diagnostic source. Overrides the
 | 
				
			||||||
                          setting from |vim.diagnostic.config()|.
 | 
					                          setting from |vim.diagnostic.config()|.
 | 
				
			||||||
      • {format}?         (`fun(diagnostic:vim.Diagnostic): string`) A
 | 
					      • {format}?         (`fun(diagnostic:vim.Diagnostic): string?`) A
 | 
				
			||||||
                          function that takes a diagnostic as input and
 | 
					                          function that takes a diagnostic as input and
 | 
				
			||||||
                          returns a string. The return value is the text used
 | 
					                          returns a string or nil. If the return value is nil,
 | 
				
			||||||
                          to display the diagnostic. Overrides the setting
 | 
					                          the diagnostic is not displayed by the handler. Else
 | 
				
			||||||
                          from |vim.diagnostic.config()|.
 | 
					                          the output text is used to display the diagnostic.
 | 
				
			||||||
 | 
					                          Overrides the setting from
 | 
				
			||||||
 | 
					                          |vim.diagnostic.config()|.
 | 
				
			||||||
      • {prefix}?         (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`)
 | 
					      • {prefix}?         (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`)
 | 
				
			||||||
                          Prefix each diagnostic in the floating window:
 | 
					                          Prefix each diagnostic in the floating window:
 | 
				
			||||||
                          • If a `function`, {i} is the index of the
 | 
					                          • If a `function`, {i} is the index of the
 | 
				
			||||||
@@ -607,10 +609,11 @@ Lua module: vim.diagnostic                                    *diagnostic-api*
 | 
				
			|||||||
    Fields: ~
 | 
					    Fields: ~
 | 
				
			||||||
      • {current_line}?  (`boolean`, default: `false`) Only show diagnostics
 | 
					      • {current_line}?  (`boolean`, default: `false`) Only show diagnostics
 | 
				
			||||||
                         for the current line.
 | 
					                         for the current line.
 | 
				
			||||||
      • {format}?        (`fun(diagnostic:vim.Diagnostic): string`) A function
 | 
					      • {format}?        (`fun(diagnostic:vim.Diagnostic): string?`) A
 | 
				
			||||||
                         that takes a diagnostic as input and returns a
 | 
					                         function that takes a diagnostic as input and returns
 | 
				
			||||||
                         string. The return value is the text used to display
 | 
					                         a string or nil. If the return value is nil, the
 | 
				
			||||||
                         the diagnostic.
 | 
					                         diagnostic is not displayed by the handler. Else the
 | 
				
			||||||
 | 
					                         output text is used to display the diagnostic.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*vim.diagnostic.Opts.VirtualText*
 | 
					*vim.diagnostic.Opts.VirtualText*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -635,9 +638,9 @@ Lua module: vim.diagnostic                                    *diagnostic-api*
 | 
				
			|||||||
      • {suffix}?             (`string|(fun(diagnostic:vim.Diagnostic): string)`)
 | 
					      • {suffix}?             (`string|(fun(diagnostic:vim.Diagnostic): string)`)
 | 
				
			||||||
                              Append diagnostic message with suffix. This can
 | 
					                              Append diagnostic message with suffix. This can
 | 
				
			||||||
                              be used to render an LSP diagnostic error code.
 | 
					                              be used to render an LSP diagnostic error code.
 | 
				
			||||||
      • {format}?             (`fun(diagnostic:vim.Diagnostic): string`) The
 | 
					      • {format}?             (`fun(diagnostic:vim.Diagnostic): string?`) If
 | 
				
			||||||
                              return value is the text used to display the
 | 
					                              not nil, the return value is the text used to
 | 
				
			||||||
                              diagnostic. Example: >lua
 | 
					                              display the diagnostic. Example: >lua
 | 
				
			||||||
                                  function(diagnostic)
 | 
					                                  function(diagnostic)
 | 
				
			||||||
                                    if diagnostic.severity == vim.diagnostic.severity.ERROR then
 | 
					                                    if diagnostic.severity == vim.diagnostic.severity.ERROR then
 | 
				
			||||||
                                      return string.format("E: %s", diagnostic.message)
 | 
					                                      return string.format("E: %s", diagnostic.message)
 | 
				
			||||||
@@ -645,6 +648,9 @@ Lua module: vim.diagnostic                                    *diagnostic-api*
 | 
				
			|||||||
                                    return diagnostic.message
 | 
					                                    return diagnostic.message
 | 
				
			||||||
                                  end
 | 
					                                  end
 | 
				
			||||||
<
 | 
					<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                              If the return value is nil, the diagnostic is
 | 
				
			||||||
 | 
					                              not displayed by the handler.
 | 
				
			||||||
      • {hl_mode}?            (`'replace'|'combine'|'blend'`) See
 | 
					      • {hl_mode}?            (`'replace'|'combine'|'blend'`) See
 | 
				
			||||||
                              |nvim_buf_set_extmark()|.
 | 
					                              |nvim_buf_set_extmark()|.
 | 
				
			||||||
      • {virt_text}?          (`[string,any][]`) See |nvim_buf_set_extmark()|.
 | 
					      • {virt_text}?          (`[string,any][]`) See |nvim_buf_set_extmark()|.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -150,10 +150,11 @@ end
 | 
				
			|||||||
--- Overrides the setting from |vim.diagnostic.config()|.
 | 
					--- Overrides the setting from |vim.diagnostic.config()|.
 | 
				
			||||||
--- @field source? boolean|'if_many'
 | 
					--- @field source? boolean|'if_many'
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
--- A function that takes a diagnostic as input and returns a string.
 | 
					--- A function that takes a diagnostic as input and returns a string or nil.
 | 
				
			||||||
--- The return value is the text used to display the diagnostic.
 | 
					--- If the return value is nil, the diagnostic is not displayed by the handler.
 | 
				
			||||||
 | 
					--- Else the output text is used to display the diagnostic.
 | 
				
			||||||
--- Overrides the setting from |vim.diagnostic.config()|.
 | 
					--- Overrides the setting from |vim.diagnostic.config()|.
 | 
				
			||||||
--- @field format? fun(diagnostic:vim.Diagnostic): string
 | 
					--- @field format? fun(diagnostic:vim.Diagnostic): string?
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
--- Prefix each diagnostic in the floating window:
 | 
					--- Prefix each diagnostic in the floating window:
 | 
				
			||||||
--- - If a `function`, {i} is the index of the diagnostic being evaluated and
 | 
					--- - If a `function`, {i} is the index of the diagnostic being evaluated and
 | 
				
			||||||
@@ -207,7 +208,7 @@ end
 | 
				
			|||||||
--- This can be used to render an LSP diagnostic error code.
 | 
					--- This can be used to render an LSP diagnostic error code.
 | 
				
			||||||
--- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string)
 | 
					--- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string)
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
--- The return value is the text used to display the diagnostic. Example:
 | 
					--- If not nil, the return value is the text used to display the diagnostic. Example:
 | 
				
			||||||
--- ```lua
 | 
					--- ```lua
 | 
				
			||||||
--- function(diagnostic)
 | 
					--- function(diagnostic)
 | 
				
			||||||
---   if diagnostic.severity == vim.diagnostic.severity.ERROR then
 | 
					---   if diagnostic.severity == vim.diagnostic.severity.ERROR then
 | 
				
			||||||
@@ -216,7 +217,8 @@ end
 | 
				
			|||||||
---   return diagnostic.message
 | 
					---   return diagnostic.message
 | 
				
			||||||
--- end
 | 
					--- end
 | 
				
			||||||
--- ```
 | 
					--- ```
 | 
				
			||||||
--- @field format? fun(diagnostic:vim.Diagnostic): string
 | 
					--- If the return value is nil, the diagnostic is not displayed by the handler.
 | 
				
			||||||
 | 
					--- @field format? fun(diagnostic:vim.Diagnostic): string?
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
--- See |nvim_buf_set_extmark()|.
 | 
					--- See |nvim_buf_set_extmark()|.
 | 
				
			||||||
--- @field hl_mode? 'replace'|'combine'|'blend'
 | 
					--- @field hl_mode? 'replace'|'combine'|'blend'
 | 
				
			||||||
@@ -239,9 +241,10 @@ end
 | 
				
			|||||||
--- (default: `false`)
 | 
					--- (default: `false`)
 | 
				
			||||||
--- @field current_line? boolean
 | 
					--- @field current_line? boolean
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
--- A function that takes a diagnostic as input and returns a string.
 | 
					--- A function that takes a diagnostic as input and returns a string or nil.
 | 
				
			||||||
--- The return value is the text used to display the diagnostic.
 | 
					--- If the return value is nil, the diagnostic is not displayed by the handler.
 | 
				
			||||||
--- @field format? fun(diagnostic:vim.Diagnostic): string
 | 
					--- Else the output text is used to display the diagnostic.
 | 
				
			||||||
 | 
					--- @field format? fun(diagnostic:vim.Diagnostic): string?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--- @class vim.diagnostic.Opts.Signs
 | 
					--- @class vim.diagnostic.Opts.Signs
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
@@ -503,15 +506,21 @@ local function prefix_source(diagnostics)
 | 
				
			|||||||
  end, diagnostics)
 | 
					  end, diagnostics)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- @param format fun(vim.Diagnostic): string?
 | 
				
			||||||
--- @param diagnostics vim.Diagnostic[]
 | 
					--- @param diagnostics vim.Diagnostic[]
 | 
				
			||||||
--- @return vim.Diagnostic[]
 | 
					--- @return vim.Diagnostic[]
 | 
				
			||||||
local function reformat_diagnostics(format, diagnostics)
 | 
					local function reformat_diagnostics(format, diagnostics)
 | 
				
			||||||
  vim.validate('format', format, 'function')
 | 
					  vim.validate('format', format, 'function')
 | 
				
			||||||
  vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics')
 | 
					  vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local formatted = vim.deepcopy(diagnostics, true)
 | 
					  local formatted = {}
 | 
				
			||||||
  for _, diagnostic in ipairs(formatted) do
 | 
					  for _, diagnostic in ipairs(diagnostics) do
 | 
				
			||||||
    diagnostic.message = format(diagnostic)
 | 
					    local message = format(diagnostic)
 | 
				
			||||||
 | 
					    if message ~= nil then
 | 
				
			||||||
 | 
					      local formatted_diagnostic = vim.deepcopy(diagnostic, true)
 | 
				
			||||||
 | 
					      formatted_diagnostic.message = message
 | 
				
			||||||
 | 
					      table.insert(formatted, formatted_diagnostic)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  return formatted
 | 
					  return formatted
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2134,6 +2134,32 @@ describe('vim.diagnostic', function()
 | 
				
			|||||||
        end)
 | 
					        end)
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    end)
 | 
					    end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('can filter diagnostics by returning nil when formatting', function()
 | 
				
			||||||
 | 
					      local result = exec_lua(function()
 | 
				
			||||||
 | 
					        vim.diagnostic.config {
 | 
				
			||||||
 | 
					          virtual_text = {
 | 
				
			||||||
 | 
					            format = function(diagnostic)
 | 
				
			||||||
 | 
					              if diagnostic.code == 'foo_err' then
 | 
				
			||||||
 | 
					                return nil
 | 
				
			||||||
 | 
					              end
 | 
				
			||||||
 | 
					              return diagnostic.message
 | 
				
			||||||
 | 
					            end,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
 | 
				
			||||||
 | 
					          _G.make_error('An error here!', 0, 0, 0, 0, 'foo_server', 'foo_err'),
 | 
				
			||||||
 | 
					          _G.make_error('An error there!', 1, 1, 1, 1, 'bar_server', 'bar_err'),
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
 | 
				
			||||||
 | 
					        return extmarks
 | 
				
			||||||
 | 
					      end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      eq(1, #result)
 | 
				
			||||||
 | 
					      eq(' An error there!', result[1][4].virt_text[3][1])
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('handlers.virtual_lines', function()
 | 
					  describe('handlers.virtual_lines', function()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user