Skip to content

Commit db4955b

Browse files
committed
Check for onEnterRules that decrease indentation when determining new line indent
1 parent 66b1668 commit db4955b

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

src/vs/editor/common/modes/languageConfigurationRegistry.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ export class LanguageConfigurationRegistryImpl {
366366
*
367367
* This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not.
368368
*/
369-
public getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null {
369+
public getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true, indentConverter: IIndentConverter | undefined = undefined): { indentation: string; action: IndentAction | null; line?: number; } | null {
370370
if (autoIndent < EditorAutoIndentStrategy.Full) {
371371
return null;
372372
}
@@ -442,8 +442,26 @@ export class LanguageConfigurationRegistryImpl {
442442
}
443443

444444
if (honorIntentialIndent) {
445+
let indentation = strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine));
446+
// Check for onEnter rules that should decrease the indent
447+
if (indentConverter) {
448+
const richEditSupport = this.getLanguageConfiguration(model.getLanguageId());
449+
if (richEditSupport) {
450+
const previousLineText = precedingUnIgnoredLine < 1 ? '' : model.getLineContent(precedingUnIgnoredLine - 1);
451+
const afterEnterText = model.getLineContent(lineNumber);
452+
const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, precedingUnIgnoredLineContent, afterEnterText);
453+
if (enterResult) {
454+
if (enterResult.indentAction === IndentAction.Outdent) {
455+
indentation = indentConverter.unshiftIndent(indentation);
456+
} else if (enterResult.removeText && indentation.length >= enterResult.removeText) {
457+
indentation = indentation.substring(0, indentation.length - enterResult.removeText - 1);
458+
}
459+
}
460+
}
461+
}
462+
445463
return {
446-
indentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),
464+
indentation: indentation,
447465
action: null,
448466
line: precedingUnIgnoredLine
449467
};
@@ -505,7 +523,7 @@ export class LanguageConfigurationRegistryImpl {
505523
return null;
506524
}
507525

508-
const indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber);
526+
const indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber, true, indentConverter);
509527
const lineContent = virtualModel.getLineContent(lineNumber);
510528

511529
if (indent) {
@@ -613,7 +631,7 @@ export class LanguageConfigurationRegistryImpl {
613631
};
614632

615633
const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
616-
const afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1);
634+
const afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, true, indentConverter);
617635
if (!afterEnterAction) {
618636
const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
619637
return {

src/vs/editor/test/browser/controller/cursor.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4529,6 +4529,57 @@ suite('Editor Controller - Indentation Rules', () => {
45294529
latexMode.dispose();
45304530
model.dispose();
45314531
});
4532+
4533+
test('Issue #136592: onEnterRules should be considered for new line indentation', () => {
4534+
const mode = new class extends MockMode {
4535+
constructor() {
4536+
super('onEnterMode');
4537+
this._register(LanguageConfigurationRegistry.register(this.languageId, {
4538+
indentationRules: {
4539+
increaseIndentPattern: /if/,
4540+
decreaseIndentPattern: /never/
4541+
},
4542+
onEnterRules: [{
4543+
beforeText: /outdent/,
4544+
action: {
4545+
indentAction: IndentAction.Outdent
4546+
}
4547+
}]
4548+
}));
4549+
}
4550+
}();
4551+
usingCursor({
4552+
text: [
4553+
'if (1)',
4554+
' outdent',
4555+
'',
4556+
'if (1) {',
4557+
' keep indent',
4558+
'',
4559+
'}'
4560+
],
4561+
languageId: mode.languageId,
4562+
}, (editor, model, viewModel) => {
4563+
4564+
// Use indent
4565+
moveTo(editor, viewModel, 6, 1);
4566+
viewModel.type('\n', 'keyboard');
4567+
assert.strictEqual(model.getLineContent(5), ' keep indent');
4568+
assert.strictEqual(model.getLineContent(6), '');
4569+
assert.strictEqual(model.getLineContent(7), ' ');
4570+
assertCursor(viewModel, new Position(7, 5));
4571+
4572+
// No indent
4573+
moveTo(editor, viewModel, 3, 1);
4574+
viewModel.type('\n', 'keyboard');
4575+
assert.strictEqual(model.getLineContent(1), 'if (1)');
4576+
assert.strictEqual(model.getLineContent(2), ' outdent');
4577+
assert.strictEqual(model.getLineContent(3), '');
4578+
assert.strictEqual(model.getLineContent(4), '');
4579+
assertCursor(viewModel, new Position(4, 1));
4580+
});
4581+
mode.dispose();
4582+
});
45324583
});
45334584

45344585
interface ICursorOpts {

0 commit comments

Comments
 (0)