adding indentation tests for different languages

This commit is contained in:
Aiday Marlen Kyzy 2024-03-22 16:02:54 +01:00
parent e763a3dea3
commit 1f8b9deafa
No known key found for this signature in database
GPG key ID: 24A8B53DBD26FF4E
7 changed files with 211 additions and 68 deletions

View file

@ -18,12 +18,13 @@ 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 { javascriptIndentationRules } from 'vs/editor/test/common/modes/supports/javascriptIndentationRules';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { javascriptIndentationRules, phpIndentationRules, rubyIndentationRules } from 'vs/editor/test/common/modes/supports/indentationRules';
import { javascriptOnEnterRules, phpOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
enum Language {
TypeScript,
Ruby
Ruby,
PHP
}
function testIndentationToSpacesCommand(lines: string[], selection: Selection, tabSize: number, expectedLines: string[], expectedSelection: Selection): void {
@ -66,10 +67,18 @@ function registerLanguageConfiguration(instantiationService: TestInstantiationSe
['[', ']'],
['(', ')']
],
indentationRules: {
decreaseIndentPattern: /^\s*([}\]]([,)]?\s*(#|$)|\.[a-zA-Z_]\w*\b)|(end|rescue|ensure|else|elsif)\b|(in|when)\s)/,
increaseIndentPattern: /^\s*((begin|class|(private|protected)\s+def|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|in|while|case)|([^#]*\sdo\b)|([^#]*=\s*(case|if|unless)))\b([^#\{;]|(\"|'|\/).*\4)*(#.*)?$/,
},
indentationRules: rubyIndentationRules,
}));
break;
case Language.PHP:
disposables.add(languageConfigurationService.register(languageId, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
indentationRules: phpIndentationRules,
onEnterRules: phpOnEnterRules
}));
break;
}
@ -606,6 +615,66 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
});
});
test('issue #43244: indent when lambda arrow function is detected, outdent when end is reached', () => {
// https://github.com/microsoft/vscode/issues/43244
const model = createTextModel([
'const array = [1, 2, 3, 4, 5];',
'array.map(_)'
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 12, 2, 12));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'const array = [1, 2, 3, 4, 5];',
'array.map(_',
' ',
')'
].join('\n'));
});
});
test('issue #43244: incorrect indentation after if/for/while without braces', () => {
// https://github.com/microsoft/vscode/issues/43244
const model = createTextModel([
'function f() {',
' if (condition)',
'}'
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 19, 2, 19));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'function f() {',
' if (condition)',
' ',
'}',
].join('\n'));
viewModel.type("return;");
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'function f() {',
' if (condition)',
' return;',
' ',
'}',
].join('\n'));
});
});
// Failing tests...
test.skip('issue #40115: keep indentation when added', () => {
// https://github.com/microsoft/vscode/issues/40115
@ -663,41 +732,6 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
});
});
test('issue #43244: incorrect indentation after if/for/while without braces', () => {
// https://github.com/microsoft/vscode/issues/43244
const model = createTextModel([
'function f() {',
' if (condition)',
'}'
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 19, 2, 19));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'function f() {',
' if (condition)',
' ',
'}',
].join('\n'));
viewModel.type("return;");
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'function f() {',
' if (condition)',
' return;',
' ',
'}',
].join('\n'));
});
});
test.skip('issue #208232: incorrect indentation inside of comments', () => {
// https://github.com/microsoft/vscode/issues/208232
@ -871,28 +905,6 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
});
});
test('issue #43244: indent when lambda arrow function is detected, outdent when end is reached', () => {
// https://github.com/microsoft/vscode/issues/43244
const model = createTextModel([
'const array = [1, 2, 3, 4, 5];',
'array.map(_)'
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 12, 2, 12));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'const array = [1, 2, 3, 4, 5];',
'array.map(_',
' ',
')'
].join('\n'));
});
});
// Add tests for:
// https://github.com/microsoft/vscode/issues/88638
@ -918,6 +930,8 @@ suite('Auto Indent On Type - Ruby', () => {
test('issue #198350: in or when incorrectly match non keywords for Ruby', () => {
// https://github.com/microsoft/vscode/issues/198350
const model = createTextModel("", languageId, {});
disposables.add(model);
@ -938,4 +952,66 @@ suite('Auto Indent On Type - Ruby', () => {
assert.strictEqual(model.getValue(), " # in ");
});
});
// Failing tests...
test.skip('issue #199846: in or when incorrectly match non keywords for Ruby', () => {
// https://github.com/microsoft/vscode/issues/199846
// explanation: happening because the # is detected probably as a comment
const model = createTextModel("", languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.Ruby, disposables);
viewModel.type("method('#foo') do");
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
"method('#foo') do",
" "
].join('\n'));
});
});
});
suite('Auto Indent On Type - PHP', () => {
const languageId = "php-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 #199050: should not indent after { detected in a string', () => {
// https://github.com/microsoft/vscode/issues/199050
const model = createTextModel("$phrase = preg_replace('#(\{1|%s).*#su', '', $phrase);", languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.PHP, disposables);
editor.setSelection(new Selection(1, 54, 1, 54));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
"$phrase = preg_replace('#(\{1|%s).*#su', '', $phrase);",
""
].join('\n'));
});
});
});

View file

@ -16,7 +16,7 @@ import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bro
import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/browser/smartSelect';
import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/browser/wordSelections';
import { createModelServices } from 'vs/editor/test/common/testTextModel';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
import { ILanguageSelection, ILanguageService } from 'vs/editor/common/languages/language';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';

View file

@ -14,7 +14,7 @@ import { Selection } from 'vs/editor/common/core/selection';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { getEditOperation, testCommand } from 'vs/editor/test/browser/testCommand';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
import { withEditorModel } from 'vs/editor/test/common/testTextModel';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';

View file

@ -26,7 +26,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { OutgoingViewModelEventKind } from 'vs/editor/common/viewModelEventDispatcher';
import { ITestCodeEditor, TestCodeEditorInstantiationOptions, createCodeEditorServices, instantiateTestCodeEditor, withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { IRelaxedTextModelCreationOptions, createTextModel, instantiateTextModel } from 'vs/editor/test/common/testTextModel';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';

View file

@ -10,3 +10,15 @@ export const javascriptIndentationRules = {
unIndentedLinePattern: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$|^(\t|[ ])*[ ]\*\/\s*$|^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/,
indentNextLinePattern: /^((.*=>\s*)|((.*[^\w]+|\s*)(if|while|for)\s*\(.*\)\s*))$/,
};
export const rubyIndentationRules = {
decreaseIndentPattern: /^\s*([}\]]([,)]?\s*(#|$)|\.[a-zA-Z_]\w*\b)|(end|rescue|ensure|else|elsif)\b|(in|when)\s)/,
increaseIndentPattern: /^\s*((begin|class|(private|protected)\s+def|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|in|while|case)|([^#]*\sdo\b)|([^#]*=\s*(case|if|unless)))\b([^#\{;]|(\"|'|\/).*\4)*(#.*)?$/,
};
export const phpIndentationRules = {
increaseIndentPattern: /({(?!.*}).*|\(|\[|((else(\s)?)?if|else|for(each)?|while|switch|case).*:)\s*((\/[/*].*|)?$|\?>)/,
decreaseIndentPattern: /^(.*\*\/)?\s*((\})|(\)+[;,])|(\]\)*[;,])|\b(else:)|\b((end(if|for(each)?|while|switch));))/,
};

View file

@ -5,7 +5,7 @@
import * as assert from 'assert';
import { CharacterPair, IndentAction } from 'vs/editor/common/languages/languageConfiguration';
import { OnEnterSupport } from 'vs/editor/common/languages/supports/onEnter';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/onEnterRules';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';

View file

@ -59,3 +59,58 @@ export const javascriptOnEnterRules = [
action: { indentAction: IndentAction.IndentOutdent, appendText: '\t' }
},
];
export const phpOnEnterRules = [
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: {
indentAction: IndentAction.IndentOutdent,
appendText: ' * ',
}
},
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: {
indentAction: IndentAction.None,
appendText: ' * ',
}
},
{
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: {
indentAction: IndentAction.None,
appendText: '* ',
}
},
{
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: {
indentAction: IndentAction.None,
removeText: 1,
}
},
{
beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/,
action: {
indentAction: IndentAction.None,
removeText: 1,
}
},
{
beforeText: /^\s+([^{i\s]|i(?!f\b))/,
previousLineText: /^\s*(((else ?)?if|for(each)?|while)\s*\(.*\)\s*|else\s*)$/,
action: {
indentAction: IndentAction.Outdent
}
},
];
/** Note
export enum IndentAction {
None = 0,
Indent = 1,
IndentOutdent = 2,
Outdent = 3
}
*/