Merge branch 'master' into actions-ci
This commit is contained in:
commit
6dbe6a3a90
27 changed files with 932 additions and 460 deletions
|
|
@ -24,7 +24,7 @@ include = [
|
|||
regex = "1"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
cc = "^1.0.58"
|
||||
|
||||
[lib]
|
||||
path = "binding_rust/lib.rs"
|
||||
|
|
|
|||
|
|
@ -1147,6 +1147,12 @@ impl<'a> TreeCursor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Clone for TreeCursor<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
TreeCursor(unsafe { ffi::ts_tree_cursor_copy(&self.0) }, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for TreeCursor<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::ts_tree_cursor_delete(&mut self.0) }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ WebAssembly bindings to the [Tree-sitter](https://github.com/tree-sitter/tree-si
|
|||
|
||||
### Setup
|
||||
|
||||
You can download the the `tree-sitter.js` and `tree-sitter.wasm` files from [the latest GitHub release](https://github.com/tree-sitter/tree-sitter/releases/tag/0.14.7) and load them using a standalone script:
|
||||
You can download the the `tree-sitter.js` and `tree-sitter.wasm` files from [the latest GitHub release](https://github.com/tree-sitter/tree-sitter/releases/latest) and load them using a standalone script:
|
||||
|
||||
```html
|
||||
<script src="/the/path/to/tree-sitter.js"/>
|
||||
|
|
|
|||
|
|
@ -184,6 +184,20 @@ TSTree *ts_parser_parse_wasm(
|
|||
return ts_parser_parse(self, old_tree, input);
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Section - Language */
|
||||
/**********************/
|
||||
|
||||
int ts_language_type_is_named_wasm(const TSLanguage *self, TSSymbol typeId) {
|
||||
const TSSymbolType symbolType = ts_language_symbol_type(self, typeId);
|
||||
return symbolType == TSSymbolTypeRegular;
|
||||
}
|
||||
|
||||
int ts_language_type_is_visible_wasm(const TSLanguage *self, TSSymbol typeId) {
|
||||
const TSSymbolType symbolType = ts_language_symbol_type(self, typeId);
|
||||
return symbolType <= TSSymbolTypeAnonymous;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Section - Tree */
|
||||
/******************/
|
||||
|
|
|
|||
|
|
@ -646,6 +646,32 @@ class Language {
|
|||
return this.fields[fieldId] || null;
|
||||
}
|
||||
|
||||
idForNodeType(type, named) {
|
||||
const typeLength = lengthBytesUTF8(type);
|
||||
const typeAddress = C._malloc(typeLength + 1);
|
||||
stringToUTF8(type, typeAddress, typeLength + 1);
|
||||
const result = C._ts_language_symbol_for_name(this[0], typeAddress, typeLength, named);
|
||||
C._free(typeAddress);
|
||||
return result || null;
|
||||
}
|
||||
|
||||
get nodeTypeCount() {
|
||||
return C._ts_language_symbol_count(this[0]);
|
||||
}
|
||||
|
||||
nodeTypeForId(typeId) {
|
||||
const name = C._ts_language_symbol_name(this[0], typeId);
|
||||
return name ? UTF8ToString(name) : null;
|
||||
}
|
||||
|
||||
nodeTypeIsNamed(typeId) {
|
||||
return C._ts_language_type_is_named_wasm(this[0], typeId) ? true : false;
|
||||
}
|
||||
|
||||
nodeTypeIsVisible(typeId) {
|
||||
return C._ts_language_type_is_visible_wasm(this[0], typeId) ? true : false;
|
||||
}
|
||||
|
||||
query(source) {
|
||||
const sourceLength = lengthBytesUTF8(source);
|
||||
const sourceAddress = C._malloc(sourceLength + 1);
|
||||
|
|
@ -856,30 +882,41 @@ class Language {
|
|||
);
|
||||
}
|
||||
|
||||
static load(url) {
|
||||
static load(input) {
|
||||
let bytes;
|
||||
if (
|
||||
typeof process !== 'undefined' &&
|
||||
process.versions &&
|
||||
process.versions.node
|
||||
) {
|
||||
const fs = require('fs');
|
||||
bytes = Promise.resolve(fs.readFileSync(url));
|
||||
if (input instanceof Uint8Array) {
|
||||
bytes = Promise.resolve(input);
|
||||
} else {
|
||||
bytes = fetch(url)
|
||||
.then(response => response.arrayBuffer()
|
||||
.then(buffer => {
|
||||
if (response.ok) {
|
||||
return new Uint8Array(buffer);
|
||||
} else {
|
||||
const body = new TextDecoder('utf-8').decode(buffer);
|
||||
throw new Error(`Language.load failed with status ${response.status}.\n\n${body}`)
|
||||
}
|
||||
}));
|
||||
const url = input;
|
||||
if (
|
||||
typeof process !== 'undefined' &&
|
||||
process.versions &&
|
||||
process.versions.node
|
||||
) {
|
||||
const fs = require('fs');
|
||||
bytes = Promise.resolve(fs.readFileSync(url));
|
||||
} else {
|
||||
bytes = fetch(url)
|
||||
.then(response => response.arrayBuffer()
|
||||
.then(buffer => {
|
||||
if (response.ok) {
|
||||
return new Uint8Array(buffer);
|
||||
} else {
|
||||
const body = new TextDecoder('utf-8').decode(buffer);
|
||||
throw new Error(`Language.load failed with status ${response.status}.\n\n${body}`)
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// emscripten-core/emscripten#12969
|
||||
const loadModule =
|
||||
typeof loadSideModule === 'function'
|
||||
? loadSideModule
|
||||
: loadWebAssemblyModule;
|
||||
|
||||
return bytes
|
||||
.then(bytes => loadSideModule(bytes, {loadAsync: true}))
|
||||
.then(bytes => loadModule(bytes, {loadAsync: true}))
|
||||
.then(mod => {
|
||||
const symbolNames = Object.keys(mod)
|
||||
const functionName = symbolNames.find(key =>
|
||||
|
|
@ -1139,3 +1176,4 @@ function marshalEdit(edit) {
|
|||
}
|
||||
|
||||
Parser.Language = Language;
|
||||
Parser.Parser = Parser;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@
|
|||
"_ts_init",
|
||||
"_ts_language_field_count",
|
||||
"_ts_language_field_name_for_id",
|
||||
"_ts_language_type_is_named_wasm",
|
||||
"_ts_language_type_is_visible_wasm",
|
||||
"_ts_language_symbol_count",
|
||||
"_ts_language_symbol_for_name",
|
||||
"_ts_language_symbol_name",
|
||||
"_ts_language_symbol_type",
|
||||
"_ts_language_version",
|
||||
|
|
@ -79,6 +82,7 @@
|
|||
"_ts_query_predicates_for_pattern",
|
||||
"_ts_query_string_count",
|
||||
"_ts_query_string_value_for_id",
|
||||
"_ts_tree_copy",
|
||||
"_ts_tree_cursor_current_field_id_wasm",
|
||||
"_ts_tree_cursor_current_node_id_wasm",
|
||||
"_ts_tree_cursor_current_node_is_missing_wasm",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "web-tree-sitter",
|
||||
"version": "0.17.1",
|
||||
"version": "0.18.0",
|
||||
"description": "Tree-sitter bindings for the web",
|
||||
"main": "tree-sitter.js",
|
||||
"types": "tree-sitter-web.d.ts",
|
||||
|
|
|
|||
44
lib/binding_web/test/language-test.js
Normal file
44
lib/binding_web/test/language-test.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
const { assert } = require("chai");
|
||||
let JavaScript;
|
||||
|
||||
describe("Language", () => {
|
||||
before(async () => ({ JavaScript } = await require("./helper")));
|
||||
|
||||
describe(".fieldIdForName, .fieldNameForId", () => {
|
||||
it("converts between the string and integer representations of fields", () => {
|
||||
const nameId = JavaScript.fieldIdForName("name");
|
||||
const bodyId = JavaScript.fieldIdForName("body");
|
||||
|
||||
assert.isBelow(nameId, JavaScript.fieldCount);
|
||||
assert.isBelow(bodyId, JavaScript.fieldCount);
|
||||
assert.equal("name", JavaScript.fieldNameForId(nameId));
|
||||
assert.equal("body", JavaScript.fieldNameForId(bodyId));
|
||||
});
|
||||
|
||||
it("handles invalid inputs", () => {
|
||||
assert.equal(null, JavaScript.fieldIdForName("namezzz"));
|
||||
assert.equal(null, JavaScript.fieldNameForId(-1));
|
||||
assert.equal(null, JavaScript.fieldNameForId(10000));
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
assert.isBelow(exportStatementId, JavaScript.nodeTypeCount);
|
||||
assert.isBelow(starId, JavaScript.nodeTypeCount);
|
||||
assert.equal(true, JavaScript.nodeTypeIsNamed(exportStatementId))
|
||||
assert.equal("export_statement", JavaScript.nodeTypeForId(exportStatementId))
|
||||
assert.equal(false, JavaScript.nodeTypeIsNamed(starId))
|
||||
assert.equal("*", JavaScript.nodeTypeForId(starId))
|
||||
});
|
||||
|
||||
it("handles invalid inputs", () => {
|
||||
assert.equal(null, JavaScript.nodeTypeForId(-1));
|
||||
assert.equal(null, JavaScript.nodeTypeForId(10000));
|
||||
assert.equal(null, JavaScript.idForNodeType("export_statement", false));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -323,6 +323,31 @@ describe("Tree", () => {
|
|||
assert(!cursor.gotoParent());
|
||||
})
|
||||
});
|
||||
|
||||
describe(".copy", () => {
|
||||
it("creates another tree that remains stable if the original tree is edited", () => {
|
||||
input = 'abc + cde';
|
||||
tree = parser.parse(input);
|
||||
assert.equal(
|
||||
tree.rootNode.toString(),
|
||||
"(program (expression_statement (binary_expression left: (identifier) right: (identifier))))"
|
||||
);
|
||||
|
||||
const tree2 = tree.copy();
|
||||
([input, edit] = spliceInput(input, 3, 0, '123'));
|
||||
assert.equal(input, 'abc123 + cde');
|
||||
tree.edit(edit);
|
||||
|
||||
const leftNode = tree.rootNode.firstChild.firstChild.firstChild;
|
||||
const leftNode2 = tree2.rootNode.firstChild.firstChild.firstChild;
|
||||
const rightNode = tree.rootNode.firstChild.firstChild.lastChild;
|
||||
const rightNode2 = tree2.rootNode.firstChild.firstChild.lastChild;
|
||||
assert.equal(leftNode.endIndex, 6)
|
||||
assert.equal(leftNode2.endIndex, 3)
|
||||
assert.equal(rightNode.startIndex, 9)
|
||||
assert.equal(rightNode2.startIndex, 6)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function spliceInput(input, startIndex, lengthRemoved, newText) {
|
||||
|
|
|
|||
7
lib/binding_web/tree-sitter-web.d.ts
vendored
7
lib/binding_web/tree-sitter-web.d.ts
vendored
|
|
@ -127,13 +127,18 @@ declare module 'web-tree-sitter' {
|
|||
}
|
||||
|
||||
class Language {
|
||||
static load(path: string): Promise<Language>;
|
||||
static load(input: string | Uint8Array): Promise<Language>;
|
||||
|
||||
readonly version: number;
|
||||
readonly fieldCount: number;
|
||||
readonly nodeTypeCount: number;
|
||||
|
||||
fieldNameForId(fieldId: number): string | null;
|
||||
fieldIdForName(fieldName: string): number | null;
|
||||
idForNodeType(type: string, named: boolean): number;
|
||||
nodeTypeForId(typeId: number): string | null;
|
||||
nodeTypeIsNamed(typeId: number): boolean;
|
||||
nodeTypeIsVisible(typeId: number): boolean;
|
||||
query(source: string): Query;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -448,6 +448,7 @@ TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *_cursor) {
|
|||
TSTreeCursor res = {NULL, NULL, {0, 0}};
|
||||
TreeCursor *copy = (TreeCursor *)&res;
|
||||
copy->tree = cursor->tree;
|
||||
array_init(©->stack);
|
||||
array_push_all(©->stack, &cursor->stack);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue