Skip to content

Commit 1e2c3d3

Browse files
committed
Fix indentation issues when pasting with trailing newline
Fixes microsoft#85781 Fixes microsoft#147223 Fixes microsoft#33760 Fixes microsoft#65614 Fixes microsoft#86301 (Some of the issues above were closed as being limitations of the regex based indentation rules, but this change is able to fix them.) Note that ReindentSelectedLinesAction already does the same thing as this fix (which is what inspired it -- I noticed that running Reindent Selected Lines on the equivalent code didn't have the same issues): see https://github.com/microsoft/vscode/blob/6cbd9e8f3c5a59c5b1170aac8f2b5e9b0b4edfee/src/vs/editor/contrib/indentation/browser/indentation.ts#L390-L392
1 parent e7e0370 commit 1e2c3d3

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

src/vs/editor/contrib/indentation/browser/indentation.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -521,17 +521,26 @@ export class AutoIndentOnPaste implements IEditorContribution {
521521
}
522522
};
523523

524+
let endLineNumber = range.endLineNumber;
525+
526+
// Don't indent the final line if the range ends at the start of it, because it will mess up
527+
// the indentation of the preexisting code (outside the paste range) on that line.
528+
// See https://github.com/microsoft/vscode/issues/85781 and https://github.com/microsoft/vscode/issues/147223
529+
if (range.endColumn === 1) {
530+
endLineNumber--;
531+
}
532+
524533
let startLineNumber = range.startLineNumber;
525534

526-
while (startLineNumber <= range.endLineNumber) {
535+
while (startLineNumber <= endLineNumber) {
527536
if (this.shouldIgnoreLine(model, startLineNumber)) {
528537
startLineNumber++;
529538
continue;
530539
}
531540
break;
532541
}
533542

534-
if (startLineNumber > range.endLineNumber) {
543+
if (startLineNumber > endLineNumber) {
535544
return;
536545
}
537546

@@ -568,15 +577,15 @@ export class AutoIndentOnPaste implements IEditorContribution {
568577
const firstLineNumber = startLineNumber;
569578

570579
// ignore empty or ignored lines
571-
while (startLineNumber < range.endLineNumber) {
580+
while (startLineNumber < endLineNumber) {
572581
if (!/\S/.test(model.getLineContent(startLineNumber + 1))) {
573582
startLineNumber++;
574583
continue;
575584
}
576585
break;
577586
}
578587

579-
if (startLineNumber !== range.endLineNumber) {
588+
if (startLineNumber !== endLineNumber) {
580589
const virtualModel = {
581590
tokenization: {
582591
getLineTokens: (lineNumber: number) => {
@@ -604,7 +613,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
604613

605614
if (newSpaceCntOfSecondLine !== oldSpaceCntOfSecondLine) {
606615
const spaceCntOffset = newSpaceCntOfSecondLine - oldSpaceCntOfSecondLine;
607-
for (let i = startLineNumber + 1; i <= range.endLineNumber; i++) {
616+
for (let i = startLineNumber + 1; i <= endLineNumber; i++) {
608617
const lineContent = model.getLineContent(i);
609618
const originalIndent = strings.getLeadingWhitespace(lineContent);
610619
const originalSpacesCnt = indentUtils.getSpaceCnt(originalIndent, tabSize);

src/vs/editor/contrib/indentation/test/browser/indentation.test.ts

+41
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,47 @@ suite('Editor Contrib - Auto Indent On Paste', () => {
271271
assert.strictEqual(model.getValue(), pasteText);
272272
});
273273
});
274+
275+
test('issue #85781: Do not indent the final line if the selection ends at the start of it', () => {
276+
const languageId = 'indentFinalLine';
277+
const lines = [
278+
'if (true) {',
279+
' console.log("end");',
280+
'}',
281+
];
282+
const model = createTextModel(lines.join('\n'), languageId, {});
283+
disposables.add(model);
284+
withTestCodeEditor(model, { autoIndent: 'full' }, (editor, viewModel, instantiationService) => {
285+
const languageService = instantiationService.get(ILanguageService);
286+
const languageConfigurationService = instantiationService.get(ILanguageConfigurationService);
287+
disposables.add(languageService.registerLanguage({ id: languageId }));
288+
disposables.add(languageConfigurationService.register(languageId, {
289+
brackets: [
290+
['{', '}'],
291+
['[', ']'],
292+
['(', ')']
293+
],
294+
indentationRules: javascriptIndentationRules,
295+
onEnterRules: javascriptOnEnterRules
296+
}));
297+
298+
const autoIndentOnPasteController = editor.registerAndInstantiateContribution(AutoIndentOnPaste.ID, AutoIndentOnPaste);
299+
const pasteLines = [
300+
'console.log(1);',
301+
'console.log(2);',
302+
];
303+
304+
viewModel.setSelections('test', [new Selection(2, 1, 2, 1)]);
305+
viewModel.paste(pasteLines.join('\n') + '\n', false, undefined, 'keyboard');
306+
autoIndentOnPasteController.trigger(new Range(2, 1, 4, 1));
307+
const expectText = [
308+
lines[0],
309+
...pasteLines.map(line => ' ' + line),
310+
...lines.slice(1),
311+
].join('\n');
312+
assert.strictEqual(model.getValue(), expectText);
313+
});
314+
});
274315
});
275316

276317
suite('Editor Contrib - Keep Indent On Paste', () => {

0 commit comments

Comments
 (0)