Check for onEnterRules that decrease indentation when determining new line indent

This commit is contained in:
Stephen Sigwart 2021-11-06 20:59:39 -04:00
parent 66b1668b66
commit db4955b550
2 changed files with 73 additions and 4 deletions

View file

@ -366,7 +366,7 @@ export class LanguageConfigurationRegistryImpl {
*
* This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not.
*/
public getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null {
public getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true, indentConverter: IIndentConverter | undefined = undefined): { indentation: string; action: IndentAction | null; line?: number; } | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
}
@ -442,8 +442,26 @@ export class LanguageConfigurationRegistryImpl {
}
if (honorIntentialIndent) {
let indentation = strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine));
// Check for onEnter rules that should decrease the indent
if (indentConverter) {
const richEditSupport = this.getLanguageConfiguration(model.getLanguageId());
if (richEditSupport) {
const previousLineText = precedingUnIgnoredLine < 1 ? '' : model.getLineContent(precedingUnIgnoredLine - 1);
const afterEnterText = model.getLineContent(lineNumber);
const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, precedingUnIgnoredLineContent, afterEnterText);
if (enterResult) {
if (enterResult.indentAction === IndentAction.Outdent) {
indentation = indentConverter.unshiftIndent(indentation);
} else if (enterResult.removeText && indentation.length >= enterResult.removeText) {
indentation = indentation.substring(0, indentation.length - enterResult.removeText - 1);
}
}
}
}
return {
indentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),
indentation: indentation,
action: null,
line: precedingUnIgnoredLine
};
@ -505,7 +523,7 @@ export class LanguageConfigurationRegistryImpl {
return null;
}
const indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber);
const indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber, true, indentConverter);
const lineContent = virtualModel.getLineContent(lineNumber);
if (indent) {
@ -613,7 +631,7 @@ export class LanguageConfigurationRegistryImpl {
};
const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
const afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1);
const afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, true, indentConverter);
if (!afterEnterAction) {
const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
return {

View file

@ -4529,6 +4529,57 @@ suite('Editor Controller - Indentation Rules', () => {
latexMode.dispose();
model.dispose();
});
test('Issue #136592: onEnterRules should be considered for new line indentation', () => {
const mode = new class extends MockMode {
constructor() {
super('onEnterMode');
this._register(LanguageConfigurationRegistry.register(this.languageId, {
indentationRules: {
increaseIndentPattern: /if/,
decreaseIndentPattern: /never/
},
onEnterRules: [{
beforeText: /outdent/,
action: {
indentAction: IndentAction.Outdent
}
}]
}));
}
}();
usingCursor({
text: [
'if (1)',
' outdent',
'',
'if (1) {',
' keep indent',
'',
'}'
],
languageId: mode.languageId,
}, (editor, model, viewModel) => {
// Use indent
moveTo(editor, viewModel, 6, 1);
viewModel.type('\n', 'keyboard');
assert.strictEqual(model.getLineContent(5), ' keep indent');
assert.strictEqual(model.getLineContent(6), '');
assert.strictEqual(model.getLineContent(7), ' ');
assertCursor(viewModel, new Position(7, 5));
// No indent
moveTo(editor, viewModel, 3, 1);
viewModel.type('\n', 'keyboard');
assert.strictEqual(model.getLineContent(1), 'if (1)');
assert.strictEqual(model.getLineContent(2), ' outdent');
assert.strictEqual(model.getLineContent(3), '');
assert.strictEqual(model.getLineContent(4), '');
assertCursor(viewModel, new Position(4, 1));
});
mode.dispose();
});
});
interface ICursorOpts {