Skip to content

Commit be0c77e

Browse files
committed
Fix buggy diff comments that were disappearing
1 parent cf13ce7 commit be0c77e

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
- Store `ReviewDiff` selector options (`target`, `--cached-only`, `--uncached-only`, `--merge-base`, `--tracked-only`) on the active local review so `ReviewSync` can re-run the same diff mode instead of silently falling back to default `diff`.
4444
- Do not carry `expanded_changes` extmark IDs across `ReviewSync`; extmarks are buffer-local and cleared by `state.clear_review()`, so stale IDs prevent old-code expansion from reapplying.
45+
- Local diff comments are state-only, so both reopened buffers and local `ReviewSync` need to repopulate overlays from `review.comments`; PR-only redraw paths make comments appear to vanish while navigation state is still intact.
4546

4647
## Learned while fixing PR comment pagination and LEFT-side rendering
4748

lua/neo_reviewer/init.lua

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -900,10 +900,8 @@ function M.apply_overlay_to_buffer(bufnr)
900900
local signs = require("neo_reviewer.ui.signs")
901901
signs.place(bufnr, file.change_blocks)
902902

903-
if not state.is_local_review() then
904-
local comments_ui = require("neo_reviewer.ui.comments")
905-
comments_ui.show_existing(bufnr, file.path)
906-
end
903+
local comments_ui = require("neo_reviewer.ui.comments")
904+
comments_ui.show_existing(bufnr, file.path)
907905

908906
local buffer = require("neo_reviewer.ui.buffer")
909907
buffer.place_change_block_marks(bufnr, file)
@@ -1407,6 +1405,7 @@ function M.sync(opts)
14071405
diff_opts = review.local_diff_opts or {},
14081406
show_old_code = review.show_old_code,
14091407
ai_analysis = review.ai_analysis,
1408+
comments = review.comments or {},
14101409
}
14111410
local ai_ui = require("neo_reviewer.ui.ai")
14121411
local keep_ai_ui_open = ai_ui.is_open() and preserved.ai_analysis ~= nil
@@ -1456,6 +1455,22 @@ function M.sync(opts)
14561455
new_review.show_old_code = preserved.show_old_code
14571456
new_review.ai_analysis = preserved.ai_analysis
14581457

1458+
---@type table<string, boolean>
1459+
local retained_paths = {}
1460+
for _, file in ipairs(filtered_files) do
1461+
retained_paths[file.path] = true
1462+
end
1463+
1464+
---@type NRComment[]
1465+
local retained_comments = {}
1466+
-- Keep local notes only for files that still exist in the refreshed diff.
1467+
for _, comment in ipairs(preserved.comments) do
1468+
if retained_paths[comment.path] then
1469+
table.insert(retained_comments, comment)
1470+
end
1471+
end
1472+
new_review.comments = retained_comments
1473+
14591474
M.enable_overlay()
14601475
if keep_ai_ui_open then
14611476
ai_ui.open({ preserve_layout = true })

lua/tests/plenary/init_review_diff_spec.lua

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ describe("neo_reviewer review noise filtering", function()
5353
package.loaded["neo_reviewer.ai"] = nil
5454
package.loaded["neo_reviewer.ui.ai"] = nil
5555
package.loaded["neo_reviewer.ui.nav"] = nil
56+
package.loaded["neo_reviewer.ui.comments"] = nil
5657
state = require("neo_reviewer.state")
5758
cli = require("neo_reviewer.cli")
5859
config = require("neo_reviewer.config")
@@ -192,6 +193,57 @@ describe("neo_reviewer review noise filtering", function()
192193
assert.is_nil(find_loading_buffer())
193194
end)
194195

196+
it("re-renders local comments when a reviewed file buffer is reopened", function()
197+
local repo_root = vim.fn.tempname()
198+
vim.fn.mkdir(repo_root .. "/src", "p")
199+
vim.fn.writefile({ "line 1", "line 2", "line 3" }, repo_root .. "/src/main.lua")
200+
vim.fn.writefile({ "line 1", "line 2" }, repo_root .. "/src/other.lua")
201+
202+
state.set_local_review({
203+
git_root = repo_root,
204+
files = {
205+
{
206+
path = "src/main.lua",
207+
status = "modified",
208+
change_blocks = {},
209+
},
210+
{
211+
path = "src/other.lua",
212+
status = "modified",
213+
change_blocks = {},
214+
},
215+
},
216+
})
217+
218+
state.add_comment({
219+
id = 7,
220+
path = "src/main.lua",
221+
line = 2,
222+
side = "RIGHT",
223+
body = "keep this comment",
224+
author = "you",
225+
created_at = "2025-01-01T00:00:00Z",
226+
})
227+
228+
vim.cmd("edit " .. vim.fn.fnameescape(repo_root .. "/src/main.lua"))
229+
local first_main = vim.api.nvim_get_current_buf()
230+
neo_reviewer.apply_overlay_to_buffer(first_main)
231+
assert.is_true(#helpers.get_extmarks(first_main, "nr_comments") > 0)
232+
233+
vim.cmd("edit " .. vim.fn.fnameescape(repo_root .. "/src/other.lua"))
234+
local other = vim.api.nvim_get_current_buf()
235+
neo_reviewer.apply_overlay_to_buffer(other)
236+
237+
vim.api.nvim_buf_delete(first_main, { force = true })
238+
239+
vim.cmd("edit " .. vim.fn.fnameescape(repo_root .. "/src/main.lua"))
240+
local reopened_main = vim.api.nvim_get_current_buf()
241+
neo_reviewer.apply_overlay_to_buffer(reopened_main)
242+
243+
local extmarks = helpers.get_extmarks(reopened_main, "nr_comments")
244+
assert.is_true(#extmarks > 0)
245+
end)
246+
195247
it("skips default noise files in PR reviews", function()
196248
cli.fetch_pr = function(_, callback)
197249
callback(

lua/tests/plenary/sync_spec.lua

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,49 @@ describe("neo_reviewer.sync", function()
201201
assert.are.same(analysis, state.get_ai_analysis())
202202
end)
203203

204+
it("preserves local comments for files that remain in the synced diff", function()
205+
state.set_local_review(mock_data.local_diff, {
206+
target = "main",
207+
})
208+
state.add_comment({
209+
id = 77,
210+
path = "src/main.lua",
211+
line = 2,
212+
side = "RIGHT",
213+
body = "keep me",
214+
author = "you",
215+
created_at = "2025-01-01T00:00:00Z",
216+
})
217+
state.add_comment({
218+
id = 78,
219+
path = "src/removed.lua",
220+
line = 1,
221+
side = "RIGHT",
222+
body = "drop me",
223+
author = "you",
224+
created_at = "2025-01-01T00:00:00Z",
225+
})
226+
227+
cli.get_local_diff.invokes(function(_, callback)
228+
callback({
229+
git_root = "/tmp/test",
230+
files = {
231+
{ path = "src/main.lua", status = "modified", change_blocks = {} },
232+
},
233+
}, nil)
234+
end)
235+
236+
neo_reviewer.sync()
237+
238+
local review = state.get_review()
239+
assert.is_not_nil(review)
240+
if review then
241+
assert.are.equal(1, #review.comments)
242+
assert.are.equal(77, review.comments[1].id)
243+
assert.are.equal("keep me", review.comments[1].body)
244+
end
245+
end)
246+
204247
it("notifies user when local diff sync is in progress", function()
205248
state.set_local_review(mock_data.local_diff)
206249

0 commit comments

Comments
 (0)