2021-05-31 03:30:58 +03:00
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
|
|
|
const TreeSitterGrammar = require('../src/tree-sitter-grammar');
|
|
|
|
const TreeSitterLanguageMode = require('../src/tree-sitter-language-mode');
|
|
|
|
const TreeIndenter = require('../src/tree-indenter');
|
|
|
|
|
|
|
|
const jsGrammarPath = require.resolve(
|
|
|
|
'language-javascript/grammars/tree-sitter-javascript.cson'
|
|
|
|
);
|
|
|
|
|
|
|
|
const TAB_LENGTH = 2;
|
|
|
|
|
|
|
|
const jsScopes = {
|
|
|
|
indent: {
|
|
|
|
array: true,
|
|
|
|
object: true,
|
|
|
|
arguments: true,
|
|
|
|
statement_block: true,
|
|
|
|
class_body: true,
|
|
|
|
parenthesized_expression: true,
|
|
|
|
jsx_element: true,
|
|
|
|
jsx_opening_element: true,
|
|
|
|
jsx_expression: true,
|
|
|
|
switch_body: true,
|
|
|
|
comment: true
|
|
|
|
},
|
|
|
|
indentExceptFirst: {
|
|
|
|
member_expression: true,
|
|
|
|
assignment_expression: true,
|
|
|
|
expression_statement: true,
|
|
|
|
variable_declarator: true,
|
|
|
|
lexical_declaration: true,
|
|
|
|
binary_expression: true,
|
|
|
|
jsx_self_closing_element: true
|
|
|
|
},
|
|
|
|
indentExceptFirstOrBlock: {
|
|
|
|
if_statement: true,
|
|
|
|
while_statement: true
|
|
|
|
},
|
|
|
|
types: {
|
|
|
|
indent: {},
|
|
|
|
outdent: {
|
|
|
|
else: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('TreeIndenter', () => {
|
|
|
|
let editor, buffer, grammar;
|
|
|
|
let languageMode, treeIndenter;
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
editor = await atom.workspace.open('');
|
|
|
|
buffer = editor.getBuffer();
|
|
|
|
editor.displayLayer.reset({ foldCharacter: '…' });
|
|
|
|
|
|
|
|
grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
|
|
|
|
parser: 'tree-sitter-javascript'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
/** load a file from disk and verify that our proposed indentation
|
|
|
|
is the same as it is in the file */
|
|
|
|
function compareFile(filename) {
|
|
|
|
const text = fs.readFileSync(filename);
|
|
|
|
buffer.setText(text);
|
|
|
|
languageMode = new TreeSitterLanguageMode({ buffer, grammar });
|
|
|
|
treeIndenter = new TreeIndenter(languageMode, jsScopes);
|
|
|
|
|
|
|
|
for (let row = 0; row < buffer.getLineCount(); row++) {
|
|
|
|
// get current (correct) indentation
|
|
|
|
const line = buffer.lineForRow(row);
|
|
|
|
const currentIndentation = languageMode.indentLevelForLine(
|
|
|
|
line,
|
|
|
|
TAB_LENGTH
|
|
|
|
);
|
|
|
|
|
|
|
|
// get suggested indentation
|
|
|
|
const indent = treeIndenter.suggestedIndentForBufferRow(
|
|
|
|
row,
|
|
|
|
TAB_LENGTH,
|
|
|
|
{}
|
|
|
|
);
|
|
|
|
|
|
|
|
// verify
|
|
|
|
if (indent !== currentIndentation) {
|
|
|
|
throw Error(
|
|
|
|
`failure in file row ${row +
|
|
|
|
1}: suggested ${indent} but ${currentIndentation} is correct (${line})`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
expect(indent).toEqual(currentIndentation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('indentation', () => {
|
|
|
|
it('indents wrongly indented lines', () => {
|
|
|
|
buffer.setText(`if (true) {
|
|
|
|
a = {a: [
|
|
|
|
1,
|
|
|
|
'something'
|
|
|
|
],
|
|
|
|
b: 2}
|
|
|
|
}`);
|
|
|
|
const correct = [0, 1, 3, 3, 2, 2, 0];
|
|
|
|
languageMode = new TreeSitterLanguageMode({ buffer, grammar });
|
|
|
|
treeIndenter = new TreeIndenter(languageMode, jsScopes);
|
|
|
|
|
|
|
|
for (let row = 0; row < buffer.getLineCount(); row++) {
|
|
|
|
// get suggested indentation
|
|
|
|
const indent = treeIndenter.suggestedIndentForBufferRow(
|
|
|
|
row,
|
|
|
|
TAB_LENGTH,
|
|
|
|
{}
|
|
|
|
);
|
|
|
|
|
|
|
|
// verify
|
|
|
|
if (indent !== correct[row]) {
|
|
|
|
const line = buffer.lineForRow(row).trim();
|
|
|
|
throw Error(
|
|
|
|
`failure in row ${row}: suggested ${indent} but ${
|
|
|
|
correct[row]
|
|
|
|
} is correct (${line})`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
expect(indent).toEqual(correct[row]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const fixtures = fs.readdirSync(
|
|
|
|
path.join(__dirname, 'fixtures', 'indentation')
|
|
|
|
);
|
|
|
|
|
|
|
|
fixtures.forEach(filename => {
|
2022-09-25 10:15:10 +03:00
|
|
|
/**
|
|
|
|
* TODO: FAILING TEST - This test fails with the following output:
|
|
|
|
* it suggests correct indentations for if_then_else.js
|
|
|
|
* Error: failure in file row 5: suggested 1 but 0 is correct (else)
|
|
|
|
*/
|
|
|
|
xit(`suggests correct indentations for ${filename}`, () => {
|
2021-05-31 03:30:58 +03:00
|
|
|
compareFile(path.join(__dirname, 'fixtures', 'indentation', filename));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|