local api = vim.api
local validate = vim.validate
local highlight = vim.highlight
local log = require('vim.lsp.log')
local protocol = require('vim.lsp.protocol')
local util = require('vim.lsp.util')
local if_nil = vim.F.if_nil
--@class DiagnosticSeverity
local DiagnosticSeverity = protocol.DiagnosticSeverity
local to_severity = function(severity)
if not severity then return nil end
return type(severity) == 'string' and DiagnosticSeverity[severity] or severity
end
local filter_to_severity_limit = function(severity, diagnostics)
local filter_level = to_severity(severity)
if not filter_level then
return diagnostics
end
return vim.tbl_filter(function(t) return t.severity == filter_level end, diagnostics)
end
local filter_by_severity_limit = function(severity_limit, diagnostics)
local filter_level = to_severity(severity_limit)
if not filter_level then
return diagnostics
end
return vim.tbl_filter(function(t) return t.severity <= filter_level end, diagnostics)
end
local to_position = function(position, bufnr)
vim.validate { position = {position, 't'} }
return {
position.line,
util._get_line_byte_from_position(bufnr, position)
}
end
---@brief lsp-diagnostic
---
--@class Diagnostic
--@field range Range
--@field message string
--@field severity DiagnosticSeverity|nil
--@field code number | string
--@field source string
--@field tags DiagnosticTag[]
--@field relatedInformation DiagnosticRelatedInformation[]
local M = {}
-- Diagnostic Highlights {{{
-- TODO(tjdevries): Determine how to generate documentation for these
-- and how to configure them to be easy for users.
--
-- For now, just use the following script. It should work pretty good.
--[[
local levels = {"Error", "Warning", "Information", "Hint" }
local all_info = {
{ "Default", "Used as the base highlight group, other highlight groups link to", },
{ "VirtualText", 'Used for "%s" diagnostic virtual text.\n See |vim.lsp.diagnostic.set_virtual_text()|', },
{ "Underline", 'Used to underline "%s" diagnostics.\n See |vim.lsp.diagnostic.set_underline()|', },
{ "Floating", 'Used to color "%s" diagnostic messages in diagnostics float.\n See |vim.lsp.diagnostic.show_line_diagnostics()|', },
{ "Sign", 'Used for "%s" signs in sing column.\n See |vim.lsp.diagnostic.set_signs()|', },
}
local results = {}
for _, info in ipairs(all_info) do
for _, level in ipairs(levels) do
local name = info[1]
local description = info[2]
local fullname = string.format("Lsp%s%s", name, level)
table.insert(results, string.format(
"%78s", string.format("*hl-%s*", fullname))
)
table.insert(results, fullname)
table.insert(results, string.format(" %s", description))
table.insert(results, "")
end
end
-- print(table.concat(results, '\n'))
vim.fn.setreg("*", table.concat(results, '\n'))
--]]
local diagnostic_severities = {
[DiagnosticSeverity.Error] = { guifg = "Red" };
[DiagnosticSeverity.Warning] = { guifg = "Orange" };
[DiagnosticSeverity.Information] = { guifg = "LightBlue" };
[DiagnosticSeverity.Hint] = { guifg = "LightGrey" };
}
-- Make a map from DiagnosticSeverity -> Highlight Name
local make_highlight_map = function(base_name)
local result = {}
for k, _ in pairs(diagnostic_severities) do
result[k] = "LspDiagnostics" .. base_name .. DiagnosticSeverity[k]
end
return result
end
local default_highlight_map = make_highlight_map("Default")
local virtual_text_highlight_map = make_highlight_map("VirtualText")
local underline_highlight_map = make_highlight_map("Underline")
local floating_highlight_map = make_highlight_map("Floating")
local sign_highlight_map = make_highlight_map("Sign")
-- }}}
-- Diagnostic Namespaces {{{
local DEFAULT_CLIENT_ID = -1
local get_client_id = function(client_id)
if client_id == nil then
client_id = DEFAULT_CLIENT_ID
end
return client_id
end
local get_bufnr = function(bufnr)
if not bufnr then
return api.nvim_get_current_buf()
elseif bufnr == 0 then
return api.nvim_get_current_buf()
end
return bufnr
end
--- Create a namespace table, used to track a client's buffer local items
local _make_namespace_table = function(namespace, api_namespace)
vim.validate { namespace = { namespace, 's' } }
return setmetatable({
[DEFAULT_CLIENT_ID] = api.nvim_create_namespace(namespace)
}, {
__index = function(t, client_id)
client_id = get_client_id(client_id)
if rawget(t, client_id) == nil then
local value = string.format("%s:%s", namespace, client_id)
if api_namespace then
value = api.nvim_create_namespace(value)
end
rawset(t, client_id, value)
end
return rawget(t, client_id)
end
})
end
local _diagnostic_namespaces = _make_namespace_table(
|