Skip to content

Commit 11218ad

Browse files
committed
Enhance diff parsing to correctly reconstruct patch headers and accurately split multiple patches
1 parent 3e87f70 commit 11218ad

5 files changed

Lines changed: 105 additions & 11 deletions

File tree

‎packages/vscode/src/commands/apply-chat-response-command/utils/clipboard-parser/clipboard-parser.spec.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,27 @@ describe('clipboard-parser', () => {
753753
)
754754
})
755755

756+
it('should parse multiple diff files format in variant m', () => {
757+
const text = load_test_case_file(
758+
'diff-multiple-files-variant-m',
759+
'diff-multiple-files-variant-m.txt'
760+
)
761+
const result = parse_response(text, true)
762+
763+
expect(result.type).toBe('patches')
764+
expect(result.patches).toHaveLength(2)
765+
766+
expect(result.patches![0].file_path).toBe('src/lorem.ts')
767+
expect(result.patches![1].file_path).toBe('src/ipsum.ts')
768+
769+
expect(result.patches![0].content).toBe(
770+
load_test_case_file('diff-multiple-files-variant-m', 'file-1.txt')
771+
)
772+
expect(result.patches![1].content).toBe(
773+
load_test_case_file('diff-multiple-files-variant-m', 'file-2.txt')
774+
)
775+
})
776+
756777
it('should parse multiple diff files format with inner triple backticks', () => {
757778
const text = load_test_case_file(
758779
'diff-inner-triple-backticks',

‎packages/vscode/src/commands/apply-chat-response-command/utils/clipboard-parser/extract-diff-patches/extract-diffs.ts‎

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,25 @@ const parse_multiple_raw_patches = (all_lines: string[]): Diff[] => {
303303
)
304304

305305
if (contains_main_header && contains_plus_plus_plus) {
306-
const patch_info = process_collected_patch_lines(current_patch_lines)
307-
if (patch_info) {
308-
patches.push(patch_info)
306+
let should_split = false
307+
if (line.startsWith('diff --git ')) {
308+
should_split = true
309+
} else if (line.startsWith('--- ')) {
310+
const contains_hunk = current_patch_lines.some((l) =>
311+
l.startsWith('@@')
312+
)
313+
if (contains_hunk) {
314+
should_split = true
315+
}
316+
}
317+
if (should_split) {
318+
const patch_info = process_collected_patch_lines(current_patch_lines)
319+
if (patch_info) {
320+
patches.push(patch_info)
321+
}
322+
current_patch_lines = [line]
323+
continue
309324
}
310-
current_patch_lines = [line]
311-
continue
312325
}
313326
}
314327
current_patch_lines.push(line)
@@ -399,13 +412,42 @@ const build_patch_content = (
399412
let patch_content: string
400413

401414
if (patch_start_index >= 0) {
402-
const patch_lines = lines.slice(patch_start_index).map((line) => {
403-
if (line.startsWith('--- ') || line.startsWith('+++ ')) {
404-
return normalize_header_line(line)
415+
let patch_lines = lines.slice(patch_start_index)
416+
417+
const hunk_start_idx = patch_lines.findIndex((line) =>
418+
line.startsWith('@@')
419+
)
420+
421+
if (hunk_start_idx > 0) {
422+
const header_lines = patch_lines.slice(0, hunk_start_idx)
423+
const body_lines = patch_lines.slice(hunk_start_idx)
424+
425+
let from_line: string | undefined
426+
let to_line: string | undefined
427+
let diff_git_line: string | undefined
428+
429+
for (const line of header_lines) {
430+
if (line.startsWith('--- ')) from_line = line
431+
if (line.startsWith('+++ ')) to_line = line
432+
if (line.startsWith('diff --git ')) diff_git_line = line
405433
}
406-
return line
407-
})
408-
patch_content = patch_lines.join('\n')
434+
435+
const final_header: string[] = []
436+
if (diff_git_line) final_header.push(diff_git_line)
437+
if (from_line) final_header.push(from_line)
438+
if (to_line) final_header.push(to_line)
439+
440+
patch_lines = [...final_header, ...body_lines]
441+
}
442+
443+
patch_content = patch_lines
444+
.map((line) => {
445+
if (line.startsWith('--- ') || line.startsWith('+++ ')) {
446+
return normalize_header_line(line)
447+
}
448+
return line
449+
})
450+
.join('\n')
409451
} else {
410452
const content_start_index = lines.findIndex((line) => line.startsWith('@@'))
411453

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
```diff
2+
--- a/src/lorem.ts
3+
+++ /dev/null
4+
deleted file mode 100644
5+
index 92d844c..0000000
6+
--- a/src/lorem.ts
7+
+++ /dev/null
8+
@@ -1,1 +0,0 @@
9+
-console.log("old lorem")
10+
```
11+
12+
```diff
13+
--- /dev/null
14+
+++ b/src/ipsum.ts
15+
new file mode 100644
16+
index 0000000..69b662d
17+
--- /dev/null
18+
+++ b/src/ipsum.ts
19+
@@ -0,0 +1,2 @@
20+
+console.log("hello")
21+
+console.log("new ipsum")
22+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
--- a/src/lorem.ts
2+
+++ /dev/null
3+
@@ -1,1 +0,0 @@
4+
-console.log("old lorem")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--- /dev/null
2+
+++ b/src/ipsum.ts
3+
@@ -0,0 +1,2 @@
4+
+console.log("hello")
5+
+console.log("new ipsum")

0 commit comments

Comments
 (0)