Adding indentation tests for different languages (#208988)

* adding rules

* adding two more tests

* adding more tests

* adding more language configuration data

* skipping one of the tests

* removing comment
This commit is contained in:
Aiday Marlen Kyzy 2024-03-28 17:56:00 +01:00 committed by GitHub
parent 74ccd516fd
commit 609c11f87f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 574 additions and 36 deletions

View file

@ -18,15 +18,22 @@ import { NullState } from 'vs/editor/common/languages/nullTokenize';
import { AutoIndentOnPaste, IndentationToSpacesCommand, IndentationToTabsCommand } from 'vs/editor/contrib/indentation/browser/indentation';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { testCommand } from 'vs/editor/test/browser/testCommand';
import { goIndentationRules, javascriptIndentationRules, phpIndentationRules, rubyIndentationRules } from 'vs/editor/test/common/modes/supports/indentationRules';
import { cppOnEnterRules, javascriptOnEnterRules, phpOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { goIndentationRules, htmlIndentationRules, javascriptIndentationRules, latexIndentationRules, luaIndentationRules, phpIndentationRules, rubyIndentationRules } from 'vs/editor/test/common/modes/supports/indentationRules';
import { cppOnEnterRules, htmlOnEnterRules, javascriptOnEnterRules, phpOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { TypeOperations } from 'vs/editor/common/cursor/cursorTypeOperations';
import { cppBracketRules, goBracketRules, htmlBracketRules, latexBracketRules, luaBracketRules, phpBracketRules, rubyBracketRules, typescriptBracketRules, vbBracketRules } from 'vs/editor/test/common/modes/supports/bracketRules';
import { latexAutoClosingPairsRules } from 'vs/editor/test/common/modes/supports/autoClosingPairsRules';
enum Language {
TypeScript,
Ruby,
PHP,
Go,
CPP
CPP,
HTML,
VB,
Latex,
Lua
}
function testIndentationToSpacesCommand(lines: string[], selection: Selection, tabSize: number, expectedLines: string[], expectedSelection: Selection): void {
@ -49,12 +56,7 @@ function registerLanguageConfiguration(instantiationService: TestInstantiationSe
switch (language) {
case Language.TypeScript:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['${', '}'],
['{', '}'],
['[', ']'],
['(', ')']
],
brackets: typescriptBracketRules,
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
@ -65,45 +67,54 @@ function registerLanguageConfiguration(instantiationService: TestInstantiationSe
break;
case Language.Ruby:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
brackets: rubyBracketRules,
indentationRules: rubyIndentationRules,
}));
break;
case Language.PHP:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
brackets: phpBracketRules,
indentationRules: phpIndentationRules,
onEnterRules: phpOnEnterRules
}));
break;
case Language.Go:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
brackets: goBracketRules,
indentationRules: goIndentationRules
}));
break;
case Language.CPP:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
brackets: cppBracketRules,
onEnterRules: cppOnEnterRules
}));
break;
case Language.HTML:
disposables.add(languageConfigurationService.register(languageId, {
brackets: htmlBracketRules,
indentationRules: htmlIndentationRules,
onEnterRules: htmlOnEnterRules
}));
break;
case Language.VB:
disposables.add(languageConfigurationService.register(languageId, {
brackets: vbBracketRules,
}));
break;
case Language.Latex:
disposables.add(languageConfigurationService.register(languageId, {
brackets: latexBracketRules,
autoClosingPairs: latexAutoClosingPairsRules,
indentationRules: latexIndentationRules
}));
break;
case Language.Lua:
disposables.add(languageConfigurationService.register(languageId, {
brackets: luaBracketRules,
indentationRules: luaIndentationRules
}));
break;
}
}
@ -305,6 +316,78 @@ suite('Change Indentation to Tabs - TypeScript/Javascript', () => {
});
});
suite('Indent With Tab - TypeScript/JavaScript', () => {
const languageId = 'ts-test';
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
teardown(() => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
test('temp issue because there should be at least one passing test in a suite', () => {
assert.ok(true);
});
test.skip('issue #63388: perserve correct indentation on tab 1', () => {
// https://github.com/microsoft/vscode/issues/63388
const model = createTextModel([
'/*',
' * Comment',
' * /',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(1, 1, 3, 5));
editor.executeCommands('editor.action.indentLines', TypeOperations.indent(viewModel.cursorConfig, editor.getModel(), editor.getSelections()));
assert.strictEqual(model.getValue(), [
' /*',
' * Comment',
' * /',
].join('\n'));
});
});
test.skip('issue #63388: perserve correct indentation on tab 2', () => {
// https://github.com/microsoft/vscode/issues/63388
const model = createTextModel([
'switch (something) {',
' case 1:',
' whatever();',
' break;',
'}',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(1, 1, 5, 2));
editor.executeCommands('editor.action.indentLines', TypeOperations.indent(viewModel.cursorConfig, editor.getModel(), editor.getSelections()));
assert.strictEqual(model.getValue(), [
' switch (something) {',
' case 1:',
' whatever();',
' break;',
' }',
].join('\n'));
});
});
});
suite('Auto Indent On Paste - TypeScript/JavaScript', () => {
const languageId = 'ts-test';
@ -625,8 +708,8 @@ suite('Auto Indent On Paste - TypeScript/JavaScript', () => {
autoIndentOnPasteController.trigger(new Range(1, 1, 4, 2));
assert.strictEqual(model.getValue(), [
'function makeSub(a,b) {',
' subsent = sent.substring(a,b);',
' return subsent;',
'subsent = sent.substring(a,b);',
'return subsent;',
'}',
].join('\n'));
});
@ -1136,11 +1219,83 @@ suite('Auto Indent On Type - TypeScript/JavaScript', () => {
});
});
// Add tests for:
// https://github.com/microsoft/vscode/issues/88638
// https://github.com/microsoft/vscode/issues/63388
// https://github.com/microsoft/vscode/issues/46401
// https://github.com/microsoft/vscode/issues/174044
test.skip('issue #67678: indent on typing curly brace', () => {
// https://github.com/microsoft/vscode/issues/67678
const model = createTextModel([
'if (true) {',
'console.log("a")',
'console.log("b")',
'',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(4, 1, 4, 1));
viewModel.type("}", 'keyboard');
assert.strictEqual(model.getValue(), [
'if (true) {',
' console.log("a")',
' console.log("b")',
'}',
].join('\n'));
});
});
test.skip('issue #46401: outdent when encountering bracket on line - allman style indentation', () => {
// https://github.com/microsoft/vscode/issues/46401
const model = createTextModel([
'if (true)',
' ',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 5, 2, 5));
viewModel.type("{}", 'keyboard');
assert.strictEqual(model.getValue(), [
'if (true)',
'{}',
].join('\n'));
editor.setSelection(new Selection(2, 2, 2, 2));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'if (true)',
'{',
' ',
'}'
].join('\n'));
});
});
test.skip('issue #125261: typing closing brace does not keep the current indentation', () => {
// https://github.com/microsoft/vscode/issues/125261
const model = createTextModel([
'foo {',
' ',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "keep" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 5, 2, 5));
viewModel.type("}", 'keyboard');
assert.strictEqual(model.getValue(), [
'foo {',
'}',
].join('\n'));
});
});
});
suite('Auto Indent On Type - Ruby', () => {
@ -1335,4 +1490,219 @@ suite('Auto Indent On Type - CPP', () => {
].join('\n'));
});
});
test.skip('issue #118929: incorrect indent when // follows curly brace', () => {
// https://github.com/microsoft/vscode/issues/118929
const model = createTextModel([
'if (true) { // jaja',
'}',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.CPP, disposables);
editor.setSelection(new Selection(1, 20, 1, 20));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'if (true) { // jaja',
' ',
'}',
].join('\n'));
});
});
test.skip('issue #111265: auto indentation set to "none" still changes the indentation', () => {
// https://github.com/microsoft/vscode/issues/111265
const model = createTextModel([
'int func() {',
' ',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "none" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.CPP, disposables);
editor.setSelection(new Selection(2, 3, 2, 3));
viewModel.type("}", 'keyboard');
assert.strictEqual(model.getValue(), [
'int func() {',
' }',
].join('\n'));
});
});
});
suite('Auto Indent On Type - HTML', () => {
const languageId = "html-test";
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
teardown(() => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
test('temp issue because there should be at least one passing test in a suite', () => {
assert.ok(true);
});
test.skip('issue #61510: incorrect indentation after // in html file', () => {
// https://github.com/microsoft/vscode/issues/178334
const model = createTextModel([
'<pre>',
' foo //I press <Enter> at the end of this line',
'</pre>',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.HTML, disposables);
editor.setSelection(new Selection(2, 48, 2, 48));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'<pre>',
' foo //I press <Enter> at the end of this line',
' ',
'</pre>',
].join('\n'));
});
});
});
suite('Auto Indent On Type - Visual Basic', () => {
const languageId = "vb-test";
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
teardown(() => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
test('temp issue because there should be at least one passing test in a suite', () => {
assert.ok(true);
});
test.skip('issue #118932: no indentation in visual basic files', () => {
// https://github.com/microsoft/vscode/issues/118932
const model = createTextModel([
'if True then',
' Some code',
' end i',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.VB, disposables);
editor.setSelection(new Selection(3, 10, 3, 10));
viewModel.type("f", 'keyboard');
assert.strictEqual(model.getValue(), [
'if True then',
' Some code',
'end if',
].join('\n'));
});
});
});
suite('Auto Indent On Type - Latex', () => {
const languageId = "latex-test";
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
teardown(() => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
test('temp issue because there should be at least one passing test in a suite', () => {
assert.ok(true);
});
test.skip('issue #178075: no auto closing pair when indentation done', () => {
// https://github.com/microsoft/vscode/issues/178075
const model = createTextModel([
'\\begin{theorem}',
' \\end',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.Latex, disposables);
editor.setSelection(new Selection(2, 9, 2, 9));
viewModel.type("{", 'keyboard');
assert.strictEqual(model.getValue(), [
'\\begin{theorem}',
'\\end{}',
].join('\n'));
});
});
});
suite('Auto Indent On Type - Lua', () => {
const languageId = "lua-test";
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
teardown(() => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
test('temp issue because there should be at least one passing test in a suite', () => {
assert.ok(true);
});
test.skip('issue #178075: no auto closing pair when indentation done', () => {
// https://github.com/microsoft/vscode/issues/178075
const model = createTextModel([
'print("asdf function asdf")',
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.Lua, disposables);
editor.setSelection(new Selection(1, 28, 1, 28));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'print("asdf function asdf")',
''
].join('\n'));
});
});
});

View file

@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAutoClosingPair } from 'vs/editor/common/languages/languageConfiguration';
export const latexAutoClosingPairsRules: IAutoClosingPair[] = [
{ open: '\\left(', close: '\\right)' },
{ open: '\\left[', close: '\\right]' },
{ open: '\\left\\{', close: '\\right\\}' },
{ open: '\\bigl(', close: '\\bigr)' },
{ open: '\\bigl[', close: '\\bigr]' },
{ open: '\\bigl\\{', close: '\\bigr\\}' },
{ open: '\\Bigl(', close: '\\Bigr)' },
{ open: '\\Bigl[', close: '\\Bigr]' },
{ open: '\\Bigl\\{', close: '\\Bigr\\}' },
{ open: '\\biggl(', close: '\\biggr)' },
{ open: '\\biggl[', close: '\\biggr]' },
{ open: '\\biggl\\{', close: '\\biggr\\}' },
{ open: '\\Biggl(', close: '\\Biggr)' },
{ open: '\\Biggl[', close: '\\Biggr]' },
{ open: '\\Biggl\\{', close: '\\Biggr\\}' },
{ open: '\\(', close: '\\)' },
{ open: '\\[', close: '\\]' },
{ open: '\\{', close: '\\}' },
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '`', close: '\'' },
];

View file

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CharacterPair } from 'vs/editor/common/languages/languageConfiguration';
const standardBracketRules: CharacterPair[] = [
['{', '}'],
['[', ']'],
['(', ')']
];
export const rubyBracketRules = standardBracketRules;
export const cppBracketRules = standardBracketRules;
export const goBracketRules = standardBracketRules;
export const phpBracketRules = standardBracketRules;
export const vbBracketRules = standardBracketRules;
export const luaBracketRules = standardBracketRules;
export const htmlBracketRules: CharacterPair[] = [
['<!--', '-->'],
['{', '}'],
['(', ')']
];
export const typescriptBracketRules: CharacterPair[] = [
['${', '}'],
['{', '}'],
['[', ']'],
['(', ')']
];
export const latexBracketRules: CharacterPair[] = [
['{', '}'],
['[', ']'],
['(', ')'],
['[', ')'],
['(', ']'],
['\\left(', '\\right)'],
['\\left(', '\\right.'],
['\\left.', '\\right)'],
['\\left[', '\\right]'],
['\\left[', '\\right.'],
['\\left.', '\\right]'],
['\\left\\{', '\\right\\}'],
['\\left\\{', '\\right.'],
['\\left.', '\\right\\}'],
['\\left<', '\\right>'],
['\\bigl(', '\\bigr)'],
['\\bigl[', '\\bigr]'],
['\\bigl\\{', '\\bigr\\}'],
['\\Bigl(', '\\Bigr)'],
['\\Bigl[', '\\Bigr]'],
['\\Bigl\\{', '\\Bigr\\}'],
['\\biggl(', '\\biggr)'],
['\\biggl[', '\\biggr]'],
['\\biggl\\{', '\\biggr\\}'],
['\\Biggl(', '\\Biggr)'],
['\\Biggl[', '\\Biggr]'],
['\\Biggl\\{', '\\Biggr\\}'],
['\\langle', '\\rangle'],
['\\lvert', '\\rvert'],
['\\lVert', '\\rVert'],
['\\left|', '\\right|'],
['\\left\\vert', '\\right\\vert'],
['\\left\\|', '\\right\\|'],
['\\left\\Vert', '\\right\\Vert'],
['\\left\\langle', '\\right\\rangle'],
['\\left\\lvert', '\\right\\rvert'],
['\\left\\lVert', '\\right\\rVert'],
['\\bigl\\langle', '\\bigr\\rangle'],
['\\bigl|', '\\bigr|'],
['\\bigl\\vert', '\\bigr\\vert'],
['\\bigl\\lvert', '\\bigr\\rvert'],
['\\bigl\\|', '\\bigr\\|'],
['\\bigl\\lVert', '\\bigr\\rVert'],
['\\bigl\\Vert', '\\bigr\\Vert'],
['\\Bigl\\langle', '\\Bigr\\rangle'],
['\\Bigl|', '\\Bigr|'],
['\\Bigl\\lvert', '\\Bigr\\rvert'],
['\\Bigl\\vert', '\\Bigr\\vert'],
['\\Bigl\\|', '\\Bigr\\|'],
['\\Bigl\\lVert', '\\Bigr\\rVert'],
['\\Bigl\\Vert', '\\Bigr\\Vert'],
['\\biggl\\langle', '\\biggr\\rangle'],
['\\biggl|', '\\biggr|'],
['\\biggl\\lvert', '\\biggr\\rvert'],
['\\biggl\\vert', '\\biggr\\vert'],
['\\biggl\\|', '\\biggr\\|'],
['\\biggl\\lVert', '\\biggr\\rVert'],
['\\biggl\\Vert', '\\biggr\\Vert'],
['\\Biggl\\langle', '\\Biggr\\rangle'],
['\\Biggl|', '\\Biggr|'],
['\\Biggl\\lvert', '\\Biggr\\rvert'],
['\\Biggl\\vert', '\\Biggr\\vert'],
['\\Biggl\\|', '\\Biggr\\|'],
['\\Biggl\\lVert', '\\Biggr\\rVert'],
['\\Biggl\\Vert', '\\Biggr\\Vert']
];

View file

@ -25,3 +25,18 @@ export const goIndentationRules = {
decreaseIndentPattern: /^\s*(\bcase\b.*:|\bdefault\b:|}[)}]*[),]?|\)[,]?)$/,
increaseIndentPattern: /^.*(\bcase\b.*:|\bdefault\b:|(\b(func|if|else|switch|select|for|struct)\b.*)?{[^}"'`]*|\([^)"'`]*)$/,
};
export const htmlIndentationRules = {
decreaseIndentPattern: /^\s*(<\/(?!html)[-_\.A-Za-z0-9]+\b[^>]*>|-->|\})/,
increaseIndentPattern: /<(?!\?|(?:area|base|br|col|frame|hr|html|img|input|keygen|link|menuitem|meta|param|source|track|wbr)\b|[^>]*\/>)([-_\.A-Za-z0-9]+)(?=\s|>)\b[^>]*>(?!.*<\/\1>)|<!--(?!.*-->)|\{[^}"']*$/,
};
export const latexIndentationRules = {
decreaseIndentPattern: /^\s*\\end{(?!document)/,
increaseIndentPattern: /\\begin{(?!document)([^}]*)}(?!.*\\end{\1})/,
};
export const luaIndentationRules = {
decreaseIndentPattern: /^\s*((\b(elseif|else|end|until)\b)|(\})|(\)))/,
increaseIndentPattern: /^((?!(\-\-)).)*((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).)*)|(\{\s*))$/,
};

View file

@ -116,6 +116,22 @@ export const cppOnEnterRules = [
}
];
export const htmlOnEnterRules = [
{
beforeText: /<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\w][_:\w-.\d]*)(?:(?:[^'"/>]|"[^"]*"|'[^']*')*?(?!\/)>)[^<]*$/i,
afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>/i,
action: {
indentAction: IndentAction.IndentOutdent
}
},
{
beforeText: /<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\w][_:\w-.\d]*)(?:(?:[^'"/>]|"[^"]*"|'[^']*')*?(?!\/)>)[^<]*$/i,
action: {
indentAction: IndentAction.Indent
}
}
];
/*
export enum IndentAction {
None = 0,