* fix: Restore buffer local settings outside reviewer (#446) * fix: do not show healthcheck alert for warnings (#468) * feat: Add MR URL to the summary details (#467) * fix: make cycling reviewed files faster (#474) * feat(pipeline): display trigger jobs for a pipeline in the pipelines popup (#465) * fix: Jumping to renamed files (#484) --------- Co-authored-by: Jakub F. Bortlík <jakub.bortlik@proton.me> Co-authored-by: Ashish Alex <ashish.alex10@gmail.com>
228 lines
7.4 KiB
Lua
Executable File
228 lines
7.4 KiB
Lua
Executable File
local u = require("gitlab.utils")
|
|
local hunks = require("gitlab.hunks")
|
|
local state = require("gitlab.state")
|
|
|
|
---@class Location
|
|
---@field location_data LocationData
|
|
---@field reviewer_data DiffviewInfo
|
|
---@field run function
|
|
---@field build_location_data function
|
|
---@field visual_range table
|
|
|
|
---@class ReviewerLineInfo
|
|
---@field old_line integer|nil
|
|
---@field new_line integer|nil
|
|
---@field type "new"|"old"
|
|
|
|
---@class ReviewerRangeInfo
|
|
---@field start ReviewerLineInfo
|
|
---@field end ReviewerLineInfo
|
|
|
|
local Location = {}
|
|
Location.__index = Location
|
|
---The new() function returns nil when the location cannot be created due to missing
|
|
---reviewer data.
|
|
---@return Location | nil
|
|
function Location.new()
|
|
local current_win = vim.api.nvim_get_current_win()
|
|
local reviewer_data = require("gitlab.reviewer").get_reviewer_data(current_win)
|
|
if reviewer_data == nil then
|
|
return nil
|
|
end
|
|
local location = {}
|
|
local instance = setmetatable(location, Location)
|
|
instance.reviewer_data = reviewer_data
|
|
instance.base_sha = state.INFO.diff_refs.base_sha
|
|
instance.head_sha = state.INFO.diff_refs.head_sha
|
|
instance:build_location_data()
|
|
return instance
|
|
end
|
|
|
|
---Takes in information about the current changes, such as the file name, modification type of the diff, and the line numbers
|
|
---and builds the appropriate payload when creating a comment.
|
|
function Location:build_location_data()
|
|
---@type DiffviewInfo
|
|
local reviewer_data = self.reviewer_data
|
|
|
|
local start_line, end_line = u.get_visual_selection_boundaries()
|
|
---@type LineRange
|
|
self.visual_range = { start_line = start_line, end_line = end_line }
|
|
|
|
---@type LocationData
|
|
self.location_data = {
|
|
old_line = nil,
|
|
new_line = nil,
|
|
line_range = nil,
|
|
}
|
|
|
|
-- Comment on new line: Include only new_line in payload.
|
|
-- Comment on deleted line: Include only old_line in payload.
|
|
-- The line was not found in any hunks, send both lines.
|
|
if reviewer_data.modification_type == "added" then
|
|
self.location_data.old_line = nil
|
|
self.location_data.new_line = reviewer_data.new_line_from_buf
|
|
elseif reviewer_data.modification_type == "deleted" then
|
|
self.location_data.old_line = reviewer_data.old_line_from_buf
|
|
self.location_data.new_line = nil
|
|
elseif
|
|
reviewer_data.modification_type == "unmodified" or reviewer_data.modification_type == "bad_file_unmodified"
|
|
then
|
|
self.location_data.old_line = reviewer_data.old_line_from_buf
|
|
self.location_data.new_line = reviewer_data.new_line_from_buf
|
|
end
|
|
|
|
if end_line > start_line then
|
|
self.location_data.line_range = {
|
|
start = {},
|
|
["end"] = {},
|
|
}
|
|
else
|
|
return
|
|
end
|
|
|
|
self:set_start_range()
|
|
self:set_end_range()
|
|
|
|
-- Ranged comments should always use the end of the range.
|
|
-- Otherwise they will not highlight the full comment in Gitlab.
|
|
self.location_data.old_line = self.location_data.line_range["end"].old_line
|
|
self.location_data.new_line = self.location_data.line_range["end"].new_line
|
|
end
|
|
|
|
-- Helper methods 🤝
|
|
|
|
-- Returns the matching line from the new SHA.
|
|
-- For instance, line 12 in the new SHA may be scroll-linked
|
|
-- to line 10 in the old SHA.
|
|
---@param line number
|
|
---@return number|nil
|
|
function Location:get_line_number_from_new_sha(line)
|
|
if self.reviewer_data.new_sha_focused then
|
|
return line
|
|
end
|
|
-- Otherwise we want to get the matching line in the opposite buffer
|
|
return hunks.calculate_matching_line_new(
|
|
self.base_sha,
|
|
self.head_sha,
|
|
self.reviewer_data.file_name,
|
|
self.reviewer_data.old_file_name,
|
|
line
|
|
)
|
|
end
|
|
|
|
-- Returns the matching line from the old SHA.
|
|
-- For instance, line 12 in the new SHA may be scroll-linked
|
|
-- to line 10 in the old SHA.
|
|
---@param line number
|
|
---@return number|nil
|
|
function Location:get_line_number_from_old_sha(line)
|
|
if not self.reviewer_data.new_sha_focused then
|
|
return line
|
|
end
|
|
|
|
-- Otherwise we want to get the matching line in the opposite buffer
|
|
return hunks.calculate_matching_line_new(
|
|
self.head_sha,
|
|
self.base_sha,
|
|
self.reviewer_data.file_name,
|
|
self.reviewer_data.old_file_name,
|
|
line
|
|
)
|
|
end
|
|
|
|
-- Returns the current line number from whatever SHA (new or old)
|
|
-- the reviewer is focused in.
|
|
---@return number|nil
|
|
function Location:get_current_line()
|
|
if self.reviewer_data.current_win_id == nil then
|
|
return
|
|
end
|
|
|
|
local current_line = vim.api.nvim_win_get_cursor(self.reviewer_data.current_win_id)[1]
|
|
return current_line
|
|
end
|
|
|
|
-- Given a modification type, a visual selection range, and the hunk data, sets the start range
|
|
-- information to the location_data for the Gitlab payload
|
|
function Location:set_start_range()
|
|
local current_file = require("gitlab.reviewer").get_current_file_path()
|
|
if current_file == nil then
|
|
u.notify("Error getting current file from Diffview", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
if self.reviewer_data.current_win_id == nil then
|
|
u.notify("Error getting window number of SHA for start range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local current_line = self:get_current_line()
|
|
if current_line == nil then
|
|
u.notify("Error getting current line for start range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local new_line = self:get_line_number_from_new_sha(self.visual_range.start_line)
|
|
local old_line = self:get_line_number_from_old_sha(self.visual_range.start_line)
|
|
if
|
|
(new_line == nil and self.reviewer_data.modification_type ~= "deleted")
|
|
or (old_line == nil and self.reviewer_data.modification_type ~= "added")
|
|
then
|
|
u.notify("Error getting new or old line for start range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local modification_type = hunks.get_modification_type(old_line, new_line, self.reviewer_data.new_sha_focused)
|
|
if modification_type == nil then
|
|
u.notify("Error getting modification type for start of range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
self.location_data.line_range.start = {
|
|
new_line = modification_type ~= "deleted" and new_line or nil,
|
|
old_line = modification_type ~= "added" and old_line or nil,
|
|
type = modification_type == "added" and "new" or "old",
|
|
}
|
|
end
|
|
|
|
-- Given a modification type, a visual selection range, and the hunk data, sets the end range
|
|
-- information to the location_data for the Gitlab payload
|
|
function Location:set_end_range()
|
|
local current_file = require("gitlab.reviewer").get_current_file_path()
|
|
if current_file == nil then
|
|
u.notify("Error getting current file from Diffview", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local current_line = self:get_current_line()
|
|
if current_line == nil then
|
|
u.notify("Error getting current line for end range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local new_line = self:get_line_number_from_new_sha(self.visual_range.end_line)
|
|
local old_line = self:get_line_number_from_old_sha(self.visual_range.end_line)
|
|
|
|
if
|
|
(new_line == nil and self.reviewer_data.modification_type ~= "deleted")
|
|
or (old_line == nil and self.reviewer_data.modification_type ~= "added")
|
|
then
|
|
u.notify("Error getting new or old line for end range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local modification_type = hunks.get_modification_type(old_line, new_line, self.reviewer_data.new_sha_focused)
|
|
if modification_type == nil then
|
|
u.notify("Error getting modification type for end of range", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
self.location_data.line_range["end"] = {
|
|
new_line = modification_type ~= "deleted" and new_line or nil,
|
|
old_line = modification_type ~= "added" and old_line or nil,
|
|
type = modification_type == "added" and "new" or "old",
|
|
}
|
|
end
|
|
|
|
return Location
|