Skip to content

Commit 2182ebd

Browse files
committed
Add support for parsing deleted file headers in diff responses and test the new case
1 parent 3c1926f commit 2182ebd

5 files changed

Lines changed: 119 additions & 29 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
@@ -1369,6 +1369,27 @@ describe('clipboard-parser', () => {
13691369
})
13701370
})
13711371

1372+
it('parses diff and deletion via header', () => {
1373+
const test_case = 'diff-deletion-via-header'
1374+
const text = load_test_case_file(test_case, `${test_case}.txt`)
1375+
const result = parse_response({
1376+
response: text,
1377+
is_single_root_folder_workspace: true
1378+
})
1379+
1380+
expect(result).toHaveLength(2)
1381+
expect(result[0]).toMatchObject({
1382+
type: 'diff',
1383+
file_path: 'src/old.ts',
1384+
content: load_test_case_file(test_case, '1-file.txt')
1385+
})
1386+
expect(result[1]).toMatchObject({
1387+
type: 'diff',
1388+
file_path: 'src/index.ts',
1389+
content: load_test_case_file(test_case, '2-file.txt')
1390+
})
1391+
})
1392+
13721393
it('parses a mix of a new file from heading and code block, and a separate diff block', () => {
13731394
const test_case = 'diff-mix-new-file-from-heading-and-diff'
13741395
const text = load_test_case_file(test_case, `${test_case}.txt`)

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

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,52 @@ const convert_code_block_to_new_file_diff = (params: {
494494
}
495495
}
496496

497+
const process_text_for_deleted_files = (params: {
498+
lines: string[]
499+
is_single_root: boolean
500+
}): DiffOrTextBlock[] => {
501+
const items: DiffOrTextBlock[] = []
502+
let current_text_lines: string[] = []
503+
504+
const deleted_file_header_regex = /^###\s+Deleted file:\s*`([^`]+)`/
505+
506+
for (const line of params.lines) {
507+
const trimmed_line = line.trim()
508+
if (trimmed_line === '<files>' || trimmed_line === '</files>') {
509+
continue
510+
}
511+
const match = trimmed_line.match(deleted_file_header_regex)
512+
513+
if (match && match[1]) {
514+
const text_content = current_text_lines.join('\n').trim()
515+
if (text_content) {
516+
items.push({ type: 'text', content: text_content })
517+
}
518+
current_text_lines = []
519+
520+
const raw_file_path = normalize_path(match[1])
521+
const { workspace_name, relative_path } = extract_workspace_and_path({
522+
raw_file_path,
523+
is_single_root_folder_workspace: params.is_single_root
524+
})
525+
const content = `--- a/${relative_path}\n+++ /dev/null\n@@ +0,0 +0,0 @@\n`
526+
items.push({
527+
type: 'diff',
528+
file_path: relative_path,
529+
workspace_name,
530+
content
531+
})
532+
} else {
533+
current_text_lines.push(line)
534+
}
535+
}
536+
const text_content = current_text_lines.join('\n').trim()
537+
if (text_content) {
538+
items.push({ type: 'text', content: text_content })
539+
}
540+
return items
541+
}
542+
497543
const extract_all_code_block_patches = (params: {
498544
normalized_text: string
499545
is_single_root: boolean
@@ -663,18 +709,15 @@ const extract_all_code_block_patches = (params: {
663709
? lines.slice(block.start, block.end + 1)
664710
: lines.slice(block.start + 1, block.end)
665711

666-
const text_before = lines
667-
.slice(last_block_end + 1, block.start)
668-
.filter((line) => {
669-
const trimmed = line.trim()
670-
return trimmed != '<files>' && trimmed != '</files>'
671-
})
672-
.join('\n')
673-
674712
if (block.type == 'diff' || block.type == 'patch') {
675-
if (text_before.trim()) {
676-
items.push({ type: 'text', content: text_before.trim() })
677-
}
713+
const text_before_lines = lines.slice(last_block_end + 1, block.start)
714+
items.push(
715+
...process_text_for_deleted_files({
716+
lines: text_before_lines,
717+
is_single_root: params.is_single_root
718+
})
719+
)
720+
678721
const patches = diff_block_patches.get(block.start) || []
679722
if (patches.length > 0) {
680723
const last_item = items.length > 0 ? items[items.length - 1] : undefined
@@ -695,15 +738,22 @@ const extract_all_code_block_patches = (params: {
695738
} else {
696739
if (i < code_blocks.length - 1) {
697740
const next_block = code_blocks[i + 1]
698-
if (next_block.type === 'diff' || next_block.type === 'patch') {
741+
if (next_block.type == 'diff' || next_block.type == 'patch') {
699742
const xml_path_regex = /<[\w-]+\s+path=["']([^"']+)["']/
700-
const non_empty_lines = block_lines.filter((l) => l.trim() !== '')
701-
if (non_empty_lines.length === 1) {
743+
const non_empty_lines = block_lines.filter((l) => l.trim() != '')
744+
if (non_empty_lines.length == 1) {
702745
const match = non_empty_lines[0].match(xml_path_regex)
703746
if (match && match[1]) {
704-
if (text_before.trim()) {
705-
items.push({ type: 'text', content: text_before.trim() })
706-
}
747+
const text_before_lines = lines.slice(
748+
last_block_end + 1,
749+
block.start
750+
)
751+
items.push(
752+
...process_text_for_deleted_files({
753+
lines: text_before_lines,
754+
is_single_root: params.is_single_root
755+
})
756+
)
707757
last_block_end = block.end
708758
continue
709759
}
@@ -726,9 +776,14 @@ const extract_all_code_block_patches = (params: {
726776
if (patch) {
727777
const file_key = `${patch.workspace_name || ''}:${patch.file_path}`
728778
if (!files_with_diffs.has(file_key)) {
729-
if (text_before.trim()) {
730-
items.push({ type: 'text', content: text_before.trim() })
731-
}
779+
const text_before_lines = lines.slice(last_block_end + 1, block.start)
780+
items.push(
781+
...process_text_for_deleted_files({
782+
lines: text_before_lines,
783+
is_single_root: params.is_single_root
784+
})
785+
)
786+
732787
const last_item =
733788
items.length > 0 ? items[items.length - 1] : undefined
734789
if (last_item && last_item.type == 'text') {
@@ -754,16 +809,13 @@ const extract_all_code_block_patches = (params: {
754809
}
755810

756811
if (last_block_end < lines.length - 1) {
757-
const text_after = lines
758-
.slice(last_block_end + 1)
759-
.filter((line) => {
760-
const trimmed = line.trim()
761-
return trimmed != '<files>' && trimmed != '</files>'
812+
const remaining_lines = lines.slice(last_block_end + 1)
813+
items.push(
814+
...process_text_for_deleted_files({
815+
lines: remaining_lines,
816+
is_single_root: params.is_single_root
762817
})
763-
.join('\n')
764-
if (text_after.trim()) {
765-
items.push({ type: 'text', content: text_after.trim() })
766-
}
818+
)
767819
}
768820

769821
return items
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--- a/src/old.ts
2+
+++ /dev/null
3+
@@ +0,0 +0,0 @@
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--- a/src/index.ts
2+
+++ b/src/index.ts
3+
@@ -1,5 +1,7 @@
4+
console.log("hello")
5+
-console.log("old message")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
### Deleted file: `src/old.ts`
2+
3+
```diff
4+
--- a/src/index.ts
5+
+++ b/src/index.ts
6+
@@ -1,5 +1,7 @@
7+
console.log("hello")
8+
-console.log("old message")
9+
```

0 commit comments

Comments
 (0)