Skip to content

Commit

Permalink
Check for onEnterRules that decrease indentation when determining new…
Browse files Browse the repository at this point in the history
… line indent
  • Loading branch information
ssigwart committed Jun 5, 2022
1 parent 2260d7c commit 86323aa
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 5 deletions.
29 changes: 24 additions & 5 deletions src/vs/editor/common/languages/autoIndent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ export function getInheritIndentForLine(
model: IVirtualModel,
lineNumber: number,
honorIntentialIndent: boolean = true,
languageConfigurationService: ILanguageConfigurationService
languageConfigurationService: ILanguageConfigurationService,
indentConverter: IIndentConverter | undefined = undefined
): { indentation: string; action: IndentAction | null; line?: number } | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
Expand Down Expand Up @@ -152,8 +153,26 @@ export function getInheritIndentForLine(
}

if (honorIntentialIndent) {
let indentation = strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine));
// Check for onEnter rules that should decrease the indent
if (indentConverter) {
const richEditSupport = languageConfigurationService.getLanguageConfiguration(model.tokenization.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
};
Expand Down Expand Up @@ -222,7 +241,7 @@ export function getGoodIndentForLine(
return null;
}

const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService);
const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService, indentConverter);
const lineContent = virtualModel.getLineContent(lineNumber);

if (indent) {
Expand Down Expand Up @@ -338,7 +357,7 @@ export function getIndentForEnter(
};

const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService);
const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService, indentConverter);
if (!afterEnterAction) {
const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
return {
Expand Down Expand Up @@ -407,7 +426,7 @@ export function getIndentActionForType(
if (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) {
// after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner.
// 1. Get inherited indent action
const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService);
const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService, indentConverter);
if (!r) {
return null;
}
Expand Down
47 changes: 47 additions & 0 deletions src/vs/editor/test/browser/controller/cursor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4747,6 +4747,53 @@ suite('Editor Controller', () => {
});
});

test('Issue #136592: onEnterRules should be considered for new line indentation', () => {
const languageId = 'onEnterRules';
disposables.add(languageService.registerLanguage({ id: languageId }));
disposables.add(languageConfigurationService.register(languageId, {
indentationRules: {
increaseIndentPattern: /if/,
decreaseIndentPattern: /never/
},
onEnterRules: [{
beforeText: /outdent/,
action: {
indentAction: IndentAction.Outdent
}
}]
}));
usingCursor({
text: [
'if (1)',
' outdent',
'',
'if (1) {',
' keep indent',
'',
'}'
],
languageId: 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));
});
});

test('ElectricCharacter - does nothing if no electric char', () => {
usingCursor({
text: [
Expand Down

0 comments on commit 86323aa

Please sign in to comment.