summaryrefslogtreecommitdiff
path: root/lua/telescope/builtin/__diagnostics.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/telescope/builtin/__diagnostics.lua')
-rw-r--r--lua/telescope/builtin/__diagnostics.lua150
1 files changed, 150 insertions, 0 deletions
diff --git a/lua/telescope/builtin/__diagnostics.lua b/lua/telescope/builtin/__diagnostics.lua
new file mode 100644
index 0000000..2614e36
--- /dev/null
+++ b/lua/telescope/builtin/__diagnostics.lua
@@ -0,0 +1,150 @@
+local conf = require("telescope.config").values
+local finders = require "telescope.finders"
+local make_entry = require "telescope.make_entry"
+local pickers = require "telescope.pickers"
+local utils = require "telescope.utils"
+
+local diagnostics = {}
+
+local convert_diagnostic_type = function(severities, severity)
+ -- convert from string to int
+ if type(severity) == "string" then
+ -- make sure that e.g. error is uppercased to ERROR
+ return severities[severity:upper()]
+ end
+ -- otherwise keep original value, incl. nil
+ return severity
+end
+
+local diagnostics_to_tbl = function(opts)
+ opts = vim.F.if_nil(opts, {})
+ local items = {}
+ local severities = vim.diagnostic.severity
+ local current_buf = vim.api.nvim_get_current_buf()
+
+ opts.severity = convert_diagnostic_type(severities, opts.severity)
+ opts.severity_limit = convert_diagnostic_type(severities, opts.severity_limit)
+ opts.severity_bound = convert_diagnostic_type(severities, opts.severity_bound)
+
+ local diagnosis_opts = { severity = {}, namespace = opts.namespace }
+ if opts.severity ~= nil then
+ if opts.severity_limit ~= nil or opts.severity_bound ~= nil then
+ utils.notify("builtin.diagnostics", {
+ msg = "Invalid severity parameters. Both a specific severity and a limit/bound is not allowed",
+ level = "ERROR",
+ })
+ return {}
+ end
+ diagnosis_opts.severity = opts.severity
+ else
+ if opts.severity_limit ~= nil then
+ diagnosis_opts.severity["min"] = opts.severity_limit
+ end
+ if opts.severity_bound ~= nil then
+ diagnosis_opts.severity["max"] = opts.severity_bound
+ end
+ end
+
+ opts.root_dir = opts.root_dir == true and vim.loop.cwd() or opts.root_dir
+
+ local bufnr_name_map = {}
+ local filter_diag = function(diagnostic)
+ if bufnr_name_map[diagnostic.bufnr] == nil then
+ bufnr_name_map[diagnostic.bufnr] = vim.api.nvim_buf_get_name(diagnostic.bufnr)
+ end
+
+ local root_dir_test = not opts.root_dir
+ or string.sub(bufnr_name_map[diagnostic.bufnr], 1, #opts.root_dir) == opts.root_dir
+ local listed_test = not opts.no_unlisted or vim.api.nvim_buf_get_option(diagnostic.bufnr, "buflisted")
+
+ return root_dir_test and listed_test
+ end
+
+ local preprocess_diag = function(diagnostic)
+ return {
+ bufnr = diagnostic.bufnr,
+ filename = bufnr_name_map[diagnostic.bufnr],
+ lnum = diagnostic.lnum + 1,
+ col = diagnostic.col + 1,
+ text = vim.trim(diagnostic.message:gsub("[\n]", "")),
+ type = severities[diagnostic.severity] or severities[1],
+ }
+ end
+
+ for _, d in ipairs(vim.diagnostic.get(opts.bufnr, diagnosis_opts)) do
+ if filter_diag(d) then
+ table.insert(items, preprocess_diag(d))
+ end
+ end
+
+ -- sort results by bufnr (prioritize cur buf), severity, lnum
+ table.sort(items, function(a, b)
+ if a.bufnr == b.bufnr then
+ if a.type == b.type then
+ return a.lnum < b.lnum
+ else
+ return a.type < b.type
+ end
+ else
+ -- prioritize for current bufnr
+ if a.bufnr == current_buf then
+ return true
+ end
+ if b.bufnr == current_buf then
+ return false
+ end
+ return a.bufnr < b.bufnr
+ end
+ end)
+
+ return items
+end
+
+diagnostics.get = function(opts)
+ if opts.bufnr ~= 0 then
+ opts.bufnr = nil
+ end
+ if opts.bufnr == nil then
+ opts.path_display = vim.F.if_nil(opts.path_display, {})
+ end
+ if type(opts.bufnr) == "string" then
+ opts.bufnr = tonumber(opts.bufnr)
+ end
+
+ local locations = diagnostics_to_tbl(opts)
+
+ if vim.tbl_isempty(locations) then
+ utils.notify("builtin.diagnostics", {
+ msg = "No diagnostics found",
+ level = "INFO",
+ })
+ return
+ end
+
+ opts.path_display = vim.F.if_nil(opts.path_display, "hidden")
+ pickers.new(opts, {
+ prompt_title = opts.bufnr == nil and "Workspace Diagnostics" or "Document Diagnostics",
+ finder = finders.new_table {
+ results = locations,
+ entry_maker = opts.entry_maker or make_entry.gen_from_diagnostics(opts),
+ },
+ previewer = conf.qflist_previewer(opts),
+ sorter = conf.prefilter_sorter {
+ tag = "type",
+ sorter = conf.generic_sorter(opts),
+ },
+ }):find()
+end
+
+local function apply_checks(mod)
+ for k, v in pairs(mod) do
+ mod[k] = function(opts)
+ opts = opts or {}
+ v(opts)
+ end
+ end
+
+ return mod
+end
+
+return apply_checks(diagnostics)