Skip to content

Commit 0b68957

Browse files
committed
Add support for quoted file paths in diff header parsing
1 parent 9980f24 commit 0b68957

5 files changed

Lines changed: 122 additions & 27 deletions

File tree

packages/vscode/src/commands/apply-chat-response-command/handlers/intelligent-update-handler.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export async function handle_intelligent_update(params: {
338338
filePath: string
339339
workspaceName?: string
340340
}
341-
const documentChanges: DocumentChange[] = []
341+
const document_changes: DocumentChange[] = []
342342

343343
// Focus on the largest file for progress tracking
344344
let largest_file: {
@@ -545,13 +545,10 @@ export async function handle_intelligent_update(params: {
545545

546546
// Wait for all promises in this batch
547547
const results = await Promise.all(promises)
548-
documentChanges.push(...results)
548+
document_changes.push(...results)
549549
}
550550

551-
// If we reached here without errors, apply all changes
552-
progress.report({ message: 'Applying changes...' }) // Update progress message
553-
554-
for (const change of documentChanges) {
551+
for (const change of document_changes) {
555552
if (token.isCancellationRequested)
556553
throw new Error('Operation cancelled')
557554

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ describe('clipboard-parser', () => {
259259
`)
260260
})
261261

262+
it('should parse direct diff format in variant g', () => {
263+
const text = load_clipboard_text('diff-direct-variant-g.txt')
264+
const result = parse_response(text, true)
265+
266+
expect(result.type).toBe('patches')
267+
expect(result.patches).toHaveLength(1)
268+
expect(result.patches![0].file_path).toBe('src/index.ts')
269+
expect(result.patches![0].content).toBe(`--- a/src/index.ts
270+
+++ b/src/index.ts
271+
@@ -1,3 +1,3 @@
272+
console.log("hello")
273+
-console.log("old message")
274+
+console.log("new message")
275+
`)
276+
})
277+
262278
it('should parse multiple diff files format in variant a', () => {
263279
const text = load_clipboard_text('diff-multiple-files-variant-a.txt')
264280
const result = parse_response(text, true)
@@ -464,6 +480,32 @@ describe('clipboard-parser', () => {
464480
console.log("hello")
465481
-console.log("old ipsum")
466482
+console.log("new ipsum")
483+
`)
484+
})
485+
486+
it('should parse multiple diff files format in variant i', () => {
487+
const text = load_clipboard_text('diff-multiple-files-variant-i.txt')
488+
const result = parse_response(text, true)
489+
490+
expect(result.type).toBe('patches')
491+
expect(result.patches).toHaveLength(2)
492+
493+
expect(result.patches![0].file_path).toBe('src/lorem.ts')
494+
expect(result.patches![1].file_path).toBe('src/ipsum.ts')
495+
496+
expect(result.patches![0].content).toBe(`--- a/src/lorem.ts
497+
+++ b/src/lorem.ts
498+
@@ -1,3 +1,3 @@
499+
console.log("hello")
500+
-console.log("old lorem")
501+
+console.log("new lorem")
502+
`)
503+
expect(result.patches![1].content).toBe(`--- a/src/ipsum.ts
504+
+++ b/src/ipsum.ts
505+
@@ -1,3 +1,3 @@
506+
console.log("hello")
507+
-console.log("old ipsum")
508+
+console.log("new ipsum")
467509
`)
468510
})
469511
})

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

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,28 @@ export type DiffPatch = {
66
workspace_name?: string
77
}
88

9+
const normalize_header_line = (line: string): string => {
10+
const processed_line = line
11+
.replace(/\s+\d{4}-\d{2}-\d{2}.*$/, '')
12+
.replace(/\t.*$/, '')
13+
14+
if (processed_line.startsWith('--- "a/') && processed_line.endsWith('"')) {
15+
const path = processed_line.substring(7, processed_line.length - 1)
16+
return `--- a/${path}`
17+
}
18+
if (processed_line.startsWith('+++ "b/') && processed_line.endsWith('"')) {
19+
const path = processed_line.substring(7, processed_line.length - 1)
20+
return `+++ b/${path}`
21+
}
22+
23+
return processed_line
24+
}
25+
926
const process_collected_patch_lines = (
1027
patch_lines_array: string[]
1128
): DiffPatch | null => {
1229
const joined_patch_text_for_checks = patch_lines_array.join('\n')
13-
if (joined_patch_text_for_checks.trim() === '') return null
30+
if (joined_patch_text_for_checks.trim() == '') return null
1431

1532
const file_path = extract_file_path_from_lines(patch_lines_array)
1633

@@ -62,7 +79,7 @@ const extract_code_block_patches = (normalized_text: string): DiffPatch[] => {
6279
continue
6380
}
6481

65-
if (trimmed_line === '```') {
82+
if (trimmed_line == '```') {
6683
if (in_diff_block) {
6784
if (current_patch_lines.length > 0) {
6885
const patch_info = process_collected_patch_lines(current_patch_lines)
@@ -76,14 +93,19 @@ const extract_code_block_patches = (normalized_text: string): DiffPatch[] => {
7693

7794
if (in_diff_block) {
7895
const is_potential_new_patch_header =
79-
line.startsWith('diff --git a/') || line.startsWith('--- a/')
96+
line.startsWith('diff --git a/') ||
97+
line.startsWith('--- a/') ||
98+
line.startsWith('--- "a/')
8099

81100
if (is_potential_new_patch_header && current_patch_lines.length > 0) {
82-
const contains_plus_plus_plus = current_patch_lines.some((l) =>
83-
l.startsWith('+++ b/')
101+
const contains_plus_plus_plus = current_patch_lines.some(
102+
(l) => l.startsWith('+++ b/') || l.startsWith('+++ "b/')
84103
)
85104
const contains_main_header = current_patch_lines.some(
86-
(l) => l.startsWith('--- a/') || l.startsWith('diff --git a/')
105+
(l) =>
106+
l.startsWith('--- a/') ||
107+
l.startsWith('diff --git a/') ||
108+
l.startsWith('--- "a/')
87109
)
88110

89111
if (contains_plus_plus_plus && contains_main_header) {
@@ -113,14 +135,19 @@ const parse_multiple_raw_patches = (all_lines: string[]): DiffPatch[] => {
113135

114136
for (const line of all_lines) {
115137
const is_potential_new_patch_header =
116-
line.startsWith('--- a/') || line.startsWith('diff --git a/')
138+
line.startsWith('--- a/') ||
139+
line.startsWith('diff --git a/') ||
140+
line.startsWith('--- "a/')
117141

118142
if (is_potential_new_patch_header && current_patch_lines.length > 0) {
119143
const contains_main_header = current_patch_lines.some(
120-
(l) => l.startsWith('--- a/') || l.startsWith('diff --git a/')
144+
(l) =>
145+
l.startsWith('--- a/') ||
146+
l.startsWith('diff --git a/') ||
147+
l.startsWith('--- "a/')
121148
)
122-
const contains_plus_plus_plus = current_patch_lines.some((l) =>
123-
l.startsWith('+++ b/')
149+
const contains_plus_plus_plus = current_patch_lines.some(
150+
(l) => l.startsWith('+++ b/') || l.startsWith('+++ "b/')
124151
)
125152

126153
if (contains_main_header && contains_plus_plus_plus) {
@@ -161,17 +188,21 @@ export const extract_diff_patches = (clipboard_text: string): DiffPatch[] => {
161188
}
162189

163190
const extract_file_path_from_lines = (lines: string[]): string | undefined => {
164-
for (let i = 0; i < lines.length; i++) {
165-
const file_path_match = lines[i].match(/^\+\+\+ b\/([^\t]+)/)
166-
if (file_path_match) {
191+
for (const line of lines) {
192+
const file_path_match = line.match(
193+
/^\+\+\+ (?:b\/|"b\/)?([^\t"]+)"?(?:\t.*)?$/
194+
)
195+
if (file_path_match && file_path_match[1]) {
167196
return file_path_match[1]
168197
}
169198
}
170199

171200
for (const line of lines) {
172-
const git_diff_match = line.match(/^diff --git a\/(.+) b\/(.+)$/)
173-
if (git_diff_match) {
174-
return git_diff_match[2]
201+
const git_diff_match = line.match(
202+
/^diff --git [^ ]+ (?:b\/|"b\/)?([^\t"]+)"?(?:\t.*)?$/
203+
)
204+
if (git_diff_match && git_diff_match[1]) {
205+
return git_diff_match[1]
175206
}
176207
}
177208

@@ -180,7 +211,7 @@ const extract_file_path_from_lines = (lines: string[]): string | undefined => {
180211

181212
const find_patch_start_index = (lines: string[]): number => {
182213
for (let i = 0; i < lines.length; i++) {
183-
if (lines[i].match(/^\+\+\+ b\//)) {
214+
if (lines[i].match(/^\+\+\+ (?:b\/|"b\/)/)) {
184215
for (let j = i - 1; j >= 0; j--) {
185216
if (lines[j].startsWith('--- ')) {
186217
if (j > 0 && lines[j - 1].startsWith('diff --git')) {
@@ -199,8 +230,9 @@ const find_patch_start_index = (lines: string[]): number => {
199230
if (lines[j].startsWith('--- ')) {
200231
return j
201232
}
202-
if (lines[j].startsWith('diff --git') || lines[j].startsWith('@@'))
233+
if (lines[j].startsWith('diff --git') || lines[j].startsWith('@@')) {
203234
break
235+
}
204236
}
205237
}
206238
}
@@ -217,8 +249,8 @@ const build_patch_content = (
217249

218250
if (patch_start_index >= 0) {
219251
const patch_lines = lines.slice(patch_start_index).map((line) => {
220-
if (line.startsWith('--- a/') || line.startsWith('+++ b/')) {
221-
return line.replace(/\s+\d{4}-\d{2}-\d{2}.*$/, '').replace(/\t.*$/, '')
252+
if (line.startsWith('--- ') || line.startsWith('+++ ')) {
253+
return normalize_header_line(line)
222254
}
223255
return line
224256
})
@@ -229,7 +261,8 @@ const build_patch_content = (
229261
if (content_start_index == -1) {
230262
Logger.log({
231263
function_name: 'build_patch_content',
232-
message: 'No @@ content found, constructing minimal patch headers.',
264+
message:
265+
'No @@ content found, constructing minimal patch headers based on file_path.',
233266
data: { file_path }
234267
})
235268
patch_content = `--- a/${file_path}\n+++ b/${file_path}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
--- "a/src/index.ts"
2+
+++ "b/src/index.ts"
3+
@@ -1,3 +1,3 @@
4+
console.log("hello")
5+
-console.log("old message")
6+
+console.log("new message")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
```diff
2+
--- "a/src/lorem.ts"
3+
+++ "b/src/lorem.ts"
4+
@@ -1,3 +1,3 @@
5+
console.log("hello")
6+
-console.log("old lorem")
7+
+console.log("new lorem")
8+
```
9+
10+
```diff
11+
--- "a/src/ipsum.ts"
12+
+++ "b/src/ipsum.ts"
13+
@@ -1,3 +1,3 @@
14+
console.log("hello")
15+
-console.log("old ipsum")
16+
+console.log("new ipsum")
17+
```

0 commit comments

Comments
 (0)