Skip to content

Commit f57cc84

Browse files
authored
Fix: Store reviewer data before creating comment popup (#476)
1 parent 58960b9 commit f57cc84

File tree

9 files changed

+126
-125
lines changed

9 files changed

+126
-125
lines changed

lua/gitlab/actions/comment.lua

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ local reviewer = require("gitlab.reviewer")
1515
local Location = require("gitlab.reviewer.location")
1616

1717
local M = {
18-
current_win = nil,
1918
start_line = nil,
2019
end_line = nil,
2120
draft_popup = nil,
@@ -25,10 +24,9 @@ local M = {
2524
---Fires the API that sends the comment data to the Go server, called when you "confirm" creation
2625
---via the M.settings.keymaps.popup.perform_action keybinding
2726
---@param text string comment text
28-
---@param visual_range LineRange | nil range of visual selection or nil
2927
---@param unlinked boolean if true, the comment is not linked to a line
3028
---@param discussion_id string | nil The ID of the discussion to which the reply is responding, nil if not a reply
31-
local confirm_create_comment = function(text, visual_range, unlinked, discussion_id)
29+
local confirm_create_comment = function(text, unlinked, discussion_id)
3230
if text == nil then
3331
u.notify("Reviewer did not provide text of change", vim.log.levels.ERROR)
3432
return
@@ -75,30 +73,16 @@ local confirm_create_comment = function(text, visual_range, unlinked, discussion
7573
return
7674
end
7775

78-
local reviewer_data = reviewer.get_reviewer_data()
79-
if reviewer_data == nil then
80-
u.notify("Error getting reviewer data", vim.log.levels.ERROR)
81-
return
82-
end
83-
84-
local location = Location.new(reviewer_data, visual_range)
85-
location:build_location_data()
86-
local location_data = location.location_data
87-
if location_data == nil then
88-
u.notify("Error getting location information", vim.log.levels.ERROR)
89-
return
90-
end
91-
9276
local revision = state.MR_REVISIONS[1]
9377
local position_data = {
94-
file_name = reviewer_data.file_name,
95-
old_file_name = reviewer_data.old_file_name,
78+
file_name = M.location.reviewer_data.file_name,
79+
old_file_name = M.location.reviewer_data.old_file_name,
9680
base_commit_sha = revision.base_commit_sha,
9781
start_commit_sha = revision.start_commit_sha,
9882
head_commit_sha = revision.head_commit_sha,
99-
old_line = location_data.old_line,
100-
new_line = location_data.new_line,
101-
line_range = location_data.line_range,
83+
old_line = M.location.location_data.old_line,
84+
new_line = M.location.location_data.new_line,
85+
line_range = M.location.location_data.line_range,
10286
}
10387

10488
-- Creating a new comment (linked to specific changes)
@@ -148,10 +132,10 @@ M.confirm_edit_comment = function(discussion_id, note_id, unlinked)
148132
end
149133

150134
---@class LayoutOpts
151-
---@field ranged boolean
152135
---@field unlinked boolean
153136
---@field discussion_id string|nil
154137
---@field reply boolean|nil
138+
---@field file_name string|nil
155139

156140
---This function sets up the layout and popups needed to create a comment, note and
157141
---multi-line comment. It also sets up the basic keybindings for switching between
@@ -163,21 +147,24 @@ M.create_comment_layout = function(opts)
163147
local title
164148
local user_settings
165149
if opts.discussion_id ~= nil then
166-
title = "Reply"
150+
title = "Reply" .. (opts.file_name and string.format(" [%s]", opts.file_name) or "")
167151
user_settings = popup_settings.reply
168152
elseif opts.unlinked then
169153
title = "Note"
170154
user_settings = popup_settings.note
171155
else
172-
title = "Comment"
156+
-- TODO: investigate why `old_file_name` is in fact the new name for renamed files!
157+
local file_name = M.location.reviewer_data.old_file_name ~= "" and M.location.reviewer_data.old_file_name
158+
or M.location.reviewer_data.file_name
159+
title =
160+
popup.create_title("Comment", file_name, M.location.visual_range.start_line, M.location.visual_range.end_line)
173161
user_settings = popup_settings.comment
174162
end
175163
local settings = u.merge(popup_settings, user_settings or {})
176164

177-
M.current_win = vim.api.nvim_get_current_win()
165+
local current_win = vim.api.nvim_get_current_win()
178166
M.comment_popup = Popup(popup.create_popup_state(title, settings))
179167
M.draft_popup = Popup(popup.create_box_popup_state("Draft", false, settings))
180-
M.start_line, M.end_line = u.get_visual_selection_boundaries()
181168

182169
local internal_layout = Layout.Box({
183170
Layout.Box(M.comment_popup, { grow = 1 }),
@@ -194,22 +181,21 @@ M.create_comment_layout = function(opts)
194181
}, internal_layout)
195182

196183
popup.set_cycle_popups_keymaps({ M.comment_popup, M.draft_popup })
197-
popup.set_up_autocommands(M.comment_popup, layout, M.current_win)
184+
popup.set_up_autocommands(M.comment_popup, layout, current_win)
198185

199-
local range = opts.ranged and { start_line = M.start_line, end_line = M.end_line } or nil
200186
local unlinked = opts.unlinked or false
201187

202188
---Keybinding for focus on draft section
203189
popup.set_popup_keymaps(M.draft_popup, function()
204190
local text = u.get_buffer_text(M.comment_popup.bufnr)
205-
confirm_create_comment(text, range, unlinked, opts.discussion_id)
206-
vim.api.nvim_set_current_win(M.current_win)
191+
confirm_create_comment(text, unlinked, opts.discussion_id)
192+
vim.api.nvim_set_current_win(current_win)
207193
end, miscellaneous.toggle_bool, popup.non_editable_popup_opts)
208194

209195
---Keybinding for focus on text section
210196
popup.set_popup_keymaps(M.comment_popup, function(text)
211-
confirm_create_comment(text, range, unlinked, opts.discussion_id)
212-
vim.api.nvim_set_current_win(M.current_win)
197+
confirm_create_comment(text, unlinked, opts.discussion_id)
198+
vim.api.nvim_set_current_win(current_win)
213199
end, miscellaneous.attach_file, popup.editable_popup_opts)
214200

215201
vim.schedule(function()
@@ -223,44 +209,43 @@ end
223209
--- This function will open a comment popup in order to create a comment on the changed/updated
224210
--- line in the current MR
225211
M.create_comment = function()
212+
M.location = Location.new()
226213
if not M.can_create_comment(false) then
227214
return
228215
end
229216

230-
local layout = M.create_comment_layout({ ranged = false, unlinked = false })
217+
local layout = M.create_comment_layout({ unlinked = false })
231218
layout:mount()
232219
end
233220

234221
--- This function will open a multi-line comment popup in order to create a multi-line comment
235222
--- on the changed/updated line in the current MR
236223
M.create_multiline_comment = function()
224+
M.location = Location.new()
237225
if not M.can_create_comment(true) then
238226
u.press_escape()
239227
return
240228
end
241229

242-
local layout = M.create_comment_layout({ ranged = true, unlinked = false })
230+
local layout = M.create_comment_layout({ unlinked = false })
243231
layout:mount()
244232
end
245233

246234
--- This function will open a a popup to create a "note" (e.g. unlinked comment)
247235
--- on the changed/updated line in the current MR
248236
M.create_note = function()
249-
local layout = M.create_comment_layout({ ranged = false, unlinked = true })
237+
local layout = M.create_comment_layout({ unlinked = true })
250238
layout:mount()
251239
end
252240

253241
---Given the current visually selected area of text, builds text to fill in the
254242
---comment popup with a suggested change
255243
---@return LineRange|nil
256-
---@return integer
257244
local build_suggestion = function()
258245
local current_line = vim.api.nvim_win_get_cursor(0)[1]
259-
M.start_line, M.end_line = u.get_visual_selection_boundaries()
260-
261-
local range_length = M.end_line - M.start_line
246+
local range_length = M.location.visual_range.end_line - M.location.visual_range.start_line
262247
local backticks = "```"
263-
local selected_lines = u.get_lines(M.start_line, M.end_line)
248+
local selected_lines = u.get_lines(M.location.visual_range.start_line, M.location.visual_range.end_line)
264249

265250
for _, line in ipairs(selected_lines) do
266251
if string.match(line, "^```%S*$") then
@@ -270,36 +255,37 @@ local build_suggestion = function()
270255
end
271256

272257
local suggestion_start
273-
if M.start_line == current_line then
258+
if M.location.visual_range.start_line == current_line then
274259
suggestion_start = backticks .. "suggestion:-0+" .. range_length
275-
elseif M.end_line == current_line then
260+
elseif M.location.visual_range.end_line == current_line then
276261
suggestion_start = backticks .. "suggestion:-" .. range_length .. "+0"
277262
else
278263
--- This should never happen afaik
279264
u.notify("Unexpected suggestion position", vim.log.levels.ERROR)
280-
return nil, 0
265+
return nil
281266
end
282267
suggestion_start = suggestion_start
283268
local suggestion_lines = {}
284269
table.insert(suggestion_lines, suggestion_start)
285270
vim.list_extend(suggestion_lines, selected_lines)
286271
table.insert(suggestion_lines, backticks)
287272

288-
return suggestion_lines, range_length
273+
return suggestion_lines
289274
end
290275

291276
--- This function will open a a popup to create a suggestion comment
292277
--- on the changed/updated line in the current MR
293278
--- See: https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html
294279
M.create_comment_suggestion = function()
280+
M.location = Location.new()
295281
if not M.can_create_comment(true) then
296282
u.press_escape()
297283
return
298284
end
299285

300-
local suggestion_lines, range_length = build_suggestion()
286+
local suggestion_lines = build_suggestion()
301287

302-
local layout = M.create_comment_layout({ ranged = range_length > 0, unlinked = false })
288+
local layout = M.create_comment_layout({ unlinked = false })
303289
layout:mount()
304290

305291
vim.schedule(function()
@@ -368,6 +354,11 @@ M.can_create_comment = function(must_be_visual)
368354
return false
369355
end
370356

357+
if M.location == nil or M.location.location_data == nil then
358+
u.notify("Error getting location information", vim.log.levels.ERROR)
359+
return false
360+
end
361+
371362
return true
372363
end
373364

lua/gitlab/actions/discussions/init.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,10 @@ M.reply = function(tree)
237237
local comment = require("gitlab.actions.comment")
238238
local unlinked = tree.bufnr == M.unlinked_bufnr
239239
local layout = comment.create_comment_layout({
240-
ranged = false,
241240
discussion_id = discussion_id,
242241
unlinked = unlinked,
243242
reply = true,
243+
file_name = discussion_node.file_name,
244244
})
245245

246246
layout:mount()
@@ -274,14 +274,16 @@ end
274274

275275
-- This function (settings.keymaps.discussion_tree.edit_comment) will open the edit popup for the current comment in the discussion tree
276276
M.edit_comment = function(tree, unlinked)
277-
local edit_popup = Popup(popup.create_popup_state("Edit Comment", state.settings.popup.edit))
278277
local current_node = tree:get_node()
279278
local note_node = common.get_note_node(tree, current_node)
280279
local root_node = common.get_root_node(tree, current_node)
281280
if note_node == nil or root_node == nil then
282281
u.notify("Could not get root or note node", vim.log.levels.ERROR)
283282
return
284283
end
284+
local title = "Edit Comment"
285+
title = root_node.file_name ~= nil and string.format("%s [%s]", title, root_node.file_name) or title
286+
local edit_popup = Popup(popup.create_popup_state(title, state.settings.popup.edit))
285287

286288
popup.set_up_autocommands(edit_popup, nil, vim.api.nvim_get_current_win())
287289

lua/gitlab/annotations.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@
120120
---Relevant for renamed files only, the name of the file in the previous commit
121121
---@field old_file_name string
122122
---@field current_bufnr integer
123-
---@field new_sha_win_id integer
124-
---@field old_sha_win_id integer
125123
---@field opposite_bufnr integer
126124
---@field new_line_from_buf integer
127125
---@field old_line_from_buf integer
126+
---@field new_sha_focused boolean
127+
---@field current_win_id integer
128128

129129
---@class LocationData
130130
---@field old_line integer | nil

lua/gitlab/hunks.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,17 +230,17 @@ end
230230
---This is in order to build the payload for Gitlab correctly by setting the old line and new line.
231231
---@param old_line number|nil
232232
---@param new_line number|nil
233-
---@param is_current_sha_focused boolean
233+
---@param new_sha_focused boolean
234234
---@return string|nil
235-
function M.get_modification_type(old_line, new_line, is_current_sha_focused)
235+
function M.get_modification_type(old_line, new_line, new_sha_focused)
236236
local hunk_and_diff_data = parse_hunks_and_diff(state.INFO.diff_refs.base_sha)
237237
if hunk_and_diff_data.hunks == nil then
238238
return
239239
end
240240

241241
local hunks = hunk_and_diff_data.hunks
242242
local all_diff_output = hunk_and_diff_data.all_diff_output
243-
return is_current_sha_focused and get_modification_type_from_new_sha(new_line, hunks, all_diff_output)
243+
return new_sha_focused and get_modification_type_from_new_sha(new_line, hunks, all_diff_output)
244244
or get_modification_type_from_old_sha(old_line, new_line, hunks, all_diff_output)
245245
end
246246

lua/gitlab/indicators/common.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ local M = {}
1212

1313
---Return true if discussion has a placeable diagnostic, false otherwise.
1414
---@param note NoteWithValues
15-
---@param file string
1615
---@return boolean
1716
local filter_discussions_and_notes = function(note)
1817
---Do not include unlinked notes

lua/gitlab/popup.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,16 @@ M.set_cycle_popups_keymaps = function(popups)
236236
end
237237
end
238238

239+
---Create the title for the comment popup.
240+
---@param title string The main title, e.g., "Comment".
241+
---@param file_name string Name of file for which comment is created.
242+
---@param start_line integer Start of the line range.
243+
---@param end_line integer End of the line range.
244+
---@return string title The full title of the popup.
245+
M.create_title = function(title, file_name, start_line, end_line)
246+
local range = start_line < end_line and string.format("-%s", end_line) or ""
247+
local position = string.format("%s%s", start_line, range)
248+
return string.format("%s [%s:%s]", title, file_name, position)
249+
end
250+
239251
return M

lua/gitlab/reviewer/init.lua

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,13 @@ end
154154

155155
---Get the data from diffview, such as line information and file name. May be used by
156156
---other modules such as the comment module to create line codes or set diagnostics
157+
---@param current_win integer The ID of the currently focused window
157158
---@return DiffviewInfo | nil
158-
M.get_reviewer_data = function()
159+
M.get_reviewer_data = function(current_win)
159160
local view = diffview_lib.get_current_view()
161+
if view == nil then
162+
return
163+
end
160164
local layout = view.cur_layout
161165
local old_win = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
162166
local new_win = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
@@ -175,9 +179,9 @@ M.get_reviewer_data = function()
175179
local new_line = vim.api.nvim_win_get_cursor(new_win)[1]
176180
local old_line = vim.api.nvim_win_get_cursor(old_win)[1]
177181

178-
local is_current_sha_focused = M.is_current_sha_focused()
182+
local new_sha_focused = M.is_new_sha_focused(current_win)
179183

180-
local modification_type = hunks.get_modification_type(old_line, new_line, is_current_sha_focused)
184+
local modification_type = hunks.get_modification_type(old_line, new_line, new_sha_focused)
181185
if modification_type == nil then
182186
u.notify("Error getting modification type", vim.log.levels.ERROR)
183187
return
@@ -187,32 +191,32 @@ M.get_reviewer_data = function()
187191
u.notify("Comments on unmodified lines will be placed in the old file", vim.log.levels.WARN)
188192
end
189193

190-
local current_bufnr = is_current_sha_focused and layout.b.file.bufnr or layout.a.file.bufnr
191-
local opposite_bufnr = is_current_sha_focused and layout.a.file.bufnr or layout.b.file.bufnr
192-
local old_sha_win_id = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
193-
local new_sha_win_id = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
194+
local current_bufnr = new_sha_focused and layout.b.file.bufnr or layout.a.file.bufnr
195+
local opposite_bufnr = new_sha_focused and layout.a.file.bufnr or layout.b.file.bufnr
194196

195197
return {
196-
old_file_name = layout.a.file.path,
197-
file_name = layout.b.file.path,
198+
-- TODO: swap 'a' and 'b' to fix lua/gitlab/actions/comment.lua:158, and hopefully also
199+
-- lua/gitlab/indicators/diagnostics.lua:129.
200+
file_name = layout.a.file.path,
201+
old_file_name = M.is_file_renamed() and layout.b.file.path or "",
198202
old_line_from_buf = old_line,
199203
new_line_from_buf = new_line,
200204
modification_type = modification_type,
201-
new_sha_win_id = new_sha_win_id,
202205
current_bufnr = current_bufnr,
203-
old_sha_win_id = old_sha_win_id,
204206
opposite_bufnr = opposite_bufnr,
207+
new_sha_focused = new_sha_focused,
208+
current_win_id = current_win,
205209
}
206210
end
207211

208212
---Return whether user is focused on the new version of the file
213+
---@param current_win integer The ID of the currently focused window
209214
---@return boolean
210-
M.is_current_sha_focused = function()
215+
M.is_new_sha_focused = function(current_win)
211216
local view = diffview_lib.get_current_view()
212217
local layout = view.cur_layout
213218
local b_win = u.get_window_id_by_buffer_id(layout.b.file.bufnr)
214219
local a_win = u.get_window_id_by_buffer_id(layout.a.file.bufnr)
215-
local current_win = require("gitlab.actions.comment").current_win
216220
if a_win ~= current_win and b_win ~= current_win then
217221
current_win = M.stored_win
218222
M.stored_win = nil

0 commit comments

Comments
 (0)