2.0.0 (#196)
This MR is a #MAJOR breaking change to the plugin. While the plugin will continue to work for users with their existing settings, they will be informed of outdated configuration (diagnostics and signs have been simplified) the next time they open the reviewer. Fix: Trim trailing slash from custom URLs Update: .github/CONTRIBUTING.md, .github/ISSUE_TEMPLATE/bug_report.md Feat: Improve discussion tree toggling (#192) Fix: Toggle modified notes (#188) Fix: Toggle discussion nodes correctly Feat: Show Help keymap in discussion tree winbar Fix: Enable toggling nodes from the note body Fix: Enable toggling resolved status from child nodes Fix: Only try to show emoji popup on note nodes Feat: Add keymap for toggling tree type Fix: Disable tree type toggling in Notes Fix Multi Line Issues (Large Refactor) (#197) Fix: Multi-line discussions. The calculation of a range for a multiline comment has been consolidated and moved into the location.lua file. This does not attempt to fix diagnostics. Refactor: It refactors the discussions code to split hunk parsing and management into a separate module Fix: Don't allow comments on modified buffers #194 by preventing comments on the reviewer when using --imply-local and when the working tree is dirty entirely. Refactor: It introduces a new List class for data aggregation, filtering, etc. Fix: It removes redundant API calls and refreshes from the discussion pane Fix: Location provider (#198) Fix: add nil check for Diffview performance issue (#199) Fix: Switch Tabs During Comment Creation (#200) Fix: Check if file is modified (#201) Fix: Off-By-One Issue in Old SHA (#202) Fix: Rebuild Diagnostics + Signs (#203) Fix: Off-By-One Issue in New SHA (#205) Fix: Reviewer Jumps to wrong location (#206) BREAKING CHANGE: Changes configuration of diagnostics and signs in the setup call.
This commit is contained in:
committed by
GitHub
parent
f6a5238d4b
commit
b5b475ce8b
@@ -1,74 +1,265 @@
|
||||
-- This Module contains all of the reviewer code. This is the code
|
||||
-- that parses or interacts with diffview directly, such as opening
|
||||
-- and closing, getting metadata about the current view, and registering
|
||||
-- callbacks for open/close actions.
|
||||
|
||||
local List = require("gitlab.utils.list")
|
||||
local u = require("gitlab.utils")
|
||||
local state = require("gitlab.state")
|
||||
local diffview = require("gitlab.reviewer.diffview")
|
||||
local git = require("gitlab.git")
|
||||
local hunks = require("gitlab.hunks")
|
||||
local async = require("diffview.async")
|
||||
local diffview_lib = require("diffview.lib")
|
||||
|
||||
local M = {
|
||||
reviewer = nil,
|
||||
}
|
||||
|
||||
local reviewer_map = {
|
||||
diffview = diffview,
|
||||
bufnr = nil,
|
||||
tabnr = nil,
|
||||
stored_win = nil,
|
||||
}
|
||||
|
||||
-- Checks for legacy installations, only Diffview is supported.
|
||||
M.init = function()
|
||||
local reviewer = reviewer_map[state.settings.reviewer]
|
||||
if reviewer == nil then
|
||||
if state.settings.reviewer ~= "diffview" then
|
||||
vim.notify(
|
||||
string.format("gitlab.nvim could not find reviewer %s, only diffview is supported", state.settings.reviewer),
|
||||
vim.log.levels.ERROR
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
-- Opens the reviewer window.
|
||||
M.open = function()
|
||||
local diff_refs = state.INFO.diff_refs
|
||||
if diff_refs == nil then
|
||||
u.notify("Gitlab did not provide diff refs required to review this MR", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
M.open = reviewer.open
|
||||
-- Opens the reviewer window
|
||||
if diff_refs.base_sha == "" or diff_refs.head_sha == "" then
|
||||
u.notify("Merge request contains no changes", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
M.close = reviewer.close
|
||||
-- Closes the reviewer and cleans up
|
||||
local diffview_open_command = "DiffviewOpen"
|
||||
local has_clean_tree = git.has_clean_tree()
|
||||
if state.settings.reviewer_settings.diffview.imply_local and has_clean_tree then
|
||||
diffview_open_command = diffview_open_command .. " --imply-local"
|
||||
end
|
||||
|
||||
M.jump = reviewer.jump
|
||||
-- Jumps to the location provided in the reviewer window
|
||||
-- Parameters:
|
||||
-- • {file_name} The name of the file to jump to
|
||||
-- • {new_line} The new_line of the change
|
||||
-- • {interval} The old_line of the change
|
||||
vim.api.nvim_command(string.format("%s %s..%s", diffview_open_command, diff_refs.base_sha, diff_refs.head_sha))
|
||||
M.tabnr = vim.api.nvim_get_current_tabpage()
|
||||
|
||||
M.get_location = reviewer.get_location
|
||||
-- Parameters:
|
||||
-- • {range} LineRange if function was triggered from visual selection
|
||||
-- Returns the current location (based on cursor) from the reviewer window as ReviewerInfo class
|
||||
if state.settings.reviewer_settings.diffview.imply_local and not has_clean_tree then
|
||||
u.notify(
|
||||
"There are uncommited changes in the working tree, cannot use 'imply_local' setting for gitlab reviews.\n Stash or commit all changes to use.",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
|
||||
M.get_lines = reviewer.get_lines
|
||||
-- Returns the content of the file in the current location in the reviewer window
|
||||
if state.INFO.has_conflicts then
|
||||
u.notify("This merge request has conflicts!", vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
M.get_current_file = reviewer.get_current_file
|
||||
-- Get currently loaded file
|
||||
if state.settings.discussion_diagnostic ~= nil or state.settings.discussion_sign ~= nil then
|
||||
u.notify(
|
||||
"Diagnostics are now configured settings.discussion_signs, see :h gitlab.signs_and_diagnostics",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
|
||||
M.place_sign = reviewer.place_sign
|
||||
-- Places a sign on the line for currently reviewed file.
|
||||
-- Parameters:
|
||||
-- • {id} The sign id
|
||||
-- • {sign} The sign to place
|
||||
-- • {group} The sign group to place on
|
||||
-- • {new_line} The line to place the sign on
|
||||
-- • {old_line} The buffer number to place the sign on
|
||||
-- Register Diffview hook for close event to set tab page # to nil
|
||||
local on_diffview_closed = function(view)
|
||||
if view.tabpage == M.tabnr then
|
||||
M.tabnr = nil
|
||||
end
|
||||
end
|
||||
require("diffview.config").user_emitter:on("view_closed", function(_, ...)
|
||||
on_diffview_closed(...)
|
||||
end)
|
||||
|
||||
M.set_callback_for_file_changed = reviewer.set_callback_for_file_changed
|
||||
-- Call callback whenever the file changes
|
||||
-- Parameters:
|
||||
-- • {callback} The callback to call
|
||||
if state.settings.discussion_tree.auto_open then
|
||||
local discussions = require("gitlab.actions.discussions")
|
||||
discussions.close()
|
||||
discussions.toggle()
|
||||
end
|
||||
end
|
||||
|
||||
M.set_callback_for_reviewer_leave = reviewer.set_callback_for_reviewer_leave
|
||||
-- Call callback whenever the reviewer is left
|
||||
-- Parameters:
|
||||
-- • {callback} The callback to call
|
||||
-- Closes the reviewer and cleans up
|
||||
M.close = function()
|
||||
vim.cmd("DiffviewClose")
|
||||
local discussions = require("gitlab.actions.discussions")
|
||||
discussions.close()
|
||||
end
|
||||
|
||||
M.set_diagnostics = reviewer.set_diagnostics
|
||||
-- Set diagnostics for currently reviewed file
|
||||
-- Parameters:
|
||||
-- • {namespace} The namespace for diagnostics
|
||||
-- • {diagnostics} The diagnostics to set
|
||||
-- • {type} "new" if diagnostic should be in file after changes else "old"
|
||||
-- • {opts} see opts in :h vim.diagnostic.set
|
||||
-- Jumps to the location provided in the reviewer window
|
||||
---@param file_name string
|
||||
---@param new_line number|nil
|
||||
---@param old_line number|nil
|
||||
M.jump = function(file_name, new_line, old_line)
|
||||
if M.tabnr == nil then
|
||||
u.notify("Can't jump to Diffvew. Is it open?", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
vim.api.nvim_set_current_tabpage(M.tabnr)
|
||||
vim.cmd("DiffviewFocusFiles")
|
||||
local view = diffview_lib.get_current_view()
|
||||
if view == nil then
|
||||
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local files = view.panel:ordered_file_list()
|
||||
local file = List.new(files):find(function(file)
|
||||
return file.path == file_name
|
||||
end)
|
||||
async.await(view:set_file(file))
|
||||
|
||||
local layout = view.cur_layout
|
||||
if old_line == nil then
|
||||
layout.b:focus()
|
||||
vim.api.nvim_win_set_cursor(0, { new_line, 0 })
|
||||
else
|
||||
layout.a:focus()
|
||||
vim.api.nvim_win_set_cursor(0, { old_line, 0 })
|
||||
end
|
||||
end
|
||||
|
||||
---Get the data from diffview, such as line information and file name. May be used by
|
||||
---other modules such as the comment module to create line codes or set diagnostics
|
||||
---@return DiffviewInfo | nil
|
||||
M.get_reviewer_data = function()
|
||||
if M.tabnr == nil then
|
||||
u.notify("Diffview reviewer must be initialized first", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if we are in the diffview tab
|
||||
local tabnr = vim.api.nvim_get_current_tabpage()
|
||||
if tabnr ~= M.tabnr then
|
||||
u.notify("Line location can only be determined within reviewer window", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if we are in the diffview buffer
|
||||
local view = diffview_lib.get_current_view()
|
||||
if view == nil then
|
||||
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local layout = view.cur_layout
|
||||
local old_win = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
|
||||
local new_win = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
|
||||
|
||||
if old_win == nil or new_win == nil then
|
||||
u.notify("Error getting window IDs for current files", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local current_file = M.get_current_file()
|
||||
if current_file == nil then
|
||||
u.notify("Error getting current file from Diffview", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local new_line = vim.api.nvim_win_get_cursor(new_win)[1]
|
||||
local old_line = vim.api.nvim_win_get_cursor(old_win)[1]
|
||||
|
||||
local is_current_sha_focused = M.is_current_sha_focused()
|
||||
local modification_type = hunks.get_modification_type(old_line, new_line, current_file, is_current_sha_focused)
|
||||
if modification_type == nil then
|
||||
u.notify("Error getting modification type", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
if modification_type == "bad_file_unmodified" then
|
||||
u.notify("Comments on unmodified lines will be placed in the old file", vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
local current_bufnr = is_current_sha_focused and layout.b.file.bufnr or layout.a.file.bufnr
|
||||
local opposite_bufnr = is_current_sha_focused and layout.a.file.bufnr or layout.b.file.bufnr
|
||||
local old_sha_win_id = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
|
||||
local new_sha_win_id = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
|
||||
|
||||
return {
|
||||
file_name = layout.a.file.path,
|
||||
old_line_from_buf = old_line,
|
||||
new_line_from_buf = new_line,
|
||||
modification_type = modification_type,
|
||||
new_sha_win_id = new_sha_win_id,
|
||||
current_bufnr = current_bufnr,
|
||||
old_sha_win_id = old_sha_win_id,
|
||||
opposite_bufnr = opposite_bufnr,
|
||||
}
|
||||
end
|
||||
|
||||
---Return whether user is focused on the new version of the file
|
||||
---@return boolean
|
||||
M.is_current_sha_focused = function()
|
||||
local view = diffview_lib.get_current_view()
|
||||
local layout = view.cur_layout
|
||||
local b_win = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
|
||||
local a_win = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
|
||||
local current_win = vim.fn.win_getid()
|
||||
|
||||
-- Handle cases where user navigates tabs in the middle of making a comment
|
||||
if a_win ~= current_win and b_win ~= current_win then
|
||||
current_win = M.stored_win
|
||||
M.stored_win = nil
|
||||
end
|
||||
return current_win == b_win
|
||||
end
|
||||
|
||||
---Get currently shown file
|
||||
---@return string|nil
|
||||
M.get_current_file = function()
|
||||
local view = diffview_lib.get_current_view()
|
||||
if not view then
|
||||
return
|
||||
end
|
||||
return view.panel.cur_file.path
|
||||
end
|
||||
|
||||
---Diffview exposes events which can be used to setup autocommands.
|
||||
---@param callback fun(opts: table) - for more information about opts see callback in :h nvim_create_autocmd
|
||||
M.set_callback_for_file_changed = function(callback)
|
||||
local group = vim.api.nvim_create_augroup("gitlab.diffview.autocommand.file_changed", {})
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = { "DiffviewDiffBufWinEnter" },
|
||||
group = group,
|
||||
callback = function(...)
|
||||
M.stored_win = vim.api.nvim_get_current_win()
|
||||
if M.tabnr == vim.api.nvim_get_current_tabpage() then
|
||||
callback(...)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
---Diffview exposes events which can be used to setup autocommands.
|
||||
---@param callback fun(opts: table) - for more information about opts see callback in :h nvim_create_autocmd
|
||||
M.set_callback_for_reviewer_leave = function(callback)
|
||||
local group = vim.api.nvim_create_augroup("gitlab.diffview.autocommand.leave", {})
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = { "DiffviewViewLeave", "DiffviewViewClosed" },
|
||||
group = group,
|
||||
callback = function(...)
|
||||
if M.tabnr == vim.api.nvim_get_current_tabpage() then
|
||||
callback(...)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
M.set_callback_for_reviewer_enter = function(callback)
|
||||
local group = vim.api.nvim_create_augroup("gitlab.diffview.autocommand.enter", {})
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = { "DiffviewViewOpened" },
|
||||
group = group,
|
||||
callback = function(...)
|
||||
callback(...)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user