Skip to content

Commit 86323aa

Browse files
committed
Check for onEnterRules that decrease indentation when determining new line indent
1 parent 2260d7c commit 86323aa

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

src/vs/editor/common/languages/autoIndent.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ export function getInheritIndentForLine(
7575
model: IVirtualModel,
7676
lineNumber: number,
7777
honorIntentialIndent: boolean = true,
78-
languageConfigurationService: ILanguageConfigurationService
78+
languageConfigurationService: ILanguageConfigurationService,
79+
indentConverter: IIndentConverter | undefined = undefined
7980
): { indentation: string; action: IndentAction | null; line?: number } | null {
8081
if (autoIndent < EditorAutoIndentStrategy.Full) {
8182
return null;
@@ -152,8 +153,26 @@ export function getInheritIndentForLine(
152153
}
153154

154155
if (honorIntentialIndent) {
156+
let indentation = strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine));
157+
// Check for onEnter rules that should decrease the indent
158+
if (indentConverter) {
159+
const richEditSupport = languageConfigurationService.getLanguageConfiguration(model.tokenization.getLanguageId());
160+
if (richEditSupport) {
161+
const previousLineText = precedingUnIgnoredLine < 1 ? '' : model.getLineContent(precedingUnIgnoredLine - 1);
162+
const afterEnterText = model.getLineContent(lineNumber);
163+
const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, precedingUnIgnoredLineContent, afterEnterText);
164+
if (enterResult) {
165+
if (enterResult.indentAction === IndentAction.Outdent) {
166+
indentation = indentConverter.unshiftIndent(indentation);
167+
} else if (enterResult.removeText && indentation.length >= enterResult.removeText) {
168+
indentation = indentation.substring(0, indentation.length - enterResult.removeText - 1);
169+
}
170+
}
171+
}
172+
}
173+
155174
return {
156-
indentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),
175+
indentation: indentation,
157176
action: null,
158177
line: precedingUnIgnoredLine
159178
};
@@ -222,7 +241,7 @@ export function getGoodIndentForLine(
222241
return null;
223242
}
224243

225-
const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService);
244+
const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService, indentConverter);
226245
const lineContent = virtualModel.getLineContent(lineNumber);
227246

228247
if (indent) {
@@ -338,7 +357,7 @@ export function getIndentForEnter(
338357
};
339358

340359
const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
341-
const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService);
360+
const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService, indentConverter);
342361
if (!afterEnterAction) {
343362
const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
344363
return {
@@ -407,7 +426,7 @@ export function getIndentActionForType(
407426
if (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) {
408427
// after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner.
409428
// 1. Get inherited indent action
410-
const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService);
429+
const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService, indentConverter);
411430
if (!r) {
412431
return null;
413432
}

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4747,6 +4747,53 @@ suite('Editor Controller', () => {
47474747
});
47484748
});
47494749

4750+
test('Issue #136592: onEnterRules should be considered for new line indentation', () => {
4751+
const languageId = 'onEnterRules';
4752+
disposables.add(languageService.registerLanguage({ id: languageId }));
4753+
disposables.add(languageConfigurationService.register(languageId, {
4754+
indentationRules: {
4755+
increaseIndentPattern: /if/,
4756+
decreaseIndentPattern: /never/
4757+
},
4758+
onEnterRules: [{
4759+
beforeText: /outdent/,
4760+
action: {
4761+
indentAction: IndentAction.Outdent
4762+
}
4763+
}]
4764+
}));
4765+
usingCursor({
4766+
text: [
4767+
'if (1)',
4768+
' outdent',
4769+
'',
4770+
'if (1) {',
4771+
' keep indent',
4772+
'',
4773+
'}'
4774+
],
4775+
languageId: languageId,
4776+
}, (editor, model, viewModel) => {
4777+
4778+
// Use indent
4779+
moveTo(editor, viewModel, 6, 1);
4780+
viewModel.type('\n', 'keyboard');
4781+
assert.strictEqual(model.getLineContent(5), ' keep indent');
4782+
assert.strictEqual(model.getLineContent(6), '');
4783+
assert.strictEqual(model.getLineContent(7), ' ');
4784+
assertCursor(viewModel, new Position(7, 5));
4785+
4786+
// No indent
4787+
moveTo(editor, viewModel, 3, 1);
4788+
viewModel.type('\n', 'keyboard');
4789+
assert.strictEqual(model.getLineContent(1), 'if (1)');
4790+
assert.strictEqual(model.getLineContent(2), ' outdent');
4791+
assert.strictEqual(model.getLineContent(3), '');
4792+
assert.strictEqual(model.getLineContent(4), '');
4793+
assertCursor(viewModel, new Position(4, 1));
4794+
});
4795+
});
4796+
47504797
test('ElectricCharacter - does nothing if no electric char', () => {
47514798
usingCursor({
47524799
text: [

0 commit comments

Comments
 (0)