Skip to content

Commit 6fee663

Browse files
authored
fix(ui): preserve new line at the end of edit window (google-gemini#27057)
1 parent 456d1ae commit 6fee663

2 files changed

Lines changed: 48 additions & 8 deletions

File tree

packages/core/src/tools/edit.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,42 @@ function doIt() {
511511
expect(result.newContent).toBe(expectedContent);
512512
});
513513

514+
it('should preserve trailing newlines in flexible replacement (regression)', async () => {
515+
const content = ' line1\n line2\n line3\n';
516+
const result = await calculateReplacement(mockConfig, {
517+
params: {
518+
file_path: 'test.txt',
519+
old_string: 'line1\nline2',
520+
new_string: 'line1-replaced\nline2-replaced',
521+
},
522+
currentContent: content,
523+
abortSignal,
524+
});
525+
526+
expect(result.newContent).toBe(
527+
' line1-replaced\n line2-replaced\n line3\n',
528+
);
529+
});
530+
531+
it('should correctly increment loop index in flexible replacement when allow_multiple is true (regression)', async () => {
532+
const content = ' match1\n match2\n match1\n match2\n';
533+
const result = await calculateReplacement(mockConfig, {
534+
params: {
535+
file_path: 'test.txt',
536+
old_string: 'match1\nmatch2',
537+
new_string: 'replaced1\nreplaced2\nreplaced3',
538+
allow_multiple: true,
539+
},
540+
currentContent: content,
541+
abortSignal,
542+
});
543+
544+
expect(result.occurrences).toBe(2);
545+
expect(result.newContent).toBe(
546+
' replaced1\n replaced2\n replaced3\n replaced1\n replaced2\n replaced3\n',
547+
);
548+
});
549+
514550
it('should correctly rebase indentation in flexible replacement without double-indenting', async () => {
515551
const content = ' if (a) {\n foo();\n }\n';
516552
// old_string and new_string are unindented. They should be rebased to 4-space.

packages/core/src/tools/edit.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,19 @@ async function calculateFlexibleReplacement(
202202
const indentationMatch = firstLineInMatch.match(/^([ \t]*)/);
203203
const indentation = indentationMatch ? indentationMatch[1] : '';
204204
const newBlockWithIndent = applyIndentation(replaceLines, indentation);
205-
sourceLines.splice(
206-
i,
207-
searchLinesStripped.length,
208-
newBlockWithIndent.join('\n'),
209-
);
210-
i += replaceLines.length;
211-
} else {
212-
i++;
205+
206+
let replacementText = newBlockWithIndent.join('\n');
207+
if (
208+
new_string !== '' &&
209+
window[window.length - 1].endsWith('\n') &&
210+
!replacementText.endsWith('\n')
211+
) {
212+
replacementText += '\n';
213+
}
214+
215+
sourceLines.splice(i, searchLinesStripped.length, replacementText);
213216
}
217+
i++;
214218
}
215219

216220
if (flexibleOccurrences > 0) {

0 commit comments

Comments
 (0)