Files
gitlab.nvim/lua/gitlab/indicators/diagnostics.lua
Harrison (Harry) Cramer e29909cd10 Bugfixes, Etc. (#502)
* Fix: Jumping to renamed files (#484)

* fix: prevent "cursor position outside buffer" error

* fix: swap file_name and old_file_name in reviewer data

`old_file_name` is not set to the empty string for un-renamed files anymore, because then we can
remove the empty-line check in `comment_helpers.go` which was used to replace the empty string with
the current file name anyway.

* fix: add old_file_name to discussion root node data

* fix: also consider old_file_name when jumping to the reviewer

This fixes jumping to renamed files, however, may not work for comments that
were created on renamed files with the previous version of `gitlab.nvim` as
that version assigned the `file_name` and `old_file_name` incorrectly.

* refactor: don't shadow variable

* fix: check file_name or old_file_name based on which SHA comment belongs to

* Fix: Store reviewer data before creating comment popup (#476)

* Fix: Make publishing drafts more robust (#483)

* Fix: Swap file_name and old_file_name in reviewer data (#485)

* Feat: Enable toggling date format between relative and absolute (#491)

* Fix: Add opts to help popup (#492)

* Fix: Force start_line for jumping to diagnostic to be inside buffer (#494)

* fix: redefine colors after reloading colorscheme (#500)

* Fix: Use path instead of oldpath as fallback for unrenamed files (#496)

* Fix: Use file_name when old_file_name is not set (#495)

* fix(ci): fix lua tests (#501)

* Proxy Support (#499)

This is a #MINOR release.

---------

Co-authored-by: Jakub F. Bortlík <jakub.bortlik@proton.me>
Co-authored-by: Jonathan Duck <Duckbrain30@gmail.com>
2025-06-24 20:53:51 -04:00

166 lines
5.6 KiB
Lua

local u = require("gitlab.utils")
local diffview_lib = require("diffview.lib")
local indicators_common = require("gitlab.indicators.common")
local actions_common = require("gitlab.actions.common")
local List = require("gitlab.utils.list")
local state = require("gitlab.state")
local discussion_sign_name = "gitlab_discussion"
local M = {}
local diagnostics_namespace = vim.api.nvim_create_namespace(discussion_sign_name)
M.diagnostics_namespace = diagnostics_namespace
M.discussion_sign_name = discussion_sign_name
M.clear_diagnostics = function()
vim.diagnostic.reset(diagnostics_namespace)
end
-- Display options for the diagnostic
local create_display_opts = function()
return {
virtual_text = state.settings.discussion_signs.virtual_text,
severity_sort = true,
underline = false,
signs = state.settings.discussion_signs.use_diagnostic_signs,
}
end
---Takes some range information and data about a discussion
---and creates a diagnostic to be placed in the reviewer
---@param range_info table
---@param d_or_n Discussion|DraftNote
---@return Diagnostic
local function create_diagnostic(range_info, d_or_n)
local first_note = indicators_common.get_first_note(d_or_n)
local header = actions_common.build_note_header(first_note)
local message = header
if d_or_n.notes then
for _, note in ipairs(d_or_n.notes or {}) do
message = message .. "\n" .. note.body .. "\n"
end
else
message = message .. "\n" .. d_or_n.note .. "\n"
end
local diagnostic = {
message = message,
col = 0,
severity = state.settings.discussion_signs.severity,
user_data = { discussion_id = d_or_n.id, header = header },
source = "gitlab",
code = "gitlab.nvim",
}
return vim.tbl_deep_extend("force", diagnostic, range_info)
end
---Creates a single line diagnostic
---@param d_or_n Discussion|DraftNote
---@return Diagnostic
local create_single_line_diagnostic = function(d_or_n)
local linnr = actions_common.get_line_number(d_or_n.id)
return create_diagnostic({
lnum = linnr - 1,
}, d_or_n)
end
---Creates a mutli-line line diagnostic
---@param d_or_n Discussion|DraftNote
---@return Diagnostic
local create_multiline_diagnostic = function(d_or_n)
local first_note = indicators_common.get_first_note(d_or_n)
local line_range = first_note.position.line_range
if line_range == nil then
error("Parsing multi-line comment but note does not contain line range")
end
local start_line, end_line, _ = actions_common.get_line_numbers_for_range(
first_note.position.old_line,
first_note.position.new_line,
line_range.start.line_code,
line_range["end"].line_code
)
return create_diagnostic({
lnum = start_line - 1,
end_lnum = end_line - 1,
}, d_or_n)
end
---Set diagnostics in the given buffer.
---@param namespace number namespace for diagnostics
---@param bufnr number the bufnr for placing the diagnostics
---@param diagnostics table see :h vim.diagnostic.set
---@param opts table? see :h vim.diagnostic.set
local set_diagnostics = function(namespace, bufnr, diagnostics, opts)
vim.diagnostic.set(namespace, bufnr, diagnostics, opts)
require("gitlab.indicators.signs").set_signs(diagnostics, bufnr)
end
---Refresh the diagnostics for all the reviewed files, and place diagnostics for the currently
---visible buffers.
M.refresh_diagnostics = function()
require("gitlab.indicators.signs").clear_signs()
M.clear_diagnostics()
M.placeable_discussions = indicators_common.filter_placeable_discussions()
local view = diffview_lib.get_current_view()
if view == nil then
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
return
end
M.place_diagnostics(view.cur_layout.a.file.bufnr)
M.place_diagnostics(view.cur_layout.b.file.bufnr)
end
---Filter and place the diagnostics for the given buffer.
---@param bufnr number The number of the buffer for placing diagnostics.
M.place_diagnostics = function(bufnr)
if not state.settings.discussion_signs.enabled then
return
end
local view = diffview_lib.get_current_view()
if view == nil then
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
return
end
if vim.api.nvim_buf_get_name(bufnr) == "diffview://null" then
return
end
local ok, err = pcall(function()
local file_discussions = List.new(M.placeable_discussions):filter(function(discussion_or_note)
local note = discussion_or_note.notes and discussion_or_note.notes[1] or discussion_or_note
return note.position.new_path == view.cur_layout.b.file.path
or note.position.old_path == view.cur_layout.a.file.path
end)
if #file_discussions == 0 then
return
end
local new_diagnostics, old_diagnostics = List.new(file_discussions):partition(indicators_common.is_new_sha)
if bufnr == view.cur_layout.a.file.bufnr then
set_diagnostics(diagnostics_namespace, bufnr, M.parse_diagnostics(old_diagnostics), create_display_opts())
elseif bufnr == view.cur_layout.b.file.bufnr then
set_diagnostics(diagnostics_namespace, bufnr, M.parse_diagnostics(new_diagnostics), create_display_opts())
end
end)
if not ok then
u.notify(string.format("Error setting diagnostics: %s", err), vim.log.levels.ERROR)
end
end
---Iterates over each discussion and returns a list of tables with sign
---data, for instance group, priority, line number etc
---@param discussions List
---@return DiagnosticTable[]
M.parse_diagnostics = function(discussions)
local single_line, multi_line = discussions:partition(indicators_common.is_single_line)
single_line = single_line:map(create_single_line_diagnostic)
multi_line = multi_line:map(create_multiline_diagnostic)
return u.combine(single_line, multi_line)
end
return M