pulsar/spec/tree-indenter-spec.js
2022-09-25 00:15:10 -07:00

148 lines
3.9 KiB
JavaScript

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 => {
/**
* 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}`, () => {
compareFile(path.join(__dirname, 'fixtures', 'indentation', filename));
});
});
});
});