API extensions

This commit is contained in:
Daumantas Kavolis 2023-05-17 10:39:37 +03:00
parent 08f4e82bb2
commit c47e217e73
14 changed files with 741 additions and 29 deletions

View file

@ -243,6 +243,13 @@ void ts_tree_cursor_reset_wasm(const TSTree *tree) {
marshal_cursor(&cursor);
}
void ts_tree_cursor_reset_to_wasm(const TSTree *_dst, const TSTree *_src) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, _dst);
TSTreeCursor src = unmarshal_cursor(&TRANSFER_BUFFER[3], _src);
ts_tree_cursor_reset_to(&cursor, &src);
marshal_cursor(&cursor);
}
bool ts_tree_cursor_goto_first_child_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
bool result = ts_tree_cursor_goto_first_child(&cursor);
@ -250,6 +257,13 @@ bool ts_tree_cursor_goto_first_child_wasm(const TSTree *tree) {
return result;
}
bool ts_tree_cursor_goto_last_child_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
bool result = ts_tree_cursor_goto_last_child(&cursor);
marshal_cursor(&cursor);
return result;
}
bool ts_tree_cursor_goto_next_sibling_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
bool result = ts_tree_cursor_goto_next_sibling(&cursor);
@ -257,6 +271,13 @@ bool ts_tree_cursor_goto_next_sibling_wasm(const TSTree *tree) {
return result;
}
bool ts_tree_cursor_goto_previous_sibling_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
bool result = ts_tree_cursor_goto_previous_sibling(&cursor);
marshal_cursor(&cursor);
return result;
}
bool ts_tree_cursor_goto_parent_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
bool result = ts_tree_cursor_goto_parent(&cursor);
@ -270,6 +291,12 @@ uint16_t ts_tree_cursor_current_node_type_id_wasm(const TSTree *tree) {
return ts_node_symbol(node);
}
uint16_t ts_tree_cursor_current_node_state_id_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
TSNode node = ts_tree_cursor_current_node(&cursor);
return ts_node_parse_state(node);
}
bool ts_tree_cursor_current_node_is_named_wasm(const TSTree *tree) {
TSTreeCursor cursor = unmarshal_cursor(TRANSFER_BUFFER, tree);
TSNode node = ts_tree_cursor_current_node(&cursor);
@ -579,11 +606,21 @@ int ts_node_has_error_wasm(const TSTree *tree) {
return ts_node_has_error(node);
}
int ts_node_is_error_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_is_error(node);
}
int ts_node_is_missing_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_is_missing(node);
}
uint16_t ts_node_parse_state_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_parse_state(node);
}
/******************/
/* Section - Query */
/******************/

View file

@ -1,6 +1,7 @@
const C = Module;
const INTERNAL = {};
const SIZE_OF_INT = 4;
const SIZE_OF_CURSOR = 3 * SIZE_OF_INT;
const SIZE_OF_NODE = 5 * SIZE_OF_INT;
const SIZE_OF_POINT = 2 * SIZE_OF_INT;
const SIZE_OF_RANGE = 2 * SIZE_OF_INT + 2 * SIZE_OF_POINT;
@ -227,6 +228,11 @@ class Node {
return getText(this.tree, this.startIndex, this.endIndex);
}
get parseState() {
marshalNode(this);
return C._ts_node_parse_state_wasm(this.tree[0]);
}
isNamed() {
marshalNode(this);
return C._ts_node_is_named_wasm(this.tree[0]) === 1;
@ -242,6 +248,11 @@ class Node {
return C._ts_node_has_changes_wasm(this.tree[0]) === 1;
}
isError() {
marshalNode(this);
return C._ts_node_is_error_wasm(this.tree[0]) === 1;
}
isMissing() {
marshalNode(this);
return C._ts_node_is_missing_wasm(this.tree[0]) === 1;
@ -505,6 +516,13 @@ class TreeCursor {
unmarshalTreeCursor(this);
}
resetTo(cursor) {
marshalTreeCursor(this, TRANSFER_BUFFER);
marshalTreeCursor(cursor, TRANSFER_BUFFER + SIZE_OF_CURSOR);
C._ts_tree_cursor_reset_to_wasm(this.tree[0], cursor.tree[0]);
unmarshalTreeCursor(this);
}
get nodeType() {
return this.tree.language.types[this.nodeTypeId] || 'ERROR';
}
@ -514,6 +532,11 @@ class TreeCursor {
return C._ts_tree_cursor_current_node_type_id_wasm(this.tree[0]);
}
get nodeStateId() {
marshalTreeCursor(this);
return C._ts_tree_cursor_current_node_state_id_wasm(this.tree[0]);
}
get nodeId() {
marshalTreeCursor(this);
return C._ts_tree_cursor_current_node_id_wasm(this.tree[0]);
@ -580,6 +603,13 @@ class TreeCursor {
return result === 1;
}
gotoLastChild() {
marshalTreeCursor(this);
const result = C._ts_tree_cursor_goto_last_child_wasm(this.tree[0]);
unmarshalTreeCursor(this);
return result === 1;
}
gotoNextSibling() {
marshalTreeCursor(this);
const result = C._ts_tree_cursor_goto_next_sibling_wasm(this.tree[0]);
@ -587,6 +617,13 @@ class TreeCursor {
return result === 1;
}
gotoPreviousSibling() {
marshalTreeCursor(this);
const result = C._ts_tree_cursor_goto_previous_sibling_wasm(this.tree[0]);
unmarshalTreeCursor(this);
return result === 1;
}
gotoParent() {
marshalTreeCursor(this);
const result = C._ts_tree_cursor_goto_parent_wasm(this.tree[0]);
@ -624,6 +661,10 @@ class Language {
return this.fields.length - 1;
}
get stateCount() {
return C._ts_language_state_count(this[0]);
}
fieldIdForName(fieldName) {
const result = this.fields.indexOf(fieldName);
if (result !== -1) {
@ -663,6 +704,15 @@ class Language {
return C._ts_language_type_is_visible_wasm(this[0], typeId) ? true : false;
}
nextState(stateId, typeId) {
return C._ts_language_next_state(this[0], stateId, typeId);
}
lookaheadIterator(stateId) {
const address = C._ts_lookahead_iterator_new(this[0], stateId);
if (address) return new LookaheadIterable(INTERNAL, address, this);
}
query(source) {
const sourceLength = lengthBytesUTF8(source);
const sourceAddress = C._malloc(sourceLength + 1);
@ -924,6 +974,53 @@ class Language {
}
}
class LookaheadIterable {
constructor(internal, address, language) {
assertInternal(internal);
this[0] = address;
this.language = language;
}
get currentTypeId() {
return C._ts_lookahead_iterator_current_symbol(this[0]);
}
get currentType() {
return this.language.types[this.currentTypeId] || 'ERROR'
}
delete() {
C._ts_lookahead_iterator_delete(this[0]);
this[0] = 0;
}
resetState(stateId) {
return C._ts_lookahead_iterator_reset_state(this[0], stateId);
}
reset(language, stateId) {
if (C._ts_lookahead_iterator_reset(this[0], language, stateId)) {
this.language = language;
return true;
}
return false;
}
[Symbol.iterator]() {
const self = this;
return {
next() {
if (C._ts_lookahead_iterator_advance(self[0])) {
return { done: false, value: self.currentType };
}
return { done: true, value: "" };
}
};
}
}
class Query {
constructor(
internal, address, captureNames, textPredicates, predicates,

View file

@ -38,10 +38,12 @@
"_ts_language_type_is_named_wasm",
"_ts_language_type_is_visible_wasm",
"_ts_language_symbol_count",
"_ts_language_state_count",
"_ts_language_symbol_for_name",
"_ts_language_symbol_name",
"_ts_language_symbol_type",
"_ts_language_version",
"_ts_language_next_state",
"_ts_node_child_by_field_id_wasm",
"_ts_node_child_count_wasm",
"_ts_node_child_wasm",
@ -53,8 +55,10 @@
"_ts_node_end_point_wasm",
"_ts_node_has_changes_wasm",
"_ts_node_has_error_wasm",
"_ts_node_is_error_wasm",
"_ts_node_is_missing_wasm",
"_ts_node_is_named_wasm",
"_ts_node_parse_state_wasm",
"_ts_node_named_child_count_wasm",
"_ts_node_named_child_wasm",
"_ts_node_named_children_wasm",
@ -93,19 +97,29 @@
"_ts_tree_cursor_current_node_is_missing_wasm",
"_ts_tree_cursor_current_node_is_named_wasm",
"_ts_tree_cursor_current_node_type_id_wasm",
"_ts_tree_cursor_current_node_state_id_wasm",
"_ts_tree_cursor_current_node_wasm",
"_ts_tree_cursor_delete_wasm",
"_ts_tree_cursor_end_index_wasm",
"_ts_tree_cursor_end_position_wasm",
"_ts_tree_cursor_goto_first_child_wasm",
"_ts_tree_cursor_goto_last_child",
"_ts_tree_cursor_goto_next_sibling_wasm",
"_ts_tree_cursor_goto_previous_sibling_wasm",
"_ts_tree_cursor_goto_parent_wasm",
"_ts_tree_cursor_new_wasm",
"_ts_tree_cursor_reset_wasm",
"_ts_tree_cursor_reset_to_wasm",
"_ts_tree_cursor_start_index_wasm",
"_ts_tree_cursor_start_position_wasm",
"_ts_tree_delete",
"_ts_tree_edit_wasm",
"_ts_tree_get_changed_ranges_wasm",
"_ts_tree_root_node_wasm"
"_ts_tree_root_node_wasm",
"_ts_lookahead_iterator_new",
"_ts_lookahead_iterator_delete",
"_ts_lookahead_iterator_reset_state",
"_ts_lookahead_iterator_reset",
"_ts_lookahead_iterator_advance",
"_ts_lookahead_iterator_current_symbol"
]

View file

@ -268,6 +268,24 @@ describe("Node", () => {
});
});
describe(".isError()", () => {
it("returns true if the node is an error", () => {
tree = parser.parse("2 * * 3");
const node = tree.rootNode;
assert.equal(
node.toString(),
'(program (expression_statement (binary_expression left: (number) (ERROR) right: (number))))'
);
const multi = node.firstChild.firstChild;
assert(multi.hasError());
assert(!multi.children[0].isError());
assert(!multi.children[1].isError());
assert(multi.children[2].isError());
assert(!multi.children[3].isError());
});
});
describe(".isMissing()", () => {
it("returns true if the node is missing from the source and was inserted via error recovery", () => {
tree = parser.parse("(2 ||)");
@ -308,6 +326,21 @@ describe("Node", () => {
);
});
describe(".parseState", () => {
const text = "10 * 5";
it(`returns node parse state ids`, async () => {
tree = await parser.parse(text)
const quotientNode = tree.rootNode.firstChild.firstChild;
const [numerator, slash, denominator] = quotientNode.children;
assert.equal(tree.rootNode.parseState, 0);
assert.equal(numerator.parseState, 1);
assert.equal(slash.parseState, 553);
assert.equal(denominator.parseState, 185);
})
});
describe('.descendantsOfType(type, min, max)', () => {
it('finds all of the descendants of the given type in the given range', () => {
tree = parser.parse("a + 1 * b * 2 + c + 3");

View file

@ -59,6 +59,7 @@ declare module 'web-tree-sitter' {
tree: Tree;
type: string;
text: string;
parseState: number;
startPosition: Point;
endPosition: Point;
startIndex: number;
@ -80,6 +81,7 @@ declare module 'web-tree-sitter' {
hasChanges(): boolean;
hasError(): boolean;
equals(other: SyntaxNode): boolean;
isError(): boolean;
isMissing(): boolean;
isNamed(): boolean;
toString(): string;
@ -104,6 +106,7 @@ declare module 'web-tree-sitter' {
export interface TreeCursor {
nodeType: string;
nodeTypeId: number;
nodeStateId: number;
nodeText: string;
nodeId: number;
nodeIsNamed: boolean;
@ -114,14 +117,17 @@ declare module 'web-tree-sitter' {
endIndex: number;
reset(node: SyntaxNode): void;
resetTo(cursor: TreeCursor): void;
delete(): void;
currentNode(): SyntaxNode;
currentFieldId(): number;
currentFieldName(): string;
gotoParent(): boolean;
gotoFirstChild(): boolean;
gotoLastChild(): boolean;
gotoFirstChildForIndex(index: number): boolean;
gotoNextSibling(): boolean;
gotoPreviousSibling(): boolean;
}
export interface Tree {
@ -141,6 +147,7 @@ declare module 'web-tree-sitter' {
readonly version: number;
readonly fieldCount: number;
readonly stateCount: number;
readonly nodeTypeCount: number;
fieldNameForId(fieldId: number): string | null;
@ -149,7 +156,20 @@ declare module 'web-tree-sitter' {
nodeTypeForId(typeId: number): string | null;
nodeTypeIsNamed(typeId: number): boolean;
nodeTypeIsVisible(typeId: number): boolean;
nextState(stateId: number, typeId: number): number;
query(source: string): Query;
lookaheadIterator(stateId: number): LookaheadIterable | null;
}
class LookaheadIterable {
readonly language: Language;
readonly currentTypeId: number;
readonly currentType: string;
delete(): void;
resetState(stateId: number): boolean;
reset(language: Language, stateId: number): boolean;
[Symbol.iterator](): Iterator<string>;
}
interface QueryCapture {