11local h = require (" tests.helpers" )
22
3- local expect = MiniTest .expect
43local new_set = MiniTest .new_set
54
65local child = MiniTest .new_child_neovim ()
@@ -11,41 +10,6 @@ T = new_set({
1110 child .lua ([[
1211 diff = require("codecompanion.diff")
1312 ]] )
14-
15- local before = [[
16- async fn run_cargo_build_json() -> io::Result<Option<String>> {
17- let mut child = Command::new("cargo")
18- .args(["build", "--message-format=json"])
19- .stdout(Stdio::piped())
20- }
21- ]]
22- local after = [[
23- async fn rn_crgo_build_jsons() -> io::Result<Option<String>> {
24- let mut childddd = Command::new("cargo")
25- .ars(["build", "--message-format=json"])
26- .stddddouttt(Stdio::piped())
27- }
28- ]]
29-
30- child .lua (string.format (
31- [[
32- before_tbl = vim.split(%q, "\n", { plain = true })
33- after_tbl = vim.split(%q, "\n", { plain = true })
34-
35- -- Create a scratch buffer with the new, after, content
36- local bufnr = vim.api.nvim_create_buf(false, true)
37- vim.api.nvim_buf_set_option(bufnr, "filetype", "rust")
38- vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, after_tbl)
39-
40- before = %q
41- after = %q
42- diff_buffer = bufnr
43- ]] ,
44- before ,
45- after ,
46- before ,
47- after
48- ))
4913 end ,
5014 post_once = child .stop ,
5115 },
6731T [" Diff" ][" Creates diff with hunks and extmarks" ] = function ()
6832 local result = child .lua ([[
6933 local bufnr = vim.api.nvim_create_buf(false, true)
70- vim.api.nvim_buf_set_option(bufnr, "filetype", "rust ")
34+ vim.api.nvim_buf_set_option(bufnr, "filetype", "lua ")
7135
7236 local diff_obj = diff.create({
7337 bufnr = bufnr,
74- from_lines = before_tbl ,
75- to_lines = after_tbl ,
76- ft = "rust "
38+ from_lines = { "function foo()", " print('old')", "end" } ,
39+ to_lines = { "function foo()", " print('new')", "end" } ,
40+ ft = "lua "
7741 })
7842
7943 return {
@@ -97,7 +61,6 @@ T["Diff"]["Detects correct hunk indices"] = function()
9761 ]] )
9862
9963 h .eq (1 , # result , " Should have 1 hunk" )
100- -- Format: {a_start, a_count, b_start, b_count}
10164 h .eq ({ 2 , 2 , 2 , 2 }, result [1 ], " Should detect lines 2-3 changed" )
10265end
10366
@@ -153,7 +116,7 @@ T["Diff"]["Generates correct extmarks for changes"] = function()
153116 h .eq (1 , result .hunk_count , " Should have 1 hunk" )
154117 h .eq (" change" , result .hunk .kind , " Should be change type" )
155118 h .eq ({ 1 , 0 }, result .hunk .pos , " Should be at row 1, col 0" )
156- h .eq (2 , result .extmark_count , " Should have 2 extmarks (deletion + addition)" )
119+ h .eq (3 , result .extmark_count , " Should have 2 extmarks (deletion + addition + change )" )
157120end
158121
159122T [" Diff" ][" Applies extmarks to buffer" ] = function ()
@@ -164,7 +127,6 @@ T["Diff"]["Applies extmarks to buffer"] = function()
164127 local from = {"line1", "old", "line3"}
165128 local to = {"line1", "new", "line3"}
166129
167- -- Set buffer to "after" content
168130 vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, to)
169131
170132 local diff_obj = diff.create({
@@ -174,10 +136,8 @@ T["Diff"]["Applies extmarks to buffer"] = function()
174136 ft = "lua"
175137 })
176138
177- -- Apply the diff
178139 diff.apply(diff_obj)
179140
180- -- Check what extmarks were actually set
181141 local extmarks = vim.api.nvim_buf_get_extmarks(
182142 bufnr,
183143 diff_obj.namespace,
@@ -195,4 +155,133 @@ T["Diff"]["Applies extmarks to buffer"] = function()
195155 h .is_true (result .extmark_count > 0 , " Should have applied extmarks to buffer" )
196156end
197157
158+ T [" Diff" ][" Word-level diff creates word change extmarks" ] = function ()
159+ local result = child .lua ([[
160+ local bufnr = vim.api.nvim_create_buf(false, true)
161+ vim.api.nvim_buf_set_option(bufnr, "filetype", "lua")
162+
163+ local from = {"local function calculate_total(items)"}
164+ local to = {"local function compute_sum(elements)"}
165+
166+ local diff_obj = diff.create({
167+ bufnr = bufnr,
168+ from_lines = from,
169+ to_lines = to,
170+ ft = "lua"
171+ })
172+
173+ local word_extmarks = 0
174+ for _, hunk in ipairs(diff_obj.hunks) do
175+ for _, extmark in ipairs(hunk.extmarks) do
176+ if extmark.end_col and extmark.hl_group == "CodeCompanionDiffChange" then
177+ word_extmarks = word_extmarks + 1
178+ end
179+ end
180+ end
181+
182+ return {
183+ hunk_kind = diff_obj.hunks[1].kind,
184+ word_extmark_count = word_extmarks,
185+ }
186+ ]] )
187+
188+ h .eq (" change" , result .hunk_kind , " Should be a change hunk" )
189+ h .is_true (result .word_extmark_count > 0 , " Should create word-level change extmarks" )
190+ end
191+
192+ T [" Diff" ][" Word-level diff handles empty lines" ] = function ()
193+ local result = child .lua ([[
194+ local bufnr = vim.api.nvim_create_buf(false, true)
195+ vim.api.nvim_buf_set_option(bufnr, "filetype", "lua")
196+
197+ local from = {"line1", "", "line3"}
198+ local to = {"line1", "new_line", "line3"}
199+
200+ local diff_obj = diff.create({
201+ bufnr = bufnr,
202+ from_lines = from,
203+ to_lines = to,
204+ ft = "lua"
205+ })
206+
207+ return {
208+ hunk_count = #diff_obj.hunks,
209+ hunk_kind = diff_obj.hunks[1].kind,
210+ }
211+ ]] )
212+
213+ h .eq (1 , result .hunk_count , " Should handle empty line changes" )
214+ h .eq (" change" , result .hunk_kind , " Should be a change hunk" )
215+ end
216+
217+ T [" Diff" ][" Clears extmarks from buffer" ] = function ()
218+ local result = child .lua ([[
219+ local bufnr = vim.api.nvim_create_buf(false, true)
220+ vim.api.nvim_buf_set_option(bufnr, "filetype", "lua")
221+
222+ local from = {"line1", "old", "line3"}
223+ local to = {"line1", "new", "line3"}
224+
225+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, to)
226+
227+ local diff_obj = diff.create({
228+ bufnr = bufnr,
229+ from_lines = from,
230+ to_lines = to,
231+ ft = "lua"
232+ })
233+
234+ diff.apply(diff_obj)
235+
236+ local extmarks_before = vim.api.nvim_buf_get_extmarks(
237+ bufnr,
238+ diff_obj.namespace,
239+ 0,
240+ -1,
241+ {}
242+ )
243+
244+ diff.clear(diff_obj)
245+
246+ local extmarks_after = vim.api.nvim_buf_get_extmarks(
247+ bufnr,
248+ diff_obj.namespace,
249+ 0,
250+ -1,
251+ {}
252+ )
253+
254+ return {
255+ before_count = #extmarks_before,
256+ after_count = #extmarks_after,
257+ }
258+ ]] )
259+
260+ h .is_true (result .before_count > 0 , " Should have extmarks before clear" )
261+ h .eq (0 , result .after_count , " Should have no extmarks after clear" )
262+ end
263+
264+ T [" Diff" ][" Handles multiple hunks" ] = function ()
265+ local result = child .lua ([[
266+ local bufnr = vim.api.nvim_create_buf(false, true)
267+ vim.api.nvim_buf_set_option(bufnr, "filetype", "lua")
268+
269+ local from = {"line1", "line2", "line3", "line4", "line5"}
270+ local to = {"line1", "modified2", "line3", "modified4", "line5"}
271+
272+ local diff_obj = diff.create({
273+ bufnr = bufnr,
274+ from_lines = from,
275+ to_lines = to,
276+ ft = "lua"
277+ })
278+
279+ return {
280+ hunk_count = #diff_obj.hunks,
281+ }
282+ ]] )
283+
284+ h .eq (2 , result .hunk_count , " Should detect 2 separate change hunks" )
285+ end
286+
198287return T
0 commit comments