Skip to content

Commit 986cfbc

Browse files
authored
fix: make cycling reviewed files faster (#474)
1 parent a4de26e commit 986cfbc

File tree

6 files changed

+80
-56
lines changed

6 files changed

+80
-56
lines changed

doc/gitlab.nvim.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ you call this function with no values the defaults will be used:
316316
comment = "→|",
317317
range = " |",
318318
},
319+
skip_old_revision_discussion = false, -- Don't show diagnostics for discussions that were created for earlier MR revisions
319320
},
320321
pipeline = {
321322
created = "",

lua/gitlab/actions/common.lua

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ M.get_line_number_from_node = function(root_node)
265265
end
266266

267267
-- This function (settings.keymaps.discussion_tree.jump_to_reviewer) will jump the cursor to the reviewer's location associated with the note. The implementation depends on the reviewer
268-
M.jump_to_reviewer = function(tree, callback)
268+
M.jump_to_reviewer = function(tree)
269269
local node = tree:get_node()
270270
local root_node = M.get_root_node(tree, node)
271271
if root_node == nil then
@@ -278,7 +278,6 @@ M.jump_to_reviewer = function(tree, callback)
278278
return
279279
end
280280
reviewer.jump(root_node.file_name, line_number, is_new_sha)
281-
callback()
282281
end
283282

284283
-- This function (settings.keymaps.discussion_tree.jump_to_file) will jump to the file changed in a new tab

lua/gitlab/actions/discussions/init.lua

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ M.initialize_discussions = function()
7474
state.discussion_tree.last_updated = os.time()
7575
signs.setup_signs()
7676
reviewer.set_callback_for_file_changed(function(args)
77+
diagnostics.place_diagnostics(args.buf)
7778
reviewer.update_winid_for_buffer(args.buf)
7879
end)
7980
reviewer.set_callback_for_reviewer_enter(function()
@@ -90,7 +91,7 @@ M.initialize_discussions = function()
9091
end)
9192
end
9293

93-
--- Take existing data and refresh the diagnostics, the winbar, and the signs
94+
--- Take existing data and refresh the diagnostics and the signs
9495
M.refresh_diagnostics = function()
9596
if state.settings.discussion_signs.enabled then
9697
diagnostics.refresh_diagnostics()
@@ -573,7 +574,7 @@ M.set_tree_keymaps = function(tree, bufnr, unlinked)
573574
if keymaps.discussion_tree.jump_to_reviewer then
574575
vim.keymap.set("n", keymaps.discussion_tree.jump_to_reviewer, function()
575576
if M.is_current_node_note(tree) then
576-
common.jump_to_reviewer(tree, M.refresh_diagnostics)
577+
common.jump_to_reviewer(tree)
577578
end
578579
end, { buffer = bufnr, desc = "Jump to reviewer", nowait = keymaps.discussion_tree.jump_to_reviewer_nowait })
579580
end
@@ -743,6 +744,16 @@ M.set_tree_keymaps = function(tree, bufnr, unlinked)
743744
})
744745
end
745746

747+
if keymaps.discussion_tree.print_node then
748+
vim.keymap.set("n", keymaps.discussion_tree.print_node, function()
749+
common.print_node(tree)
750+
end, {
751+
buffer = bufnr,
752+
desc = "Print current node (for debugging)",
753+
nowait = keymaps.discussion_tree.print_node_nowait,
754+
})
755+
end
756+
746757
if keymaps.discussion_tree.add_emoji then
747758
vim.keymap.set("n", keymaps.discussion_tree.add_emoji, function()
748759
M.add_emoji_to_note(tree, unlinked)

lua/gitlab/annotations.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,15 @@
346346
---@field perform_action? string -- Once in normal mode, does action (like saving comment or applying description edit, etc)
347347
---@field perform_linewise_action? string -- Once in normal mode, does the linewise action (see logs for this job, etc)
348348
---@field discard_changes? string -- Quit the popup discarding changes, the popup content is not? saved to the `temp_registers` (see `:h gitlab.nvim.temp-registers`)
349+
350+
---@class List The base class for all list objects
351+
---@field new function -- Creates a new List from a table
352+
---@field map function -- Mutates a given list
353+
---@field filter function -- Filters a given list
354+
---@field partition function -- Partitions a given list into two lists
355+
---@field reduce function -- Applies a function to reduce the list to a single value
356+
---@field sort function -- Sorts the list in place based on a comparator function
357+
---@field find function -- Returns the first element that satisfies the callback
358+
---@field slice function -- Returns a portion of the list between start and end indices
359+
---@field includes function -- Returns true if any of the elements can satisfy the callback
360+
---@field values function -- Returns an iterator over the list's values

lua/gitlab/indicators/common.lua

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
local u = require("gitlab.utils")
22
local state = require("gitlab.state")
3-
local reviewer = require("gitlab.reviewer")
43
local List = require("gitlab.utils.list")
54

65
local M = {}
@@ -11,24 +10,25 @@ local M = {}
1110
---@field resolved boolean|nil
1211
---@field created_at string|nil
1312

13+
---Return true if discussion has a placeable diagnostic, false otherwise.
1414
---@param note NoteWithValues
1515
---@param file string
1616
---@return boolean
17-
local filter_discussions_and_notes = function(note, file)
17+
local filter_discussions_and_notes = function(note)
1818
---Do not include unlinked notes
1919
return note.position ~= nil
20-
and (note.position.new_path == file or note.position.old_path == file)
2120
---Skip resolved discussions if user wants to
2221
and not (state.settings.discussion_signs.skip_resolved_discussion and note.resolvable and note.resolved)
2322
---Skip discussions from old revisions
2423
and not (
2524
state.settings.discussion_signs.skip_old_revision_discussion
25+
and note.created_at ~= nil
2626
and u.from_iso_format_date_to_timestamp(note.created_at)
2727
<= u.from_iso_format_date_to_timestamp(state.MR_REVISIONS[1].created_at)
2828
)
2929
end
3030

31-
---Filter all discussions which are relevant for currently visible signs and diagnostics.
31+
---Filter all discussions and drafts which have placeable signs and diagnostics.
3232
---@return Discussion|DraftNote[]
3333
M.filter_placeable_discussions = function()
3434
local discussions = u.ensure_table(state.DISCUSSION_DATA and state.DISCUSSION_DATA.discussions or {})
@@ -41,18 +41,13 @@ M.filter_placeable_discussions = function()
4141
draft_notes = {}
4242
end
4343

44-
local file = reviewer.get_current_file_path()
45-
if not file then
46-
return {}
47-
end
48-
4944
local filtered_discussions = List.new(discussions):filter(function(discussion)
5045
local first_note = discussion.notes[1]
51-
return type(first_note.position) == "table" and filter_discussions_and_notes(first_note, file)
46+
return type(first_note.position) == "table" and filter_discussions_and_notes(first_note)
5247
end)
5348

5449
local filtered_draft_notes = List.new(draft_notes):filter(function(note)
55-
return filter_discussions_and_notes(note, file)
50+
return filter_discussions_and_notes(note)
5651
end)
5752

5853
return u.join(filtered_discussions, filtered_draft_notes)

lua/gitlab/indicators/diagnostics.lua

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -85,47 +85,64 @@ local create_multiline_diagnostic = function(d_or_n)
8585
}, d_or_n)
8686
end
8787

88-
---Set diagnostics in currently new SHA.
88+
---Set diagnostics in the given buffer.
8989
---@param namespace number namespace for diagnostics
90+
---@param bufnr number the bufnr for placing the diagnostics
9091
---@param diagnostics table see :h vim.diagnostic.set
9192
---@param opts table? see :h vim.diagnostic.set
92-
local set_diagnostics_in_new_sha = function(namespace, diagnostics, opts)
93+
local set_diagnostics = function(namespace, bufnr, diagnostics, opts)
94+
vim.diagnostic.set(namespace, bufnr, diagnostics, opts)
95+
require("gitlab.indicators.signs").set_signs(diagnostics, bufnr)
96+
end
97+
98+
---Refresh the diagnostics for all the reviewed files, and place diagnostics for the currently
99+
---visible buffers.
100+
M.refresh_diagnostics = function()
101+
require("gitlab.indicators.signs").clear_signs()
102+
M.clear_diagnostics()
103+
M.placeable_discussions = indicators_common.filter_placeable_discussions()
104+
93105
local view = diffview_lib.get_current_view()
94-
if not view then
106+
if view == nil then
107+
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
95108
return
96109
end
97-
vim.diagnostic.set(namespace, view.cur_layout.b.file.bufnr, diagnostics, opts)
98-
require("gitlab.indicators.signs").set_signs(diagnostics, view.cur_layout.b.file.bufnr)
110+
M.place_diagnostics(view.cur_layout.a.file.bufnr)
111+
M.place_diagnostics(view.cur_layout.b.file.bufnr)
99112
end
100113

101-
---Set diagnostics in old SHA.
102-
---@param namespace number namespace for diagnostics
103-
---@param diagnostics table see :h vim.diagnostic.set
104-
---@param opts table? see :h vim.diagnostic.set
105-
local set_diagnostics_in_old_sha = function(namespace, diagnostics, opts)
114+
---Filter and place the diagnostics for the given buffer.
115+
---@param bufnr number The number of the buffer for placing diagnostics.
116+
M.place_diagnostics = function(bufnr)
117+
if not state.settings.discussion_signs.enabled then
118+
return
119+
end
106120
local view = diffview_lib.get_current_view()
107-
if not view then
121+
if view == nil then
122+
u.notify("Could not find Diffview view", vim.log.levels.ERROR)
108123
return
109124
end
110-
vim.diagnostic.set(namespace, view.cur_layout.a.file.bufnr, diagnostics, opts)
111-
require("gitlab.indicators.signs").set_signs(diagnostics, view.cur_layout.a.file.bufnr)
112-
end
113125

114-
---Refresh the diagnostics for the currently reviewed file
115-
M.refresh_diagnostics = function()
116126
local ok, err = pcall(function()
117-
require("gitlab.indicators.signs").clear_signs()
118-
M.clear_diagnostics()
119-
local filtered_discussions = indicators_common.filter_placeable_discussions()
120-
if filtered_discussions == nil then
127+
local file_discussions = List.new(M.placeable_discussions):filter(function(discussion_or_note)
128+
local note = discussion_or_note.notes and discussion_or_note.notes[1] or discussion_or_note
129+
-- Surprisingly, the following line works even if I'd expect it should match new/old paths
130+
-- with a/b buffers the other way round!
131+
return note.position.new_path == view.cur_layout.a.file.path
132+
or note.position.old_path == view.cur_layout.b.file.path
133+
end)
134+
135+
if #file_discussions == 0 then
121136
return
122137
end
123138

124-
local new_diagnostics = M.parse_new_diagnostics(filtered_discussions)
125-
set_diagnostics_in_new_sha(diagnostics_namespace, new_diagnostics, create_display_opts())
139+
local new_diagnostics, old_diagnostics = List.new(file_discussions):partition(indicators_common.is_new_sha)
126140

127-
local old_diagnostics = M.parse_old_diagnostics(filtered_discussions)
128-
set_diagnostics_in_old_sha(diagnostics_namespace, old_diagnostics, create_display_opts())
141+
if bufnr == view.cur_layout.a.file.bufnr then
142+
set_diagnostics(diagnostics_namespace, bufnr, M.parse_diagnostics(old_diagnostics), create_display_opts())
143+
elseif bufnr == view.cur_layout.b.file.bufnr then
144+
set_diagnostics(diagnostics_namespace, bufnr, M.parse_diagnostics(new_diagnostics), create_display_opts())
145+
end
129146
end)
130147

131148
if not ok then
@@ -134,24 +151,13 @@ M.refresh_diagnostics = function()
134151
end
135152

136153
---Iterates over each discussion and returns a list of tables with sign
137-
---data, for instance group, priority, line number etc for the new SHA
138-
---@param discussions Discussion[]
139-
---@return DiagnosticTable[]
140-
M.parse_new_diagnostics = function(discussions)
141-
local new_diagnostics = List.new(discussions):filter(indicators_common.is_new_sha)
142-
local single_line = new_diagnostics:filter(indicators_common.is_single_line):map(create_single_line_diagnostic)
143-
local multi_line = new_diagnostics:filter(indicators_common.is_multi_line):map(create_multiline_diagnostic)
144-
return u.combine(single_line, multi_line)
145-
end
146-
147-
---Iterates over each discussion and returns a list of tables with sign
148-
---data, for instance group, priority, line number etc for the old SHA
149-
---@param discussions Discussion[]
154+
---data, for instance group, priority, line number etc
155+
---@param discussions List
150156
---@return DiagnosticTable[]
151-
M.parse_old_diagnostics = function(discussions)
152-
local old_diagnostics = List.new(discussions):filter(indicators_common.is_old_sha)
153-
local single_line = old_diagnostics:filter(indicators_common.is_single_line):map(create_single_line_diagnostic)
154-
local multi_line = old_diagnostics:filter(indicators_common.is_multi_line):map(create_multiline_diagnostic)
157+
M.parse_diagnostics = function(discussions)
158+
local single_line, multi_line = discussions:partition(indicators_common.is_single_line)
159+
single_line = single_line:map(create_single_line_diagnostic)
160+
multi_line = multi_line:map(create_multiline_diagnostic)
155161
return u.combine(single_line, multi_line)
156162
end
157163

0 commit comments

Comments
 (0)