feat(web)!: use the WASM module in the bindings, and not the other way around
Parser is no longer the default export, but you *must* call `Parser.init()` before doing anything still
This commit is contained in:
parent
b1e39d2dba
commit
be7716dfa7
29 changed files with 613 additions and 662 deletions
|
|
@ -1,9 +1,11 @@
|
|||
import type { default as ParserType } from 'web-tree-sitter';
|
||||
import { type Parser as ParserType, type Language as LanguageType } from '../src';
|
||||
import path from 'path';
|
||||
|
||||
// @ts-expect-error We're intentionally importing ../tree-sitter.js
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
||||
const Parser: typeof ParserType = await import('..').then(m => m.default);
|
||||
import { Parser as ParserImpl, Language as LanguageImpl } from '..';
|
||||
|
||||
const Parser = ParserImpl as typeof ParserType;
|
||||
const Language = LanguageImpl as typeof LanguageType;
|
||||
|
||||
// https://github.com/tree-sitter/tree-sitter/blob/master/xtask/src/fetch.rs#L15
|
||||
export type LanguageName = 'bash' | 'c' | 'cpp' | 'embedded-template' | 'go' | 'html' | 'java' | 'javascript' | 'jsdoc' | 'json' | 'php' | 'python' | 'ruby' | 'rust' | 'typescript' | 'tsx';
|
||||
|
|
@ -15,12 +17,13 @@ function languageURL(name: LanguageName): string {
|
|||
|
||||
export default Parser.init().then(async () => ({
|
||||
Parser,
|
||||
Language,
|
||||
languageURL,
|
||||
C: await Parser.Language.load(languageURL('c')),
|
||||
EmbeddedTemplate: await Parser.Language.load(languageURL('embedded-template')),
|
||||
HTML: await Parser.Language.load(languageURL('html')),
|
||||
JavaScript: await Parser.Language.load(languageURL('javascript')),
|
||||
JSON: await Parser.Language.load(languageURL('json')),
|
||||
Python: await Parser.Language.load(languageURL('python')),
|
||||
Rust: await Parser.Language.load(languageURL('rust')),
|
||||
C: await Language.load(languageURL('c')),
|
||||
EmbeddedTemplate: await Language.load(languageURL('embedded-template')),
|
||||
HTML: await Language.load(languageURL('html')),
|
||||
JavaScript: await Language.load(languageURL('javascript')),
|
||||
JSON: await Language.load(languageURL('json')),
|
||||
Python: await Language.load(languageURL('python')),
|
||||
Rust: await Language.load(languageURL('rust')),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import helper from './helper';
|
||||
import type { default as ParserType, LookaheadIterable, Language } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, LookaheadIterator, Language } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
let Rust: Language;
|
||||
|
||||
|
|
@ -35,8 +36,8 @@ describe('Language', () => {
|
|||
|
||||
describe('.idForNodeType, .nodeTypeForId, .nodeTypeIsNamed', () => {
|
||||
it('converts between the string and integer representations of a node type', () => {
|
||||
const exportStatementId = JavaScript.idForNodeType('export_statement', true);
|
||||
const starId = JavaScript.idForNodeType('*', false);
|
||||
const exportStatementId = JavaScript.idForNodeType('export_statement', true)!;
|
||||
const starId = JavaScript.idForNodeType('*', false)!;
|
||||
|
||||
expect(exportStatementId).toBeLessThan(JavaScript.nodeTypeCount);
|
||||
expect(starId).toBeLessThan(JavaScript.nodeTypeCount);
|
||||
|
|
@ -131,12 +132,11 @@ describe('Language', () => {
|
|||
});
|
||||
|
||||
describe('Lookahead iterator', () => {
|
||||
let lookahead: LookaheadIterable;
|
||||
let lookahead: LookaheadIterator;
|
||||
let state: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
let Parser: typeof ParserType;
|
||||
({ JavaScript, Parser } = await helper);
|
||||
({ Parser, JavaScript } = await helper);
|
||||
const parser = new Parser();
|
||||
parser.setLanguage(JavaScript);
|
||||
const tree = parser.parse('function fn() {}');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, SyntaxNode } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Language, Tree, Node } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
@ -19,8 +19,8 @@ const JSON_EXAMPLE = `
|
|||
]
|
||||
`;
|
||||
|
||||
function getAllNodes(tree: Tree): SyntaxNode[] {
|
||||
const result: SyntaxNode[] = [];
|
||||
function getAllNodes(tree: Tree): Node[] {
|
||||
const result: Node[] = [];
|
||||
let visitedChildren = false;
|
||||
const cursor = tree.walk();
|
||||
|
||||
|
|
@ -55,15 +55,15 @@ describe('Node', () => {
|
|||
|
||||
afterEach(() => {
|
||||
parser.delete();
|
||||
tree!.delete();
|
||||
tree?.delete();
|
||||
});
|
||||
|
||||
describe('.children', () => {
|
||||
it('returns an array of child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
expect(tree.rootNode.children).toHaveLength(1);
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children.map(child => child.type)).toEqual([
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children.map(child => child?.type)).toEqual([
|
||||
'identifier',
|
||||
'+',
|
||||
'number'
|
||||
|
|
@ -74,9 +74,9 @@ describe('Node', () => {
|
|||
describe('.namedChildren', () => {
|
||||
it('returns an array of named child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(tree.rootNode.namedChildren).toHaveLength(1);
|
||||
expect(sumNode!.namedChildren.map(child => child.type)).toEqual([
|
||||
expect(sumNode?.namedChildren.map(child => child?.type)).toEqual([
|
||||
'identifier',
|
||||
'number'
|
||||
]);
|
||||
|
|
@ -98,11 +98,11 @@ describe('Node', () => {
|
|||
|
||||
tree = parser.parse(source);
|
||||
const node = tree.rootNode.firstChild;
|
||||
expect(node!.type).toBe('if_statement');
|
||||
const alternatives = node!.childrenForFieldName('alternative');
|
||||
const alternativeTexts = alternatives.map(n => {
|
||||
const condition = n.childForFieldName('condition');
|
||||
return source.slice(condition!.startIndex, condition!.endIndex);
|
||||
expect(node?.type).toBe('if_statement');
|
||||
const alternatives = node?.childrenForFieldName('alternative');
|
||||
const alternativeTexts = alternatives?.map(n => {
|
||||
const condition = n?.childForFieldName('condition');
|
||||
return source.slice(condition?.startIndex, condition?.endIndex);
|
||||
});
|
||||
expect(alternativeTexts).toEqual(['two', 'three', 'four']);
|
||||
});
|
||||
|
|
@ -111,29 +111,29 @@ describe('Node', () => {
|
|||
describe('.startIndex and .endIndex', () => {
|
||||
it('returns the character index where the node starts/ends in the text', () => {
|
||||
tree = parser.parse('a👍👎1 / b👎c👎');
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(quotientNode!.startIndex).toBe(0);
|
||||
expect(quotientNode!.endIndex).toBe(15);
|
||||
expect(quotientNode!.children.map(child => child.startIndex)).toEqual([0, 7, 9]);
|
||||
expect(quotientNode!.children.map(child => child.endIndex)).toEqual([6, 8, 15]);
|
||||
expect(quotientNode?.startIndex).toBe(0);
|
||||
expect(quotientNode?.endIndex).toBe(15);
|
||||
expect(quotientNode?.children.map(child => child?.startIndex)).toEqual([0, 7, 9]);
|
||||
expect(quotientNode?.children.map(child => child?.endIndex)).toEqual([6, 8, 15]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.startPosition and .endPosition', () => {
|
||||
it('returns the row and column where the node starts/ends in the text', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild!;
|
||||
expect(sumNode.type).toBe('binary_expression');
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.type).toBe('binary_expression');
|
||||
|
||||
expect(sumNode.startPosition).toEqual({ row: 0, column: 0 });
|
||||
expect(sumNode.endPosition).toEqual({ row: 0, column: 10 });
|
||||
expect(sumNode.children.map((child) => child.startPosition)).toEqual([
|
||||
expect(sumNode?.startPosition).toEqual({ row: 0, column: 0 });
|
||||
expect(sumNode?.endPosition).toEqual({ row: 0, column: 10 });
|
||||
expect(sumNode?.children.map((child) => child?.startPosition)).toEqual([
|
||||
{ row: 0, column: 0 },
|
||||
{ row: 0, column: 4 },
|
||||
{ row: 0, column: 6 },
|
||||
]);
|
||||
expect(sumNode.children.map((child) => child.endPosition)).toEqual([
|
||||
expect(sumNode?.children.map((child) => child?.endPosition)).toEqual([
|
||||
{ row: 0, column: 3 },
|
||||
{ row: 0, column: 5 },
|
||||
{ row: 0, column: 10 },
|
||||
|
|
@ -142,8 +142,8 @@ describe('Node', () => {
|
|||
|
||||
it('handles characters that occupy two UTF16 code units', () => {
|
||||
tree = parser.parse('a👍👎1 /\n b👎c👎');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children.map(child => [child.startPosition, child.endPosition])).toEqual([
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children.map(child => [child?.startPosition, child?.endPosition])).toEqual([
|
||||
[{ row: 0, column: 0 }, { row: 0, column: 6 }],
|
||||
[{ row: 0, column: 7 }, { row: 0, column: 8 }],
|
||||
[{ row: 1, column: 1 }, { row: 1, column: 7 }]
|
||||
|
|
@ -155,23 +155,23 @@ describe('Node', () => {
|
|||
it('returns the node\'s parent', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
const variableNode = sumNode!.firstChild;
|
||||
expect(sumNode!.id).not.toBe(variableNode!.id);
|
||||
expect(sumNode!.id).toBe(variableNode!.parent!.id);
|
||||
expect(tree.rootNode.id).toBe(sumNode!.parent!.id);
|
||||
const variableNode = sumNode?.firstChild;
|
||||
expect(sumNode?.id).not.toBe(variableNode?.id);
|
||||
expect(sumNode?.id).toBe(variableNode?.parent?.id);
|
||||
expect(tree.rootNode.id).toBe(sumNode?.parent?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.child(), .firstChild, .lastChild', () => {
|
||||
it('returns null when the node has no children', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const variableNode = sumNode!.firstChild;
|
||||
expect(variableNode!.firstChild).toBeNull();
|
||||
expect(variableNode!.lastChild).toBeNull();
|
||||
expect(variableNode!.firstNamedChild).toBeNull();
|
||||
expect(variableNode!.lastNamedChild).toBeNull();
|
||||
expect(variableNode!.child(1)).toBeNull();
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const variableNode = sumNode?.firstChild;
|
||||
expect(variableNode?.firstChild).toBeNull();
|
||||
expect(variableNode?.lastChild).toBeNull();
|
||||
expect(variableNode?.firstNamedChild).toBeNull();
|
||||
expect(variableNode?.lastNamedChild).toBeNull();
|
||||
expect(variableNode?.child(1)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -180,57 +180,57 @@ describe('Node', () => {
|
|||
tree = parser.parse('class A { b() {} }');
|
||||
|
||||
const classNode = tree.rootNode.firstChild;
|
||||
expect(classNode!.type).toBe('class_declaration');
|
||||
expect(classNode?.type).toBe('class_declaration');
|
||||
|
||||
const classNameNode = classNode!.childForFieldName('name');
|
||||
expect(classNameNode!.type).toBe('identifier');
|
||||
expect(classNameNode!.text).toBe('A');
|
||||
const classNameNode = classNode?.childForFieldName('name');
|
||||
expect(classNameNode?.type).toBe('identifier');
|
||||
expect(classNameNode?.text).toBe('A');
|
||||
|
||||
const bodyNode = classNode!.childForFieldName('body');
|
||||
expect(bodyNode!.type).toBe('class_body');
|
||||
expect(bodyNode!.text).toBe('{ b() {} }');
|
||||
const bodyNode = classNode?.childForFieldName('body');
|
||||
expect(bodyNode?.type).toBe('class_body');
|
||||
expect(bodyNode?.text).toBe('{ b() {} }');
|
||||
|
||||
const methodNode = bodyNode!.firstNamedChild;
|
||||
expect(methodNode!.type).toBe('method_definition');
|
||||
expect(methodNode!.text).toBe('b() {}');
|
||||
const methodNode = bodyNode?.firstNamedChild;
|
||||
expect(methodNode?.type).toBe('method_definition');
|
||||
expect(methodNode?.text).toBe('b() {}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.nextSibling and .previousSibling', () => {
|
||||
it('returns the node\'s next and previous sibling', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children[1].id).toBe(sumNode!.children[0].nextSibling!.id);
|
||||
expect(sumNode!.children[2].id).toBe(sumNode!.children[1].nextSibling!.id);
|
||||
expect(sumNode!.children[0].id).toBe(sumNode!.children[1].previousSibling!.id);
|
||||
expect(sumNode!.children[1].id).toBe(sumNode!.children[2].previousSibling!.id);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children[1]?.id).toBe(sumNode?.children[0]?.nextSibling?.id);
|
||||
expect(sumNode?.children[2]?.id).toBe(sumNode?.children[1]?.nextSibling?.id);
|
||||
expect(sumNode?.children[0]?.id).toBe(sumNode?.children[1]?.previousSibling?.id);
|
||||
expect(sumNode?.children[1]?.id).toBe(sumNode?.children[2]?.previousSibling?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.nextNamedSibling and .previousNamedSibling', () => {
|
||||
it('returns the node\'s next and previous named sibling', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.namedChildren[1].id).toBe(sumNode!.namedChildren[0].nextNamedSibling!.id);
|
||||
expect(sumNode!.namedChildren[0].id).toBe(sumNode!.namedChildren[1].previousNamedSibling!.id);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.namedChildren[1]?.id).toBe(sumNode?.namedChildren[0]?.nextNamedSibling?.id);
|
||||
expect(sumNode?.namedChildren[0]?.id).toBe(sumNode?.namedChildren[1]?.previousNamedSibling?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.descendantForIndex(min, max)', () => {
|
||||
it('returns the smallest node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.descendantForIndex(1, 2).type).toBe('identifier');
|
||||
expect(sumNode!.descendantForIndex(4, 4).type).toBe('+');
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.descendantForIndex(1, 2)?.type).toBe('identifier');
|
||||
expect(sumNode?.descendantForIndex(4, 4)?.type).toBe('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForIndex(1, {});
|
||||
sumNode.descendantForIndex(1, {});
|
||||
}).toThrow('Arguments must be numbers');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForIndex(undefined);
|
||||
sumNode.descendantForIndex(undefined);
|
||||
}).toThrow('Arguments must be numbers');
|
||||
});
|
||||
});
|
||||
|
|
@ -238,36 +238,36 @@ describe('Node', () => {
|
|||
describe('.namedDescendantForIndex', () => {
|
||||
it('returns the smallest named node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
expect(sumNode!.descendantForIndex(1, 2).type).toBe('identifier');
|
||||
expect(sumNode!.descendantForIndex(4, 4).type).toBe('+');
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
expect(sumNode.descendantForIndex(1, 2)?.type).toBe('identifier');
|
||||
expect(sumNode.descendantForIndex(4, 4)?.type).toBe('+');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.descendantForPosition', () => {
|
||||
it('returns the smallest node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
|
||||
expect(
|
||||
sumNode!.descendantForPosition(
|
||||
sumNode.descendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 }
|
||||
).type
|
||||
)?.type
|
||||
).toBe('identifier');
|
||||
|
||||
expect(
|
||||
sumNode!.descendantForPosition({ row: 0, column: 4 }).type
|
||||
sumNode.descendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForPosition(1, {});
|
||||
sumNode.descendantForPosition(1, {});
|
||||
}).toThrow('Arguments must be {row, column} objects');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForPosition(undefined);
|
||||
sumNode.descendantForPosition(undefined);
|
||||
}).toThrow('Arguments must be {row, column} objects');
|
||||
});
|
||||
});
|
||||
|
|
@ -281,11 +281,11 @@ describe('Node', () => {
|
|||
sumNode.namedDescendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 },
|
||||
).type
|
||||
)?.type
|
||||
).toBe('identifier')
|
||||
|
||||
expect(
|
||||
sumNode.namedDescendantForPosition({ row: 0, column: 4 }).type
|
||||
sumNode.namedDescendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('binary_expression');
|
||||
});
|
||||
});
|
||||
|
|
@ -298,11 +298,11 @@ describe('Node', () => {
|
|||
'(program (expression_statement (binary_expression left: (number) right: (binary_expression left: (number) (ERROR) right: (number)))))'
|
||||
);
|
||||
|
||||
const sum = node.firstChild!.firstChild;
|
||||
expect(sum!.hasError).toBe(true);
|
||||
expect(sum!.children[0].hasError).toBe(false);
|
||||
expect(sum!.children[1].hasError).toBe(false);
|
||||
expect(sum!.children[2].hasError).toBe(true);
|
||||
const sum = node.firstChild?.firstChild;
|
||||
expect(sum?.hasError).toBe(true);
|
||||
expect(sum?.children[0]?.hasError).toBe(false);
|
||||
expect(sum?.children[1]?.hasError).toBe(false);
|
||||
expect(sum?.children[2]?.hasError).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -314,12 +314,12 @@ describe('Node', () => {
|
|||
'(program (expression_statement (binary_expression left: (number) (ERROR) right: (number))))'
|
||||
);
|
||||
|
||||
const multi = node.firstChild!.firstChild;
|
||||
expect(multi!.hasError).toBe(true);
|
||||
expect(multi!.children[0].isError).toBe(false);
|
||||
expect(multi!.children[1].isError).toBe(false);
|
||||
expect(multi!.children[2].isError).toBe(true);
|
||||
expect(multi!.children[3].isError).toBe(false);
|
||||
const multi = node.firstChild?.firstChild;
|
||||
expect(multi?.hasError).toBe(true);
|
||||
expect(multi?.children[0]?.isError).toBe(false);
|
||||
expect(multi?.children[1]?.isError).toBe(false);
|
||||
expect(multi?.children[2]?.isError).toBe(true);
|
||||
expect(multi?.children[3]?.isError).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -331,12 +331,12 @@ describe('Node', () => {
|
|||
'(program (expression_statement (parenthesized_expression (binary_expression left: (number) right: (MISSING identifier)))))'
|
||||
);
|
||||
|
||||
const sum = node.firstChild!.firstChild!.firstNamedChild;
|
||||
expect(sum!.type).toBe('binary_expression');
|
||||
expect(sum!.hasError).toBe(true);
|
||||
expect(sum!.children[0].isMissing).toBe(false);
|
||||
expect(sum!.children[1].isMissing).toBe(false);
|
||||
expect(sum!.children[2].isMissing).toBe(true);
|
||||
const sum = node.firstChild?.firstChild?.firstNamedChild;
|
||||
expect(sum?.type).toBe('binary_expression');
|
||||
expect(sum?.hasError).toBe(true);
|
||||
expect(sum?.children[0]?.isMissing).toBe(false);
|
||||
expect(sum?.children[1]?.isMissing).toBe(false);
|
||||
expect(sum?.children[2]?.isMissing).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -344,7 +344,7 @@ describe('Node', () => {
|
|||
it('returns true if the node is an extra node like comments', () => {
|
||||
tree = parser.parse('foo(/* hi */);');
|
||||
const node = tree.rootNode;
|
||||
const commentNode = node.descendantForIndex(7, 7);
|
||||
const commentNode = node.descendantForIndex(7, 7)!;
|
||||
|
||||
expect(node.type).toBe('program');
|
||||
expect(commentNode.type).toBe('comment');
|
||||
|
|
@ -363,14 +363,14 @@ describe('Node', () => {
|
|||
it(`returns the text of a node generated by ${method}`, () => {
|
||||
const [numeratorSrc, denominatorSrc] = text.split(/\s*\/\s+/);
|
||||
tree = parser.parse(_parse);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild!;
|
||||
const [numerator, slash, denominator] = quotientNode.children;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
const [numerator, slash, denominator] = quotientNode!.children;
|
||||
|
||||
expect(tree.rootNode.text).toBe(text);
|
||||
expect(denominator.text).toBe(denominatorSrc);
|
||||
expect(quotientNode.text).toBe(text);
|
||||
expect(numerator.text).toBe(numeratorSrc);
|
||||
expect(slash.text).toBe('/');
|
||||
expect(denominator?.text).toBe(denominatorSrc);
|
||||
expect(quotientNode?.text).toBe(text);
|
||||
expect(numerator?.text).toBe(numeratorSrc);
|
||||
expect(slash?.text).toBe('/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -427,12 +427,12 @@ describe('Node', () => {
|
|||
expect(node.startPosition).toEqual({ row: 2, column: 4 });
|
||||
expect(node.endPosition).toEqual({ row: 2, column: 12 });
|
||||
|
||||
let child = node.firstChild!.child(2);
|
||||
expect(child!.type).toBe('expression_statement');
|
||||
expect(child!.startIndex).toBe(15);
|
||||
expect(child!.endIndex).toBe(16);
|
||||
expect(child!.startPosition).toEqual({ row: 2, column: 11 });
|
||||
expect(child!.endPosition).toEqual({ row: 2, column: 12 });
|
||||
let child = node.firstChild?.child(2);
|
||||
expect(child?.type).toBe('expression_statement');
|
||||
expect(child?.startIndex).toBe(15);
|
||||
expect(child?.endIndex).toBe(16);
|
||||
expect(child?.startPosition).toEqual({ row: 2, column: 11 });
|
||||
expect(child?.endPosition).toEqual({ row: 2, column: 12 });
|
||||
|
||||
const cursor = node.walk();
|
||||
cursor.gotoFirstChild();
|
||||
|
|
@ -452,23 +452,23 @@ describe('Node', () => {
|
|||
|
||||
it('returns node parse state ids', () => {
|
||||
tree = parser.parse(text);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
const [numerator, slash, denominator] = quotientNode!.children;
|
||||
|
||||
expect(tree.rootNode.parseState).toBe(0);
|
||||
// parse states will change on any change to the grammar so test that it
|
||||
// returns something instead
|
||||
expect(numerator.parseState).toBeGreaterThan(0);
|
||||
expect(slash.parseState).toBeGreaterThan(0);
|
||||
expect(denominator.parseState).toBeGreaterThan(0);
|
||||
expect(numerator?.parseState).toBeGreaterThan(0);
|
||||
expect(slash?.parseState).toBeGreaterThan(0);
|
||||
expect(denominator?.parseState).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('returns next parse state equal to the language', () => {
|
||||
tree = parser.parse(text);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
quotientNode!.children.forEach((node) => {
|
||||
expect(node.nextParseState).toBe(
|
||||
JavaScript.nextState(node.parseState, node.grammarId)
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
quotientNode?.children.forEach((node) => {
|
||||
expect(node?.nextParseState).toBe(
|
||||
JavaScript.nextState(node!.parseState, node!.grammarId)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -477,11 +477,11 @@ describe('Node', () => {
|
|||
describe('.descendantsOfType', () => {
|
||||
it('finds all descendants of a given type in the given range', () => {
|
||||
tree = parser.parse('a + 1 * b * 2 + c + 3');
|
||||
const outerSum = tree.rootNode.firstChild!.firstChild;
|
||||
const outerSum = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
const descendants = outerSum!.descendantsOfType('number', { row: 0, column: 2 }, { row: 0, column: 15 });
|
||||
expect(descendants.map(node => node.startIndex)).toEqual([4, 12]);
|
||||
expect(descendants.map(node => node.endPosition)).toEqual([
|
||||
const descendants = outerSum?.descendantsOfType('number', { row: 0, column: 2 }, { row: 0, column: 15 }) ?? [];
|
||||
expect(descendants.map(node => node?.startIndex)).toEqual([4, 12]);
|
||||
expect(descendants.map(node => node?.endPosition)).toEqual([
|
||||
{ row: 0, column: 5 },
|
||||
{ row: 0, column: 13 },
|
||||
]);
|
||||
|
|
@ -493,23 +493,23 @@ describe('Node', () => {
|
|||
describe('.firstChildForIndex(index)', () => {
|
||||
it('returns the first child that contains or starts after the given index', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(sumNode!.firstChildForIndex(0)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstChildForIndex(1)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstChildForIndex(3)!.type).toBe('+');
|
||||
expect(sumNode!.firstChildForIndex(5)!.type).toBe('number');
|
||||
expect(sumNode?.firstChildForIndex(0)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstChildForIndex(1)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstChildForIndex(3)?.type).toBe('+');
|
||||
expect(sumNode?.firstChildForIndex(5)?.type).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.firstNamedChildForIndex(index)', () => {
|
||||
it('returns the first child that contains or starts after the given index', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(sumNode!.firstNamedChildForIndex(0)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstNamedChildForIndex(1)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstNamedChildForIndex(3)!.type).toBe('number');
|
||||
expect(sumNode?.firstNamedChildForIndex(0)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstNamedChildForIndex(1)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstNamedChildForIndex(3)?.type).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -517,19 +517,19 @@ describe('Node', () => {
|
|||
it('returns true if the nodes are the same', () => {
|
||||
tree = parser.parse('1 + 2');
|
||||
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const node1 = sumNode!.firstChild;
|
||||
const node2 = sumNode!.firstChild;
|
||||
expect(node1!.equals(node2!)).toBe(true);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const node1 = sumNode?.firstChild;
|
||||
const node2 = sumNode?.firstChild;
|
||||
expect(node1?.equals(node2!)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if the nodes are not the same', () => {
|
||||
tree = parser.parse('1 + 2');
|
||||
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const node1 = sumNode!.firstChild;
|
||||
const node2 = node1!.nextSibling;
|
||||
expect(node1!.equals(node2!)).toBe(false);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const node1 = sumNode?.firstChild;
|
||||
const node2 = node1?.nextSibling;
|
||||
expect(node1?.equals(node2!)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -551,13 +551,13 @@ describe('Node', () => {
|
|||
// right: (identifier) 3
|
||||
// -------------------
|
||||
|
||||
expect(binaryExpressionNode!.fieldNameForChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode!.fieldNameForChild(1)).toBe('operator');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(1)).toBe('operator');
|
||||
// The comment should not have a field name, as it's just an extra
|
||||
expect(binaryExpressionNode!.fieldNameForChild(2)).toBeNull();
|
||||
expect(binaryExpressionNode!.fieldNameForChild(3)).toBe('right');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(2)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForChild(3)).toBe('right');
|
||||
// Negative test - Not a valid child index
|
||||
expect(binaryExpressionNode!.fieldNameForChild(4)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForChild(4)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -579,13 +579,13 @@ describe('Node', () => {
|
|||
// right: (identifier) 2
|
||||
// -------------------
|
||||
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(0)).toBe('left');
|
||||
// The comment should not have a field name, as it's just an extra
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(1)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(1)).toBeNull();
|
||||
// The operator is not a named child, so the named child at index 2 is the right child
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(2)).toBe('right');
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(2)).toBe('right');
|
||||
// Negative test - Not a valid child index
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(3)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(3)).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import helper, { type LanguageName } from './helper';
|
||||
import type { default as ParserType, Language } from 'web-tree-sitter';
|
||||
import type { ParseState, Tree, Parser as ParserType, Language as LanguageType } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
let HTML: Language;
|
||||
let JSON: Language;
|
||||
let Language: typeof LanguageType;
|
||||
let JavaScript: LanguageType;
|
||||
let HTML: LanguageType;
|
||||
let JSON: LanguageType;
|
||||
let languageURL: (name: LanguageName) => string;
|
||||
|
||||
describe('Parser', () => {
|
||||
let parser: ParserType;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
({ Parser, Language, JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -25,7 +26,7 @@ describe('Parser', () => {
|
|||
|
||||
describe('.setLanguage', () => {
|
||||
it('allows setting the language to null', () => {
|
||||
expect(parser.getLanguage()).toBeUndefined();
|
||||
expect(parser.getLanguage()).toBeNull();
|
||||
parser.setLanguage(JavaScript);
|
||||
expect(parser.getLanguage()).toBe(JavaScript);
|
||||
parser.setLanguage(null);
|
||||
|
|
@ -134,7 +135,7 @@ describe('Parser', () => {
|
|||
const templateStringNode = jsTree.rootNode.descendantForIndex(
|
||||
sourceCode.indexOf('`<'),
|
||||
sourceCode.indexOf('>`')
|
||||
);
|
||||
)!;
|
||||
expect(templateStringNode.type).toBe('template_string');
|
||||
|
||||
const openQuoteNode = templateStringNode.child(0)!;
|
||||
|
|
@ -222,7 +223,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
describe('.parse', () => {
|
||||
let tree: ParserType.Tree | null;
|
||||
let tree: Tree | null;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = null;
|
||||
|
|
@ -266,7 +267,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the bash parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('bash')));
|
||||
parser.setLanguage(await Language.load(languageURL('bash')));
|
||||
tree = parser.parse('FOO=bar echo <<EOF 2> err.txt > hello.txt \nhello${FOO}\nEOF');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -283,7 +284,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the c++ parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('cpp')));
|
||||
parser.setLanguage(await Language.load(languageURL('cpp')));
|
||||
tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(translation_unit (declaration ' +
|
||||
|
|
@ -296,7 +297,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the HTML parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('html')));
|
||||
parser.setLanguage(await Language.load(languageURL('html')));
|
||||
tree = parser.parse('<div><span><custom></custom></span></div>');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(document (element (start_tag (tag_name)) (element (start_tag (tag_name)) ' +
|
||||
|
|
@ -305,7 +306,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the python parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('python')));
|
||||
parser.setLanguage(await Language.load(languageURL('python')));
|
||||
tree = parser.parse('class A:\n def b():\n c()');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(module (class_definition ' +
|
||||
|
|
@ -321,7 +322,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the rust parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('rust')));
|
||||
parser.setLanguage(await Language.load(languageURL('rust')));
|
||||
tree = parser.parse('const x: &\'static str = r###"hello"###;');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(source_file (const_item ' +
|
||||
|
|
@ -332,7 +333,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the typescript parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('typescript')));
|
||||
parser.setLanguage(await Language.load(languageURL('typescript')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -346,7 +347,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the tsx parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('tsx')));
|
||||
parser.setLanguage(await Language.load(languageURL('tsx')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -397,7 +398,7 @@ describe('Parser', () => {
|
|||
|
||||
const startTime = performance.now();
|
||||
let currentByteOffset = 0;
|
||||
const progressCallback = (state: ParserType.State) => {
|
||||
const progressCallback = (state: ParseState) => {
|
||||
expect(state.currentOffset).toBeGreaterThanOrEqual(currentByteOffset);
|
||||
currentByteOffset = state.currentOffset;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, Query, QueryCapture, QueryMatch } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Language, Tree, Query, QueryMatch, QueryCapture } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
@ -576,12 +576,11 @@ function formatMatches(matches: QueryMatch[]): QueryMatch[] {
|
|||
}));
|
||||
}
|
||||
|
||||
function formatCaptures(captures: QueryCapture[]): QueryCapture[] {
|
||||
function formatCaptures(captures: QueryCapture[]): (QueryCapture & { text: string })[] {
|
||||
return captures.map((c) => {
|
||||
const node = c.node;
|
||||
// @ts-expect-error We're not interested in the node object for these tests
|
||||
delete c.node;
|
||||
c.text = node.text;
|
||||
return c;
|
||||
return { ...c, text: node.text };
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, TreeCursor, Edit, Point } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Point, Language, Tree, Edit, TreeCursor } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue