test: update tests
This commit is contained in:
parent
09cb4c5729
commit
1f66d156b5
6 changed files with 234 additions and 272 deletions
|
|
@ -1,12 +1,6 @@
|
|||
import { type Parser as ParserType, type Language as LanguageType } from '../src';
|
||||
import { Parser, Language } from '../src';
|
||||
import path from 'path';
|
||||
|
||||
// @ts-expect-error We're intentionally importing ../tree-sitter.js
|
||||
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';
|
||||
|
||||
|
|
@ -16,8 +10,6 @@ function languageURL(name: LanguageName): string {
|
|||
}
|
||||
|
||||
export default Parser.init().then(async () => ({
|
||||
Parser,
|
||||
Language,
|
||||
languageURL,
|
||||
C: await Language.load(languageURL('c')),
|
||||
EmbeddedTemplate: await Language.load(languageURL('embedded-template')),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import helper from './helper';
|
||||
import type { Parser as ParserType, LookaheadIterator, Language } from '../src';
|
||||
import type { LookaheadIterator, Language } from '../src';
|
||||
import { Parser } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
let Rust: Language;
|
||||
|
||||
|
|
@ -136,10 +136,10 @@ describe('Lookahead iterator', () => {
|
|||
let state: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, JavaScript } = await helper);
|
||||
({ JavaScript } = await helper);
|
||||
const parser = new Parser();
|
||||
parser.setLanguage(JavaScript);
|
||||
const tree = parser.parse('function fn() {}');
|
||||
const tree = parser.parse('function fn() {}')!;
|
||||
parser.delete();
|
||||
const cursor = tree.walk();
|
||||
expect(cursor.gotoFirstChild()).toBe(true);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { Parser as ParserType, Language, Tree, Node } from '../src';
|
||||
import type { Language, Tree, Node } from '../src';
|
||||
import { Parser } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let C: Language;
|
||||
let JavaScript: Language;
|
||||
let JSON: Language;
|
||||
|
|
@ -40,11 +40,11 @@ function getAllNodes(tree: Tree): Node[] {
|
|||
}
|
||||
|
||||
describe('Node', () => {
|
||||
let parser: ParserType;
|
||||
let parser: Parser;
|
||||
let tree: Tree | null;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, C, EmbeddedTemplate, JavaScript, JSON, Python } = await helper);
|
||||
({ C, EmbeddedTemplate, JavaScript, JSON, Python } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -55,31 +55,24 @@ describe('Node', () => {
|
|||
|
||||
afterEach(() => {
|
||||
parser.delete();
|
||||
tree?.delete();
|
||||
tree!.delete();
|
||||
});
|
||||
|
||||
describe('.children', () => {
|
||||
it('returns an array of child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
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([
|
||||
'identifier',
|
||||
'+',
|
||||
'number'
|
||||
]);
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild!;
|
||||
expect(sumNode.children.map(child => child!.type)).toEqual(['identifier', '+', 'number' ]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.namedChildren', () => {
|
||||
it('returns an array of named child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild!;
|
||||
expect(tree.rootNode.namedChildren).toHaveLength(1);
|
||||
expect(sumNode?.namedChildren.map(child => child?.type)).toEqual([
|
||||
'identifier',
|
||||
'number'
|
||||
]);
|
||||
expect(sumNode.namedChildren.map(child => child!.type)).toEqual(['identifier', 'number']);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -96,13 +89,13 @@ describe('Node', () => {
|
|||
elif four:
|
||||
d()`;
|
||||
|
||||
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);
|
||||
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(alternativeTexts).toEqual(['two', 'three', 'four']);
|
||||
});
|
||||
|
|
@ -110,30 +103,30 @@ 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;
|
||||
tree = parser.parse('a👍👎1 / b👎c👎')!;
|
||||
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');
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
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 },
|
||||
|
|
@ -141,9 +134,9 @@ 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([
|
||||
tree = parser.parse('a👍👎1 /\n b👎c👎')!;
|
||||
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 }]
|
||||
|
|
@ -153,75 +146,75 @@ describe('Node', () => {
|
|||
|
||||
describe('.parent', () => {
|
||||
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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.childForFieldName()', () => {
|
||||
it('returns node for the given field name', () => {
|
||||
tree = parser.parse('class A { b() {} }');
|
||||
tree = parser.parse('class A { b() {} }')!;
|
||||
|
||||
const classNode = tree.rootNode.firstChild;
|
||||
expect(classNode?.type).toBe('class_declaration');
|
||||
const classNode = tree.rootNode.firstChild!;
|
||||
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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
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('+');
|
||||
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('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
|
|
@ -237,28 +230,20 @@ describe('Node', () => {
|
|||
|
||||
describe('.namedDescendantForIndex', () => {
|
||||
it('returns the smallest named node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
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('+');
|
||||
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');
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
|
||||
expect(
|
||||
sumNode.descendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 }
|
||||
)?.type
|
||||
).toBe('identifier');
|
||||
|
||||
expect(
|
||||
sumNode.descendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('+');
|
||||
expect(sumNode.descendantForPosition({ row: 0, column: 1 }, { row: 0, column: 2 })!.type).toBe('identifier');
|
||||
expect(sumNode.descendantForPosition({ row: 0, column: 4 })!.type).toBe('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
|
|
@ -274,75 +259,67 @@ describe('Node', () => {
|
|||
|
||||
describe('.namedDescendantForPosition(min, max)', () => {
|
||||
it('returns the smallest named node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
|
||||
expect(
|
||||
sumNode.namedDescendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 },
|
||||
)?.type
|
||||
).toBe('identifier')
|
||||
|
||||
expect(
|
||||
sumNode.namedDescendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('binary_expression');
|
||||
expect(sumNode.namedDescendantForPosition({ row: 0, column: 1 }, { row: 0, column: 2 })!.type).toBe('identifier')
|
||||
expect(sumNode.namedDescendantForPosition({ row: 0, column: 4 })!.type).toBe('binary_expression');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.hasError', () => {
|
||||
it('returns true if the node contains an error', () => {
|
||||
tree = parser.parse('1 + 2 * * 3');
|
||||
tree = parser.parse('1 + 2 * * 3')!;
|
||||
const node = tree.rootNode;
|
||||
expect(node.toString()).toBe(
|
||||
'(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);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.isError', () => {
|
||||
it('returns true if the node is an error', () => {
|
||||
tree = parser.parse('2 * * 3');
|
||||
tree = parser.parse('2 * * 3')!;
|
||||
const node = tree.rootNode;
|
||||
expect(node.toString()).toBe(
|
||||
'(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);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.isMissing', () => {
|
||||
it('returns true if the node was inserted via error recovery', () => {
|
||||
tree = parser.parse('(2 ||)');
|
||||
tree = parser.parse('(2 ||)')!;
|
||||
const node = tree.rootNode;
|
||||
expect(node.toString()).toBe(
|
||||
'(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);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.isExtra', () => {
|
||||
it('returns true if the node is an extra node like comments', () => {
|
||||
tree = parser.parse('foo(/* hi */);');
|
||||
tree = parser.parse('foo(/* hi */);')!;
|
||||
const node = tree.rootNode;
|
||||
const commentNode = node.descendantForIndex(7, 7)!;
|
||||
|
||||
|
|
@ -362,15 +339,15 @@ describe('Node', () => {
|
|||
}).forEach(([method, _parse]) => {
|
||||
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;
|
||||
tree = parser.parse(_parse)!;
|
||||
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('/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -378,7 +355,7 @@ describe('Node', () => {
|
|||
describe('.descendantCount', () => {
|
||||
it('returns the number of descendants', () => {
|
||||
parser.setLanguage(JSON);
|
||||
tree = parser.parse(JSON_EXAMPLE);
|
||||
tree = parser.parse(JSON_EXAMPLE)!;
|
||||
const valueNode = tree.rootNode;
|
||||
const allNodes = getAllNodes(tree);
|
||||
|
||||
|
|
@ -400,7 +377,7 @@ describe('Node', () => {
|
|||
|
||||
it('tests a single node tree', () => {
|
||||
parser.setLanguage(EmbeddedTemplate);
|
||||
tree = parser.parse('hello');
|
||||
tree = parser.parse('hello')!;
|
||||
|
||||
const nodes = getAllNodes(tree);
|
||||
expect(nodes).toHaveLength(2);
|
||||
|
|
@ -420,19 +397,19 @@ describe('Node', () => {
|
|||
|
||||
describe('.rootNodeWithOffset', () => {
|
||||
it('returns the root node of the tree, offset by the given byte offset', () => {
|
||||
tree = parser.parse(' if (a) b');
|
||||
tree = parser.parse(' if (a) b')!;
|
||||
const node = tree.rootNodeWithOffset(6, { row: 2, column: 2 });
|
||||
expect(node.startIndex).toBe(8);
|
||||
expect(node.endIndex).toBe(16);
|
||||
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();
|
||||
|
|
@ -451,40 +428,35 @@ describe('Node', () => {
|
|||
const text = '10 / 5';
|
||||
|
||||
it('returns node parse state ids', () => {
|
||||
tree = parser.parse(text);
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
const [numerator, slash, denominator] = quotientNode!.children;
|
||||
tree = parser.parse(text)!;
|
||||
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)
|
||||
);
|
||||
tree = parser.parse(text)!;
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild!;
|
||||
quotientNode.children.forEach((node) => {
|
||||
expect(node!.nextParseState).toBe(JavaScript.nextState(node!.parseState, node!.grammarId));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
tree = parser.parse('a + 1 * b * 2 + c + 3')!;
|
||||
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([
|
||||
{ row: 0, column: 5 },
|
||||
{ row: 0, column: 13 },
|
||||
]);
|
||||
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 }]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -492,57 +464,57 @@ 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;
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
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;
|
||||
tree = parser.parse('x10 + 1000')!;
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.equals(other)', () => {
|
||||
it('returns true if the nodes are the same', () => {
|
||||
tree = parser.parse('1 + 2');
|
||||
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');
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.fieldNameForChild(index)', () => {
|
||||
it('returns the field of a child or null', () => {
|
||||
parser.setLanguage(C);
|
||||
tree = parser.parse('int w = x + /* y is special! */ y;');
|
||||
tree = parser.parse('int w = x + /* y is special! */ y;')!;
|
||||
|
||||
const translationUnitNode = tree.rootNode;
|
||||
const declarationNode = translationUnitNode.firstChild;
|
||||
const binaryExpressionNode = declarationNode!
|
||||
.childForFieldName('declarator')!
|
||||
.childForFieldName('value');
|
||||
.childForFieldName('value')!;
|
||||
|
||||
// -------------------
|
||||
// left: (identifier) 0
|
||||
|
|
@ -551,26 +523,26 @@ 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();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.fieldNameForNamedChild(index)', () => {
|
||||
it('returns the field of a named child or null', () => {
|
||||
parser.setLanguage(C);
|
||||
tree = parser.parse('int w = x + /* y is special! */ y;');
|
||||
tree = parser.parse('int w = x + /* y is special! */ y;')!;
|
||||
|
||||
const translationUnitNode = tree.rootNode;
|
||||
const declarationNode = translationUnitNode.firstNamedChild;
|
||||
const binaryExpressionNode = declarationNode!
|
||||
.childForFieldName('declarator')!
|
||||
.childForFieldName('value');
|
||||
.childForFieldName('value')!;
|
||||
|
||||
// -------------------
|
||||
// left: (identifier) 0
|
||||
|
|
@ -579,13 +551,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,19 +1,18 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import helper, { type LanguageName } from './helper';
|
||||
import type { ParseState, Tree, Parser as ParserType, Language as LanguageType } from '../src';
|
||||
import type { ParseState, Tree } from '../src';
|
||||
import { Parser, Language } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let Language: typeof LanguageType;
|
||||
let JavaScript: LanguageType;
|
||||
let HTML: LanguageType;
|
||||
let JSON: LanguageType;
|
||||
let JavaScript: Language;
|
||||
let HTML: Language;
|
||||
let JSON: Language;
|
||||
let languageURL: (name: LanguageName) => string;
|
||||
|
||||
describe('Parser', () => {
|
||||
let parser: ParserType;
|
||||
let parser: Parser;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, Language, JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
({ JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -49,7 +48,7 @@ describe('Parser', () => {
|
|||
it('calls the given callback for each parse event', () => {
|
||||
const debugMessages: string[] = [];
|
||||
parser.setLogger((message) => debugMessages.push(message));
|
||||
parser.parse('a + b + c');
|
||||
parser.parse('a + b + c')!;
|
||||
expect(debugMessages).toEqual(expect.arrayContaining([
|
||||
'skip character:\' \'',
|
||||
'consume character:\'b\'',
|
||||
|
|
@ -70,7 +69,7 @@ describe('Parser', () => {
|
|||
const debugMessages: string[] = [];
|
||||
parser.setLogger((message) => debugMessages.push(message));
|
||||
parser.setLogger(false);
|
||||
parser.parse('a + b * c');
|
||||
parser.parse('a + b * c')!;
|
||||
expect(debugMessages).toHaveLength(0);
|
||||
});
|
||||
|
||||
|
|
@ -92,7 +91,7 @@ describe('Parser', () => {
|
|||
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 htmlTree = parser.parse(sourceCode)!;
|
||||
const scriptContentNode = htmlTree.rootNode.child(1)!.child(1)!;
|
||||
expect(scriptContentNode.type).toBe('raw_text');
|
||||
|
||||
|
|
@ -115,7 +114,7 @@ describe('Parser', () => {
|
|||
sourceCode,
|
||||
null,
|
||||
{ includedRanges: ranges }
|
||||
);
|
||||
)!;
|
||||
expect(parser.getIncludedRanges()).toEqual(ranges);
|
||||
|
||||
expect(jsTree.rootNode.toString()).toBe(
|
||||
|
|
@ -131,7 +130,7 @@ describe('Parser', () => {
|
|||
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 jsTree = parser.parse(sourceCode)!;
|
||||
const templateStringNode = jsTree.rootNode.descendantForIndex(
|
||||
sourceCode.indexOf('`<'),
|
||||
sourceCode.indexOf('>`')
|
||||
|
|
@ -165,7 +164,7 @@ describe('Parser', () => {
|
|||
},
|
||||
];
|
||||
|
||||
const htmlTree = parser.parse(sourceCode, null, { includedRanges: htmlRanges });
|
||||
const htmlTree = parser.parse(sourceCode, null, { includedRanges: htmlRanges })!;
|
||||
|
||||
expect(htmlTree.rootNode.toString()).toBe(
|
||||
'(document (element' +
|
||||
|
|
@ -212,7 +211,7 @@ describe('Parser', () => {
|
|||
endPosition: { row: 10, column: 12 + endIndex },
|
||||
};
|
||||
|
||||
const htmlTree = parser.parse(sourceCode, null, { includedRanges: [rangeToParse] });
|
||||
const htmlTree = parser.parse(sourceCode, null, { includedRanges: [rangeToParse] })!;
|
||||
|
||||
expect(htmlTree.getIncludedRanges()[0]).toEqual(rangeToParse);
|
||||
|
||||
|
|
@ -236,13 +235,13 @@ describe('Parser', () => {
|
|||
|
||||
it('reads from the given input', () => {
|
||||
const parts = ['first', '_', 'second', '_', 'third'];
|
||||
tree = parser.parse(() => parts.shift());
|
||||
tree = parser.parse(() => parts.shift())!;
|
||||
expect(tree.rootNode.toString()).toBe('(program (expression_statement (identifier)))');
|
||||
});
|
||||
|
||||
it('stops reading when the input callback returns something that\'s not a string', () => {
|
||||
const parts = ['abc', 'def', 'ghi', {}, {}, {}, 'second-word', ' '];
|
||||
tree = parser.parse(() => parts.shift() as string);
|
||||
tree = parser.parse(() => parts.shift() as string)!;
|
||||
expect(tree.rootNode.toString()).toBe('(program (expression_statement (identifier)))');
|
||||
expect(tree.rootNode.endIndex).toBe(9);
|
||||
expect(parts).toHaveLength(2);
|
||||
|
|
@ -261,14 +260,14 @@ describe('Parser', () => {
|
|||
const repeatCount = 10000;
|
||||
const inputString = `[${Array(repeatCount).fill('0').join(',')}]`;
|
||||
|
||||
tree = parser.parse(inputString);
|
||||
tree = parser.parse(inputString)!;
|
||||
expect(tree.rootNode.type).toBe('program');
|
||||
expect(tree.rootNode.firstChild!.firstChild!.namedChildCount).toBe(repeatCount);
|
||||
});
|
||||
|
||||
it('can use the bash parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('bash')));
|
||||
tree = parser.parse('FOO=bar echo <<EOF 2> err.txt > hello.txt \nhello${FOO}\nEOF');
|
||||
tree = parser.parse('FOO=bar echo <<EOF 2> err.txt > hello.txt \nhello${FOO}\nEOF')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
'(redirected_statement ' +
|
||||
|
|
@ -285,7 +284,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the c++ parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('cpp')));
|
||||
tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";');
|
||||
tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(translation_unit (declaration ' +
|
||||
'(type_qualifier) ' +
|
||||
|
|
@ -298,7 +297,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the HTML parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('html')));
|
||||
tree = parser.parse('<div><span><custom></custom></span></div>');
|
||||
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)) ' +
|
||||
'(element (start_tag (tag_name)) (end_tag (tag_name))) (end_tag (tag_name))) (end_tag (tag_name))))'
|
||||
|
|
@ -307,7 +306,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the python parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('python')));
|
||||
tree = parser.parse('class A:\n def b():\n c()');
|
||||
tree = parser.parse('class A:\n def b():\n c()')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(module (class_definition ' +
|
||||
'name: (identifier) ' +
|
||||
|
|
@ -323,7 +322,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the rust parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('rust')));
|
||||
tree = parser.parse('const x: &\'static str = r###"hello"###;');
|
||||
tree = parser.parse('const x: &\'static str = r###"hello"###;')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(source_file (const_item ' +
|
||||
'name: (identifier) ' +
|
||||
|
|
@ -334,7 +333,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the typescript parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('typescript')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
tree = parser.parse('a()\nb()\n[c]')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
'(expression_statement (call_expression function: (identifier) arguments: (arguments))) ' +
|
||||
|
|
@ -348,7 +347,7 @@ describe('Parser', () => {
|
|||
|
||||
it('can use the tsx parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Language.load(languageURL('tsx')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
tree = parser.parse('a()\nb()\n[c]')!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
'(expression_statement (call_expression function: (identifier) arguments: (arguments))) ' +
|
||||
|
|
@ -384,7 +383,7 @@ describe('Parser', () => {
|
|||
endPosition: { row: 0, column: end2 },
|
||||
},
|
||||
],
|
||||
});
|
||||
})!;
|
||||
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -408,12 +407,11 @@ describe('Parser', () => {
|
|||
return false;
|
||||
};
|
||||
|
||||
expect(() => parser.parse(
|
||||
expect(parser.parse(
|
||||
(offset) => offset === 0 ? '[' : ',0',
|
||||
null,
|
||||
{ progressCallback },
|
||||
)
|
||||
).toThrowError();
|
||||
)).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { Parser as ParserType, Language, Tree, Query, QueryMatch, QueryCapture } from '../src';
|
||||
import type { Language, Tree, QueryMatch, QueryCapture } from '../src';
|
||||
import { Parser, Query } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
|
||||
describe('Query', () => {
|
||||
let parser: ParserType;
|
||||
let parser: Parser;
|
||||
let tree: Tree | null;
|
||||
let query: Query | null;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, JavaScript } = await helper);
|
||||
({ JavaScript } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -65,7 +65,7 @@ describe('Query', () => {
|
|||
|
||||
describe('.matches', () => {
|
||||
it('returns all of the matches for the given query', () => {
|
||||
tree = parser.parse('function one() { two(); function three() {} }');
|
||||
tree = parser.parse('function one() { two(); function three() {} }')!;
|
||||
query = JavaScript.query(`
|
||||
(function_declaration name: (identifier) @fn-def)
|
||||
(call_expression function: (identifier) @fn-ref)
|
||||
|
|
@ -79,7 +79,7 @@ describe('Query', () => {
|
|||
});
|
||||
|
||||
it('can search in specified ranges', () => {
|
||||
tree = parser.parse('[a, b,\nc, d,\ne, f,\ng, h]');
|
||||
tree = parser.parse('[a, b,\nc, d,\ne, f,\ng, h]')!;
|
||||
query = JavaScript.query('(identifier) @element');
|
||||
const matches = query.matches(
|
||||
tree.rootNode,
|
||||
|
|
@ -104,7 +104,7 @@ describe('Query', () => {
|
|||
gross(3, []);
|
||||
hiccup([]);
|
||||
gaff(5);
|
||||
`);
|
||||
`)!;
|
||||
|
||||
// Find all calls to functions beginning with 'g', where one argument
|
||||
// is an array literal.
|
||||
|
|
@ -125,7 +125,7 @@ describe('Query', () => {
|
|||
it('handles multiple matches where the first one is filtered', () => {
|
||||
tree = parser.parse(`
|
||||
const a = window.b;
|
||||
`);
|
||||
`)!;
|
||||
|
||||
query = JavaScript.query(`
|
||||
((identifier) @variable.builtin
|
||||
|
|
@ -151,7 +151,7 @@ describe('Query', () => {
|
|||
const no = function pq() {}
|
||||
},
|
||||
});
|
||||
`);
|
||||
`)!;
|
||||
query = JavaScript.query(`
|
||||
(pair
|
||||
key: _ @method.def
|
||||
|
|
@ -192,7 +192,7 @@ describe('Query', () => {
|
|||
toad
|
||||
const ab = require('./ab');
|
||||
new Cd(EF);
|
||||
`);
|
||||
`)!;
|
||||
|
||||
query = JavaScript.query(`
|
||||
((identifier) @variable
|
||||
|
|
@ -228,7 +228,7 @@ describe('Query', () => {
|
|||
ab = abc + 1;
|
||||
def = de + 1;
|
||||
ghi = ghi + 1;
|
||||
`);
|
||||
`)!;
|
||||
|
||||
query = JavaScript.query(`
|
||||
(
|
||||
|
|
@ -248,7 +248,7 @@ describe('Query', () => {
|
|||
});
|
||||
|
||||
it('handles patterns with properties', () => {
|
||||
tree = parser.parse(`a(b.c);`);
|
||||
tree = parser.parse(`a(b.c);`)!;
|
||||
query = JavaScript.query(`
|
||||
((call_expression (identifier) @func)
|
||||
(#set! foo)
|
||||
|
|
@ -285,7 +285,7 @@ describe('Query', () => {
|
|||
hello, hello, hello, hello, hello, hello, hello, hello, hello, hello,
|
||||
hello, hello, hello, hello, hello, hello, hello, hello, hello, hello,
|
||||
];
|
||||
`);
|
||||
`)!;
|
||||
|
||||
query = JavaScript.query(`
|
||||
(array (identifier) @pre (identifier) @post)
|
||||
|
|
@ -300,7 +300,7 @@ describe('Query', () => {
|
|||
/// foo
|
||||
/// bar
|
||||
/// baz
|
||||
`);
|
||||
`)!;
|
||||
|
||||
const expectCount = (tree: Tree, queryText: string, expectedCount: number) => {
|
||||
query = JavaScript.query(queryText);
|
||||
|
|
@ -427,7 +427,7 @@ describe('Query', () => {
|
|||
`);
|
||||
|
||||
const source = 'function foo() { return 1; }';
|
||||
const tree = parser.parse(source);
|
||||
const tree = parser.parse(source)!;
|
||||
|
||||
let matches = query.matches(tree.rootNode);
|
||||
expect(formatMatches(matches)).toEqual([
|
||||
|
|
@ -463,7 +463,7 @@ describe('Query', () => {
|
|||
|
||||
describe('Set a timeout', () => {
|
||||
it('returns less than the expected matches', () => {
|
||||
tree = parser.parse('function foo() while (true) { } }\n'.repeat(1000));
|
||||
tree = parser.parse('function foo() while (true) { } }\n'.repeat(1000))!;
|
||||
query = JavaScript.query(
|
||||
'(function_declaration name: (identifier) @function)'
|
||||
);
|
||||
|
|
@ -528,7 +528,7 @@ describe('Query', () => {
|
|||
query.disablePattern(2);
|
||||
|
||||
const source = 'class A { constructor() {} } function b() { return 1; }';
|
||||
tree = parser.parse(source);
|
||||
tree = parser.parse(source)!;
|
||||
const matches = query.matches(tree.rootNode);
|
||||
expect(formatMatches(matches)).toEqual([
|
||||
{
|
||||
|
|
@ -542,7 +542,7 @@ describe('Query', () => {
|
|||
|
||||
describe('Executes with a timeout', () => {
|
||||
it('Returns less than the expected matches', () => {
|
||||
tree = parser.parse('function foo() while (true) { } }\n'.repeat(1000));
|
||||
tree = parser.parse('function foo() while (true) { } }\n'.repeat(1000))!;
|
||||
query = JavaScript.query(
|
||||
'(function_declaration) @function'
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { Parser as ParserType, Point, Language, Tree, Edit, TreeCursor } from '../src';
|
||||
import type { Point, Language, Tree, Edit, TreeCursor } from '../src';
|
||||
import { Parser } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
|
||||
interface CursorState {
|
||||
|
|
@ -15,11 +15,11 @@ interface CursorState {
|
|||
}
|
||||
|
||||
describe('Tree', () => {
|
||||
let parser: ParserType;
|
||||
let parser: Parser;
|
||||
let tree: Tree;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, JavaScript } = await helper);
|
||||
({ JavaScript } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -38,7 +38,7 @@ describe('Tree', () => {
|
|||
|
||||
it('updates the positions of nodes', () => {
|
||||
input = 'abc + cde';
|
||||
tree = parser.parse(input);
|
||||
tree = parser.parse(input)!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (identifier) right: (identifier))))'
|
||||
);
|
||||
|
|
@ -63,7 +63,7 @@ describe('Tree', () => {
|
|||
expect(variableNode2!.startIndex).toBe(9);
|
||||
expect(variableNode2!.endIndex).toBe(12);
|
||||
|
||||
tree = parser.parse(input, tree);
|
||||
tree = parser.parse(input, tree)!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))'
|
||||
);
|
||||
|
|
@ -72,7 +72,7 @@ describe('Tree', () => {
|
|||
it('handles non-ascii characters', () => {
|
||||
input = 'αβδ + cde';
|
||||
|
||||
tree = parser.parse(input);
|
||||
tree = parser.parse(input)!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (identifier) right: (identifier))))'
|
||||
);
|
||||
|
|
@ -86,7 +86,7 @@ describe('Tree', () => {
|
|||
variableNode = tree.rootNode.firstChild!.firstChild!.lastChild;
|
||||
expect(variableNode!.startIndex).toBe(input.indexOf('cde'));
|
||||
|
||||
tree = parser.parse(input, tree);
|
||||
tree = parser.parse(input, tree)!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))'
|
||||
);
|
||||
|
|
@ -96,7 +96,7 @@ describe('Tree', () => {
|
|||
describe('.getChangedRanges(previous)', () => {
|
||||
it('reports the ranges of text whose syntactic meaning has changed', () => {
|
||||
let sourceCode = 'abcdefg + hij';
|
||||
tree = parser.parse(sourceCode);
|
||||
tree = parser.parse(sourceCode)!;
|
||||
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (identifier) right: (identifier))))'
|
||||
|
|
@ -112,7 +112,7 @@ describe('Tree', () => {
|
|||
newEndPosition: { row: 0, column: 5 },
|
||||
});
|
||||
|
||||
const tree2 = parser.parse(sourceCode, tree);
|
||||
const tree2 = parser.parse(sourceCode, tree)!;
|
||||
expect(tree2.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (binary_expression left: (identifier) right: (identifier)) right: (identifier))))'
|
||||
);
|
||||
|
|
@ -131,7 +131,7 @@ describe('Tree', () => {
|
|||
});
|
||||
|
||||
it('throws an exception if the argument is not a tree', () => {
|
||||
tree = parser.parse('abcdefg + hij');
|
||||
tree = parser.parse('abcdefg + hij')!;
|
||||
|
||||
expect(() => {
|
||||
tree.getChangedRanges({} as Tree);
|
||||
|
|
@ -147,7 +147,7 @@ describe('Tree', () => {
|
|||
});
|
||||
|
||||
it('returns a cursor that can be used to walk the tree', () => {
|
||||
tree = parser.parse('a * b + c / d');
|
||||
tree = parser.parse('a * b + c / d')!;
|
||||
cursor = tree.walk();
|
||||
|
||||
assertCursorState(cursor, {
|
||||
|
|
@ -306,7 +306,7 @@ describe('Tree', () => {
|
|||
});
|
||||
|
||||
it('keeps track of the field name associated with each node', () => {
|
||||
tree = parser.parse('a.b();');
|
||||
tree = parser.parse('a.b();')!;
|
||||
cursor = tree.walk();
|
||||
cursor.gotoFirstChild();
|
||||
cursor.gotoFirstChild();
|
||||
|
|
@ -334,7 +334,7 @@ describe('Tree', () => {
|
|||
});
|
||||
|
||||
it('returns a cursor that can be reset anywhere in the tree', () => {
|
||||
tree = parser.parse('a * b + c / d');
|
||||
tree = parser.parse('a * b + c / d')!;
|
||||
cursor = tree.walk();
|
||||
const root = tree.rootNode.firstChild;
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ describe('Tree', () => {
|
|||
|
||||
it('creates another tree that remains stable if the original tree is edited', () => {
|
||||
input = 'abc + cde';
|
||||
tree = parser.parse(input);
|
||||
tree = parser.parse(input)!;
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program (expression_statement (binary_expression left: (identifier) right: (identifier))))'
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue