2019-04-26 17:28:15 -07:00
|
|
|
const {assert} = require('chai');
|
2024-03-09 01:28:35 -05:00
|
|
|
let Parser; let JavaScript; let HTML; let languageURL;
|
2019-04-25 17:27:24 -07:00
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
describe('Parser', () => {
|
2019-04-25 17:27:24 -07:00
|
|
|
let parser;
|
|
|
|
|
|
2019-04-26 17:28:15 -07:00
|
|
|
before(async () =>
|
2024-03-09 01:28:35 -05:00
|
|
|
({Parser, JavaScript, HTML, languageURL} = await require('./helper')),
|
2019-04-26 17:28:15 -07:00
|
|
|
);
|
|
|
|
|
|
2019-04-25 17:27:24 -07:00
|
|
|
beforeEach(() => {
|
|
|
|
|
parser = new Parser();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
2024-02-07 11:32:27 -05:00
|
|
|
parser.delete();
|
2019-04-25 17:27:24 -07:00
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
describe('.setLanguage', () => {
|
|
|
|
|
it('allows setting the language to null', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.equal(parser.getLanguage(), null);
|
|
|
|
|
parser.setLanguage(JavaScript);
|
|
|
|
|
assert.equal(parser.getLanguage(), JavaScript);
|
|
|
|
|
parser.setLanguage(null);
|
|
|
|
|
assert.equal(parser.getLanguage(), null);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('throws an exception when the given object is not a tree-sitter language', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.throws(() => parser.setLanguage({}), /Argument must be a Language/);
|
|
|
|
|
assert.throws(() => parser.setLanguage(1), /Argument must be a Language/);
|
|
|
|
|
});
|
2019-04-25 17:27:24 -07:00
|
|
|
});
|
2019-04-26 17:28:15 -07:00
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
describe('.setLogger', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
beforeEach(() => {
|
2024-02-07 11:32:27 -05:00
|
|
|
parser.setLanguage(JavaScript);
|
2019-04-26 17:28:15 -07:00
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('calls the given callback for each parse event', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
const debugMessages = [];
|
|
|
|
|
parser.setLogger((message) => debugMessages.push(message));
|
2024-02-07 11:32:27 -05:00
|
|
|
parser.parse('a + b + c');
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.includeMembers(debugMessages, [
|
2024-02-07 11:32:27 -05:00
|
|
|
'skip character:\' \'',
|
|
|
|
|
'consume character:\'b\'',
|
|
|
|
|
'reduce sym:program, child_count:1',
|
|
|
|
|
'accept',
|
2019-04-26 17:28:15 -07:00
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('allows the callback to be retrieved later', () => {
|
|
|
|
|
const callback = () => {};
|
2019-04-26 17:28:15 -07:00
|
|
|
parser.setLogger(callback);
|
|
|
|
|
assert.equal(parser.getLogger(), callback);
|
|
|
|
|
parser.setLogger(false);
|
|
|
|
|
assert.equal(parser.getLogger(), null);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('disables debugging when given a falsy value', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
const debugMessages = [];
|
|
|
|
|
parser.setLogger((message) => debugMessages.push(message));
|
|
|
|
|
parser.setLogger(false);
|
2024-02-07 11:32:27 -05:00
|
|
|
parser.parse('a + b * c');
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.equal(debugMessages.length, 0);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('throws an error when given a truthy value that isn\'t a function ', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.throws(
|
2024-02-07 11:32:27 -05:00
|
|
|
() => parser.setLogger('5'),
|
|
|
|
|
'Logger callback must be a function',
|
2019-04-26 17:28:15 -07:00
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('rethrows errors thrown by the logging callback', () => {
|
|
|
|
|
const error = new Error('The error message');
|
2024-03-09 01:28:35 -05:00
|
|
|
parser.setLogger((_msg, _params) => {
|
2024-02-07 11:32:27 -05:00
|
|
|
throw error;
|
|
|
|
|
});
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.throws(
|
2024-02-07 11:32:27 -05:00
|
|
|
() => parser.parse('ok;'),
|
|
|
|
|
'The error message',
|
2019-04-26 17:28:15 -07:00
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2024-03-11 23:12:06 -04:00
|
|
|
describe('one included range', () => {
|
|
|
|
|
it('parses the text within a range', () => {
|
|
|
|
|
parser.setLanguage(HTML);
|
|
|
|
|
const sourceCode = '<span>hi</span><script>console.log(\'sup\');</script>';
|
|
|
|
|
const htmlTree = parser.parse(sourceCode);
|
|
|
|
|
const scriptContentNode = htmlTree.rootNode.child(1).child(1);
|
|
|
|
|
assert.equal(scriptContentNode.type, 'raw_text');
|
|
|
|
|
|
|
|
|
|
parser.setLanguage(JavaScript);
|
|
|
|
|
assert.deepEqual(parser.getIncludedRanges(), [{
|
|
|
|
|
startIndex: 0,
|
|
|
|
|
endIndex: 2147483647,
|
|
|
|
|
startPosition: {row: 0, column: 0},
|
|
|
|
|
endPosition: {row: 4294967295, column: 2147483647},
|
|
|
|
|
}]);
|
|
|
|
|
const ranges = [{
|
|
|
|
|
startIndex: scriptContentNode.startIndex,
|
|
|
|
|
endIndex: scriptContentNode.endIndex,
|
|
|
|
|
startPosition: scriptContentNode.startPosition,
|
|
|
|
|
endPosition: scriptContentNode.endPosition,
|
|
|
|
|
}];
|
|
|
|
|
const jsTree = parser.parse(
|
|
|
|
|
sourceCode,
|
|
|
|
|
null,
|
|
|
|
|
{includedRanges: ranges},
|
|
|
|
|
);
|
|
|
|
|
assert.deepEqual(parser.getIncludedRanges(), ranges);
|
|
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
|
jsTree.rootNode.toString(),
|
|
|
|
|
'(program (expression_statement (call_expression ' +
|
|
|
|
|
'function: (member_expression object: (identifier) property: (property_identifier)) ' +
|
|
|
|
|
'arguments: (arguments (string (string_fragment))))))',
|
|
|
|
|
);
|
|
|
|
|
assert.deepEqual(jsTree.rootNode.startPosition, {row: 0, column: sourceCode.indexOf('console')});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2024-03-09 01:28:35 -05:00
|
|
|
describe('multiple included ranges', () => {
|
|
|
|
|
it('parses the text within multiple ranges', () => {
|
|
|
|
|
parser.setLanguage(JavaScript);
|
|
|
|
|
const sourceCode = 'html `<div>Hello, ${name.toUpperCase()}, it\'s <b>${now()}</b>.</div>`';
|
|
|
|
|
const jsTree = parser.parse(sourceCode);
|
|
|
|
|
const templateStringNode = jsTree.rootNode.descendantForIndex(sourceCode.indexOf('`<'), sourceCode.indexOf('>`'));
|
|
|
|
|
assert.equal(templateStringNode.type, 'template_string');
|
|
|
|
|
|
|
|
|
|
const openQuoteNode = templateStringNode.child(0);
|
|
|
|
|
const interpolationNode1 = templateStringNode.child(2);
|
|
|
|
|
const interpolationNode2 = templateStringNode.child(4);
|
|
|
|
|
const closeQuoteNode = templateStringNode.child(6);
|
|
|
|
|
|
|
|
|
|
parser.setLanguage(HTML);
|
|
|
|
|
const htmlRanges = [
|
|
|
|
|
{
|
|
|
|
|
startIndex: openQuoteNode.endIndex,
|
|
|
|
|
startPosition: openQuoteNode.endPosition,
|
|
|
|
|
endIndex: interpolationNode1.startIndex,
|
|
|
|
|
endPosition: interpolationNode1.startPosition,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
startIndex: interpolationNode1.endIndex,
|
|
|
|
|
startPosition: interpolationNode1.endPosition,
|
|
|
|
|
endIndex: interpolationNode2.startIndex,
|
|
|
|
|
endPosition: interpolationNode2.startPosition,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
startIndex: interpolationNode2.endIndex,
|
|
|
|
|
startPosition: interpolationNode2.endPosition,
|
|
|
|
|
endIndex: closeQuoteNode.startIndex,
|
|
|
|
|
endPosition: closeQuoteNode.startPosition,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
const htmlTree = parser.parse(sourceCode, null, {includedRanges: htmlRanges});
|
|
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
|
htmlTree.rootNode.toString(),
|
|
|
|
|
'(document (element' +
|
|
|
|
|
' (start_tag (tag_name))' +
|
|
|
|
|
' (text)' +
|
|
|
|
|
' (element (start_tag (tag_name)) (end_tag (tag_name)))' +
|
|
|
|
|
' (text)' +
|
|
|
|
|
' (end_tag (tag_name))))',
|
|
|
|
|
);
|
|
|
|
|
assert.deepEqual(htmlTree.getIncludedRanges(), htmlRanges);
|
|
|
|
|
|
|
|
|
|
const divElementNode = htmlTree.rootNode.child(0);
|
|
|
|
|
const helloTextNode = divElementNode.child(1);
|
|
|
|
|
const bElementNode = divElementNode.child(2);
|
|
|
|
|
const bStartTagNode = bElementNode.child(0);
|
|
|
|
|
const bEndTagNode = bElementNode.child(1);
|
|
|
|
|
|
|
|
|
|
assert.equal(helloTextNode.type, 'text');
|
|
|
|
|
assert.equal(helloTextNode.startIndex, sourceCode.indexOf('Hello'));
|
|
|
|
|
assert.equal(helloTextNode.endIndex, sourceCode.indexOf(' <b>'));
|
|
|
|
|
|
|
|
|
|
assert.equal(bStartTagNode.type, 'start_tag');
|
|
|
|
|
assert.equal(bStartTagNode.startIndex, sourceCode.indexOf('<b>'));
|
|
|
|
|
assert.equal(bStartTagNode.endIndex, sourceCode.indexOf('${now()}'));
|
|
|
|
|
|
|
|
|
|
assert.equal(bEndTagNode.type, 'end_tag');
|
|
|
|
|
assert.equal(bEndTagNode.startIndex, sourceCode.indexOf('</b>'));
|
|
|
|
|
assert.equal(bEndTagNode.endIndex, sourceCode.indexOf('.</div>'));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('an included range containing mismatched positions', () => {
|
|
|
|
|
it('parses the text within the range', () => {
|
|
|
|
|
const sourceCode = '<div>test</div>{_ignore_this_part_}';
|
|
|
|
|
|
|
|
|
|
parser.setLanguage(HTML);
|
|
|
|
|
|
|
|
|
|
const endIndex = sourceCode.indexOf('{_ignore_this_part_');
|
|
|
|
|
|
|
|
|
|
const rangeToParse = {
|
|
|
|
|
startIndex: 0,
|
|
|
|
|
startPosition: {row: 10, column: 12},
|
|
|
|
|
endIndex,
|
|
|
|
|
endPosition: {row: 10, column: 12 + endIndex},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const htmlTree = parser.parse(sourceCode, null, {includedRanges: [rangeToParse]});
|
|
|
|
|
|
|
|
|
|
assert.deepEqual(htmlTree.getIncludedRanges()[0], rangeToParse);
|
|
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
|
htmlTree.rootNode.toString(),
|
|
|
|
|
'(document (element (start_tag (tag_name)) (text) (end_tag (tag_name))))',
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
describe('.parse', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
let tree;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
tree = null;
|
2024-02-07 11:32:27 -05:00
|
|
|
parser.setLanguage(JavaScript);
|
2019-04-26 17:28:15 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
if (tree) tree.delete();
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('reads from the given input', () => {
|
|
|
|
|
const parts = ['first', '_', 'second', '_', 'third'];
|
2019-04-26 17:28:15 -07:00
|
|
|
tree = parser.parse(() => parts.shift());
|
2024-02-07 11:32:27 -05:00
|
|
|
assert.equal(tree.rootNode.toString(), '(program (expression_statement (identifier)))');
|
2019-04-26 17:28:15 -07:00
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('stops reading when the input callback return something that\'s not a string', () => {
|
|
|
|
|
const parts = ['abc', 'def', 'ghi', {}, {}, {}, 'second-word', ' '];
|
2019-04-26 17:28:15 -07:00
|
|
|
tree = parser.parse(() => parts.shift());
|
|
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2024-02-07 11:32:27 -05:00
|
|
|
'(program (expression_statement (identifier)))',
|
2019-04-26 17:28:15 -07:00
|
|
|
);
|
|
|
|
|
assert.equal(tree.rootNode.endIndex, 9);
|
|
|
|
|
assert.equal(parts.length, 2);
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('throws an exception when the given input is not a function', () => {
|
|
|
|
|
assert.throws(() => parser.parse(null), 'Argument must be a string or a function');
|
|
|
|
|
assert.throws(() => parser.parse(5), 'Argument must be a string or a function');
|
|
|
|
|
assert.throws(() => parser.parse({}), 'Argument must be a string or a function');
|
2019-04-26 17:28:15 -07:00
|
|
|
});
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('handles long input strings', () => {
|
2019-04-26 17:28:15 -07:00
|
|
|
const repeatCount = 10000;
|
2024-04-09 21:44:37 -04:00
|
|
|
const inputString = `[${Array(repeatCount).fill('0').join(',')}]`;
|
2019-04-26 17:28:15 -07:00
|
|
|
|
|
|
|
|
tree = parser.parse(inputString);
|
2024-02-07 11:32:27 -05:00
|
|
|
assert.equal(tree.rootNode.type, 'program');
|
2019-04-26 17:28:15 -07:00
|
|
|
assert.equal(tree.rootNode.firstChild.firstChild.namedChildCount, repeatCount);
|
2019-04-23 14:46:46 -07:00
|
|
|
}).timeout(5000);
|
2019-04-26 17:28:15 -07:00
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the bash parser', async () => {
|
2019-05-01 11:29:35 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('bash')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('FOO=bar echo <<EOF 2> err.txt > hello.txt \nhello${FOO}\nEOF');
|
2019-04-27 18:06:34 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2024-02-07 11:32:27 -05:00
|
|
|
'(program ' +
|
2023-08-25 16:55:08 +03:00
|
|
|
'(redirected_statement ' +
|
|
|
|
|
'body: (command ' +
|
|
|
|
|
'(variable_assignment name: (variable_name) value: (word)) ' +
|
|
|
|
|
'name: (command_name (word))) ' +
|
|
|
|
|
'redirect: (heredoc_redirect (heredoc_start) ' +
|
|
|
|
|
'redirect: (file_redirect descriptor: (file_descriptor) destination: (word)) ' +
|
|
|
|
|
'redirect: (file_redirect destination: (word)) ' +
|
|
|
|
|
'(heredoc_body ' +
|
2024-02-07 11:32:27 -05:00
|
|
|
'(expansion (variable_name)) (heredoc_content)) (heredoc_end))))',
|
2019-04-27 18:06:34 -07:00
|
|
|
);
|
2019-05-01 11:29:35 -07:00
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the c++ parser', async () => {
|
2019-05-01 11:29:35 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('cpp')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";');
|
2019-05-01 11:29:35 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2019-07-05 12:13:38 -07:00
|
|
|
'(translation_unit (declaration ' +
|
|
|
|
|
'(type_qualifier) ' +
|
|
|
|
|
'type: (primitive_type) ' +
|
|
|
|
|
'declarator: (init_declarator ' +
|
|
|
|
|
'declarator: (pointer_declarator declarator: (identifier)) ' +
|
2024-02-07 11:32:27 -05:00
|
|
|
'value: (raw_string_literal delimiter: (raw_string_delimiter) (raw_string_content) (raw_string_delimiter)))))',
|
2019-05-01 11:29:35 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the HTML parser', async () => {
|
2019-05-01 11:29:35 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('html')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('<div><span><custom></custom></span></div>');
|
2019-05-01 11:29:35 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2024-02-19 05:42:52 -05:00
|
|
|
'(document (element (start_tag (tag_name)) (element (start_tag (tag_name)) (element (start_tag (tag_name)) (end_tag (tag_name))) (end_tag (tag_name))) (end_tag (tag_name))))',
|
2019-05-01 11:29:35 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the python parser', async () => {
|
2019-05-01 11:29:35 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('python')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('class A:\n def b():\n c()');
|
2019-05-01 11:29:35 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2019-07-22 09:34:48 -07:00
|
|
|
'(module (class_definition ' +
|
|
|
|
|
'name: (identifier) ' +
|
|
|
|
|
'body: (block ' +
|
|
|
|
|
'(function_definition ' +
|
|
|
|
|
'name: (identifier) ' +
|
|
|
|
|
'parameters: (parameters) ' +
|
|
|
|
|
'body: (block (expression_statement (call ' +
|
|
|
|
|
'function: (identifier) ' +
|
2024-02-07 11:32:27 -05:00
|
|
|
'arguments: (argument_list))))))))',
|
2019-05-01 11:29:35 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the rust parser', async () => {
|
2019-05-01 11:29:35 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('rust')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('const x: &\'static str = r###"hello"###;');
|
2019-05-01 11:29:35 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2019-10-14 16:55:14 -07:00
|
|
|
'(source_file (const_item ' +
|
|
|
|
|
'name: (identifier) ' +
|
|
|
|
|
'type: (reference_type (lifetime (identifier)) type: (primitive_type)) ' +
|
2024-04-08 12:29:16 -04:00
|
|
|
'value: (raw_string_literal (string_content))))',
|
2019-05-01 11:29:35 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
2019-04-27 18:06:34 -07:00
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the typescript parser', async () => {
|
2019-05-30 12:34:03 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('typescript')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('a()\nb()\n[c]');
|
2019-05-30 12:34:03 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2019-08-08 10:17:27 -07:00
|
|
|
'(program ' +
|
|
|
|
|
'(expression_statement (call_expression function: (identifier) arguments: (arguments))) ' +
|
|
|
|
|
'(expression_statement (subscript_expression ' +
|
|
|
|
|
'object: (call_expression ' +
|
|
|
|
|
'function: (identifier) ' +
|
|
|
|
|
'arguments: (arguments)) ' +
|
2024-02-07 11:32:27 -05:00
|
|
|
'index: (identifier))))',
|
2019-05-30 12:34:03 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2024-02-07 11:32:27 -05:00
|
|
|
it('can use the tsx parser', async () => {
|
2019-05-30 12:34:03 -07:00
|
|
|
parser.setLanguage(await Parser.Language.load(languageURL('tsx')));
|
2024-02-07 11:32:27 -05:00
|
|
|
tree = parser.parse('a()\nb()\n[c]');
|
2019-05-30 12:34:03 -07:00
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2019-08-08 10:17:27 -07:00
|
|
|
'(program ' +
|
|
|
|
|
'(expression_statement (call_expression function: (identifier) arguments: (arguments))) ' +
|
|
|
|
|
'(expression_statement (subscript_expression ' +
|
|
|
|
|
'object: (call_expression ' +
|
|
|
|
|
'function: (identifier) ' +
|
|
|
|
|
'arguments: (arguments)) ' +
|
2024-02-07 11:32:27 -05:00
|
|
|
'index: (identifier))))',
|
2019-05-30 12:34:03 -07:00
|
|
|
);
|
|
|
|
|
}).timeout(5000);
|
|
|
|
|
|
2019-04-26 17:28:15 -07:00
|
|
|
it('parses only the text within the `includedRanges` if they are specified', () => {
|
2024-02-07 11:32:27 -05:00
|
|
|
const sourceCode = '<% foo() %> <% bar %>';
|
2019-04-26 17:28:15 -07:00
|
|
|
|
|
|
|
|
const start1 = sourceCode.indexOf('foo');
|
2024-02-07 11:32:27 -05:00
|
|
|
const end1 = start1 + 5;
|
2019-04-26 17:28:15 -07:00
|
|
|
const start2 = sourceCode.indexOf('bar');
|
2024-02-07 11:32:27 -05:00
|
|
|
const end2 = start2 + 3;
|
2019-04-26 17:28:15 -07:00
|
|
|
|
|
|
|
|
const tree = parser.parse(sourceCode, null, {
|
|
|
|
|
includedRanges: [
|
|
|
|
|
{
|
|
|
|
|
startIndex: start1,
|
|
|
|
|
endIndex: end1,
|
|
|
|
|
startPosition: {row: 0, column: start1},
|
2024-02-07 11:32:27 -05:00
|
|
|
endPosition: {row: 0, column: end1},
|
2019-04-26 17:28:15 -07:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
startIndex: start2,
|
|
|
|
|
endIndex: end2,
|
|
|
|
|
startPosition: {row: 0, column: start2},
|
2024-02-07 11:32:27 -05:00
|
|
|
endPosition: {row: 0, column: end2},
|
2019-04-26 17:28:15 -07:00
|
|
|
},
|
2024-02-07 11:32:27 -05:00
|
|
|
],
|
2019-04-26 17:28:15 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
|
tree.rootNode.toString(),
|
2024-02-07 11:32:27 -05:00
|
|
|
'(program (expression_statement (call_expression function: (identifier) arguments: (arguments))) (expression_statement (identifier)))',
|
2019-04-26 17:28:15 -07:00
|
|
|
);
|
2024-02-07 11:32:27 -05:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|