diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..095d62c1
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = off
+
+[*.{cc,h}]
+max_line_length = 120
+
+[*.js]
+max_line_length = 120
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..f64d1130
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,44 @@
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ day: sunday
+ cooldown:
+ default-days: 3
+ commit-message:
+ prefix: ci
+ labels: [dependencies]
+ open-pull-requests-limit: 1
+ groups:
+ actions:
+ patterns: ["*"]
+
+ - package-ecosystem: gitsubmodule
+ directory: /
+ schedule:
+ interval: weekly
+ day: friday
+ commit-message:
+ prefix: build
+ labels: [dependencies]
+ open-pull-requests-limit: 1
+ groups:
+ submodules:
+ patterns: ["*"]
+
+ - package-ecosystem: npm
+ directory: /
+ schedule:
+ interval: weekly
+ day: saturday
+ cooldown:
+ default-days: 3
+ commit-message:
+ prefix: build
+ labels: [dependencies]
+ open-pull-requests-limit: 1
+ groups:
+ npm:
+ patterns: ["*"]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e7443f06..bd8add23 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,11 +2,9 @@ name: CI
on:
push:
- branches:
- - master
+ branches: [master]
pull_request:
- branches:
- - master
+ branches: [master]
workflow_call:
concurrency:
@@ -18,58 +16,49 @@ jobs:
strategy:
matrix:
os:
- - windows-latest
- - macos-latest
+ - windows-2022
+ - windows-11-arm
+ - macos-15
+ - macos-13
- ubuntu-22.04
+ - ubuntu-22.04-arm
node:
- - 18
- - 20
- - 22
+ - 20.19.5
+ - 22.19.0
+ - 24.7.0
fail-fast: false
- name: Test Node ${{ matrix.node }} on ${{ matrix.os }}
- runs-on: ${{ matrix.os }}
+ name: Test Node ${{matrix.node}} on ${{matrix.os}}
+ runs-on: ${{matrix.os}}
defaults:
run:
shell: bash
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
submodules: true
- fetch-depth: 0
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
- node-version: ${{ matrix.node }}
-
- - name: Install dependencies
- run: npm ci --legacy-peer-deps
+ node-version: ${{matrix.node}}
- name: Set npm_config_target
- run: echo "CONFIG_TARGET=${{ matrix.node == 22 && '22.12.0' || '20.9.0' }}" >> $GITHUB_ENV
+ run: printf 'npm_config_target=${{matrix.node}}\n' >> "$GITHUB_ENV"
- - name: Build x64 binary
- run: npm_config_target=${{ env.CONFIG_TARGET }} npm x -- prebuildify --napi --arch x64 -t 20.9.0
-
- - name: Set up cross-compilation
- if: runner.os == 'Linux'
- run: |-
- sudo apt-get update
- sudo apt-get install g++-aarch64-linux-gnu
- printf '%s\n' >> "$GITHUB_ENV" \
- 'CC=aarch64-linux-gnu-gcc' 'CXX=aarch64-linux-gnu-g++'
+ - name: Install dependencies
+ run: npm ci --legacy-peer-deps
- - name: Build arm64 binary
- run: npm_config_target=${{ env.CONFIG_TARGET }} npm x -- prebuildify --napi --arch arm64 -t 20.9.0
+ - name: Build binary
+ run: npm x -- prebuildify --napi
- name: Run tests
run: npm test
- name: Upload prebuilds
uses: actions/upload-artifact@v4
- if: github.ref_type == 'tag' && matrix.node == 20
+ if: github.ref_type == 'tag' && startsWith(matrix.node, '20')
with:
path: prebuilds/**
- name: prebuilds-${{matrix.os}}
+ name: prebuilds-${{runner.os}}-${{runner.arch}}
retention-days: 2
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 430536af..bbd00328 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -26,12 +26,11 @@ jobs:
url: ${{steps.deployment.outputs.page_url}}
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
submodules: true
- fetch-depth: 0
- name: Setup Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
@@ -40,7 +39,7 @@ jobs:
- name: Generate documentation
run: npm run docs
- name: Upload pages artifact
- uses: actions/upload-pages-artifact@v3
+ uses: actions/upload-pages-artifact@v4
with:
path: docs/api
- name: Deploy to GitHub Pages
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 9af6b721..8cba229b 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,22 +12,26 @@ jobs:
publish:
name: Publish
runs-on: ubuntu-latest
+ environment: npm
+ permissions:
+ id-token: write
+ attestations: write
+ contents: read
needs: build
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: true
- fetch-depth: 0
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
node-version: 20
registry-url: https://registry.npmjs.org
- name: Download prebuilds
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v5
with:
path: prebuilds
pattern: prebuilds-*
@@ -41,8 +45,6 @@ jobs:
- name: Publish to NPM
run: npm publish
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Prepare release artifacts
run: |
@@ -53,8 +55,12 @@ jobs:
done
ls -l dist
+ - name: Generate attestations
+ uses: actions/attest-build-provenance@v3
+ with:
+ subject-path: dist/*
+
- name: Create release
- run: |-
- gh release create ${{ github.ref_name }} --generate-notes dist/*
+ run: gh release create "$GITHUB_REF_NAME" --generate-notes dist/*
env:
- GH_TOKEN: ${{ github.token }}
+ GH_TOKEN: ${{github.token}}
diff --git a/.gitmodules b/.gitmodules
index 08707772..fa31e810 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
[submodule "vendor/tree-sitter"]
path = vendor/tree-sitter
url = https://github.com/tree-sitter/tree-sitter.git
+ branch = release-0.25
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index 9c85d0f6..00000000
--- a/.npmignore
+++ /dev/null
@@ -1,12 +0,0 @@
-test
-
-out
-build
-prebuilds
-
-vendor/tree-sitter/**/*
-!vendor/tree-sitter/lib/src/**/*.{c,h}
-!vendor/tree-sitter/lib/include/tree_sitter/api.h
-
-.github/
-.vscode/
diff --git a/binding.gyp b/binding.gyp
index bb40aa7e..21f3de80 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -24,14 +24,11 @@
"defines": [
"NAPI_VERSION=<(napi_build_version)",
],
- "cflags_cc": [
- "-std=c++17"
- ],
"conditions": [
["OS=='mac'", {
"xcode_settings": {
"GCC_SYMBOLS_PRIVATE_EXTERN": "YES", # -fvisibility=hidden
- "CLANG_CXX_LANGUAGE_STANDARD": "c++17",
+ "CLANG_CXX_LANGUAGE_STANDARD": "<(cxxstd)",
"MACOSX_DEPLOYMENT_TARGET": "10.9",
},
}],
@@ -39,7 +36,7 @@
"msvs_settings": {
"VCCLCompilerTool": {
"AdditionalOptions": [
- "/std:c++17",
+ "/std:<(cxxstd)",
],
"RuntimeLibrary": 0,
},
@@ -47,7 +44,9 @@
}],
["OS == 'linux'", {
"cflags_cc": [
- "-Wno-cast-function-type"
+ "-std=<(cxxstd)",
+ "-fvisibility=hidden",
+ "-Wno-cast-function-type",
]
}],
]
@@ -62,13 +61,21 @@
"vendor/tree-sitter/lib/src",
"vendor/tree-sitter/lib/include",
],
- "cflags": [
- "-std=c11"
- ],
"defines": [
"_POSIX_C_SOURCE=200112L",
"_DEFAULT_SOURCE",
- ]
+ ],
+ "conditions": [
+ ["OS!='win'", {
+ "cflags_c": [
+ "-std=c11",
+ ],
+ }, { # OS == "win"
+ "cflags_c": [
+ "/std:c11",
+ ],
+ }],
+ ],
}
],
"variables": {
@@ -76,5 +83,6 @@
"openssl_fips": "",
"v8_enable_pointer_compression%": 0,
"v8_enable_31bit_smis_on_64bit_arch%": 0,
+ "cxxstd%": " 22 ? 'c++20' : 'c++17'\")",
}
}
diff --git a/index.js b/index.js
index 9a57b365..0bf3bef5 100644
--- a/index.js
+++ b/index.js
@@ -18,10 +18,10 @@ Object.defineProperty(Tree.prototype, 'rootNode', {
Due to a race condition arising from Jest's worker pool, "this"
has no knowledge of the native extension if the extension has not
yet loaded when multiple Jest tests are being run simultaneously.
- If the extension has correctly loaded, "this" should be an instance
+ If the extension has correctly loaded, "this" should be an instance
of the class whose prototype we are acting on (in this case, Tree).
- Furthermore, the race condition sometimes results in the function in
- question being undefined even when the context is correct, so we also
+ Furthermore, the race condition sometimes results in the function in
+ question being undefined even when the context is correct, so we also
perform a null function check.
*/
if (this instanceof Tree && rootNode) {
@@ -61,7 +61,10 @@ Tree.prototype.walk = function() {
class SyntaxNode {
constructor(tree) {
- this.tree = tree;
+ Object.defineProperty(this, 'tree', {
+ value: tree,
+ enumerable: true
+ });
}
[util.inspect.custom]() {
@@ -239,6 +242,15 @@ class SyntaxNode {
return NodeMethods.toString(this.tree);
}
+ toJSON() {
+ return {
+ type: this.type,
+ startPosition: this.startPosition,
+ endPosition: this.endPosition,
+ childCount: this.childCount,
+ }
+ }
+
child(index) {
marshalNode(this);
return unmarshalNode(NodeMethods.child(this.tree, index), this.tree);
@@ -855,7 +867,8 @@ function initializeLanguageNodeClasses(language) {
const nodeTypeInfo = language.nodeTypeInfo || [];
const nodeSubclasses = [];
- for (let id = 0, n = nodeTypeNamesById.length; id < n; id++) {
+
+ for (let id = 0, n = nodeTypeNamesById.length; id < n; ++id) {
nodeSubclasses[id] = SyntaxNode;
const typeName = nodeTypeNamesById[id];
@@ -865,7 +878,8 @@ function initializeLanguageNodeClasses(language) {
if (!typeInfo) continue;
const fieldNames = [];
- let classBody = '\n';
+ const fieldGetters = {};
+
if (typeInfo.fields) {
for (const fieldName in typeInfo.fields) {
const fieldId = nodeFieldNamesById.indexOf(fieldName);
@@ -873,35 +887,54 @@ function initializeLanguageNodeClasses(language) {
if (typeInfo.fields[fieldName].multiple) {
const getterName = camelCase(fieldName) + 'Nodes';
fieldNames.push(getterName);
- classBody += `
- get ${getterName}() {
+ fieldGetters[getterName] = {
+ get: function () {
marshalNode(this);
- return unmarshalNodes(NodeMethods.childNodesForFieldId(this.tree, ${fieldId}), this.tree);
- }
- `.replace(/\s+/g, ' ') + '\n';
+ return unmarshalNodes(
+ NodeMethods.childNodesForFieldId(this.tree, fieldId),
+ this.tree
+ );
+ },
+ enumerable: true
+ };
} else {
const getterName = camelCase(fieldName, false) + 'Node';
fieldNames.push(getterName);
- classBody += `
- get ${getterName}() {
+ fieldGetters[getterName] = {
+ get: function () {
marshalNode(this);
- return unmarshalNode(NodeMethods.childNodeForFieldId(this.tree, ${fieldId}), this.tree);
- }
- `.replace(/\s+/g, ' ') + '\n';
+ return unmarshalNode(
+ NodeMethods.childNodeForFieldId(this.tree, fieldId),
+ this.tree
+ );
+ },
+ enumerable: true
+ };
}
}
}
- const className = camelCase(typeName, true) + 'Node';
- const nodeSubclass = eval(`class ${className} extends SyntaxNode {${classBody}}; ${className}`);
- nodeSubclass.prototype.type = typeName;
- nodeSubclass.prototype.fields = Object.freeze(fieldNames.sort())
- nodeSubclasses[id] = nodeSubclass;
+ nodeSubclasses[id] = new Function('SyntaxNode', `
+ return class ${camelCase(typeName, true)}Node extends SyntaxNode {}
+ `)(SyntaxNode);
+
+ Object.defineProperties(nodeSubclasses[id].prototype, {
+ type: {
+ value: typeName,
+ enumerable: true
+ },
+ fields: {
+ value: Object.freeze(fieldNames.sort()),
+ enumerable: true
+ },
+ ...fieldGetters
+ });
}
- language.nodeSubclasses = nodeSubclasses
+ language.nodeSubclasses = nodeSubclasses;
}
+
function camelCase(name, upperCase) {
name = name.replace(/_(\w)/g, (_match, letter) => letter.toUpperCase());
if (upperCase) name = name[0].toUpperCase() + name.slice(1);
diff --git a/test/lookahead_iterable_test.js b/test/lookahead_iterable_test.js
index 0cd3caa7..dd237841 100644
--- a/test/lookahead_iterable_test.js
+++ b/test/lookahead_iterable_test.js
@@ -1,4 +1,5 @@
-/** @type {typeof import('tree-sitter')} */
+///
+/** @type {typeof import("tree-sitter")} */
const Parser = require("../index.js");
const Rust = require("tree-sitter-rust");
const assert = require('node:assert');
diff --git a/test/node_test.js b/test/node_test.js
index 8424f517..c6c1fe1a 100644
--- a/test/node_test.js
+++ b/test/node_test.js
@@ -1,5 +1,6 @@
-/** @type {typeof import('tree-sitter')} */
-const Parser = require("../index.js");
+///
+/** @type {typeof import("tree-sitter")} */
+const Parser = require("../index");
const C = require('tree-sitter-c');
const EmbeddedTemplate = require('tree-sitter-embedded-template');
@@ -64,17 +65,15 @@ describe("Node", () => {
`);
const classNode = tree.rootNode.firstChild;
- // @ts-ignore
assert.deepEqual(classNode.fields, ['bodyNode', 'decoratorNodes', 'nameNode'])
- // @ts-ignore
const methodNode = classNode.bodyNode.firstNamedChild;
assert.equal(methodNode.constructor.name, 'MethodDefinitionNode');
assert.equal(methodNode.nameNode.text, 'b');
assert.deepEqual(methodNode.fields, ['bodyNode', 'decoratorNodes', 'nameNode', 'parametersNode'])
const decoratorNodes = methodNode.decoratorNodes;
- assert.deepEqual(decoratorNodes.map(_ => _.text), ['@autobind', '@something'])
+ assert.deepEqual(decoratorNodes.map(n => n.text), ['@autobind', '@something'])
const paramsNode = methodNode.parametersNode;
assert.equal(paramsNode.constructor.name, 'FormalParametersNode');
@@ -707,14 +706,14 @@ describe("Node", () => {
describe(".text", () => {
Object.entries({
- '.parse(String)': (parser, src) => parser.parse(src),
- '.parse(Function)': (parser, src) =>
- parser.parse(offset => src.substr(offset, 4)),
+ '.parse(String)': (/** @type {import('tree-sitter')} */ parser, /** @type {string} */ src) => parser.parse(src),
+ '.parse(Function)': (/** @type {import('tree-sitter')} */ parser, /** @type {string} */ src) =>
+ parser.parse(offset => src.substring(offset, offset + 4)),
}).forEach(([method, parse]) =>
it(`returns the text of a node generated by ${method}`, async () => {
const src = "α0 / b👎c👎"
const [numeratorSrc, denominatorSrc] = src.split(/\s*\/\s+/)
- const tree = await parse(parser, src)
+ const tree = parse(parser, src)
const quotientNode = tree.rootNode.firstChild.firstChild;
const [numerator, slash, denominator] = quotientNode.children;
@@ -921,10 +920,8 @@ describe("Node", () => {
it("shouldn't segfault when accessing properties on the prototype", () => {
const tree = parser.parse('2 + 2');
const nodePrototype = Object.getPrototypeOf(tree.rootNode);
- // const nodePrototype = tree.rootNode.__proto__;
const properties = [
- "type",
"typeId",
"isNamed",
"isMissing",
@@ -950,6 +947,9 @@ describe("Node", () => {
"previousSibling",
"previousNamedSibling",
];
+ if (nodePrototype.constructor.name === "SyntaxNode") {
+ assert.throws(() => { nodePrototype.type; }, TypeError)
+ }
for (const property of properties) {
assert.throws(() => { nodePrototype[property]; }, TypeError)
}
diff --git a/test/parser_test.js b/test/parser_test.js
index 11dd2b12..0f9099d2 100644
--- a/test/parser_test.js
+++ b/test/parser_test.js
@@ -1,4 +1,5 @@
-/** @type {typeof import('tree-sitter')} */
+///
+/** @type {typeof import("tree-sitter")} */
const Parser = require("../index.js");
const HTML = require('tree-sitter-html');
const JavaScript = require('tree-sitter-javascript');
@@ -17,6 +18,7 @@ describe("Parser", () => {
describe(".setLanguage", () => {
it("throws an exception when the supplied object is not a tree-sitter language", () => {
+ // @ts-expect-error: Invalid language
assert.throws(() => parser.setLanguage({}), /Invalid language/);
assert.throws(() => parser.setLanguage(undefined), /Invalid language/);
});
@@ -166,7 +168,7 @@ describe("Parser", () => {
describe("when the input callback returns something other than a string", () => {
it("stops reading", () => {
- const parts = ["abc", "def", "ghi", {}, {}, {}, "second-word", " "];
+ const parts = ["abc", "def", "ghi", null, null, null, "second-word", " "];
const tree = parser.parse(() => parts.shift());
assert.equal(
tree.rootNode.toString(),
diff --git a/test/query_test.js b/test/query_test.js
index 05ce1a34..da7e86df 100644
--- a/test/query_test.js
+++ b/test/query_test.js
@@ -1,4 +1,5 @@
-/** @type {typeof import('tree-sitter')} */
+///
+/** @type {typeof import("tree-sitter")} */
const Parser = require("../index.js");
const C = require("tree-sitter-c");
diff --git a/test/tree_test.js b/test/tree_test.js
index 924aa601..d6a4a469 100644
--- a/test/tree_test.js
+++ b/test/tree_test.js
@@ -1,4 +1,5 @@
-/** @type {typeof import('tree-sitter')} */
+///
+/** @type {typeof import("tree-sitter")} */
const Parser = require("../index.js");
const JavaScript = require('tree-sitter-javascript');
const Rust = require('tree-sitter-rust');
diff --git a/tree-sitter.d.ts b/tree-sitter.d.ts
index 4fd5c601..c964a9b7 100644
--- a/tree-sitter.d.ts
+++ b/tree-sitter.d.ts
@@ -187,13 +187,13 @@ declare module "tree-sitter" {
* @param position - Optional position in the text as {row, column}
* @returns A string chunk, or null/undefined if no text at this index
*/
- (index: number, position?: Point): string | null | undefined | {};
+ (index: number, position?: Point): string | null | undefined;
}
/** The syntax tree that contains this node */
export interface SyntaxNode {
/** The syntax tree that contains this node */
- tree: Tree;
+ readonly tree: Tree;
/**
* A unique numeric identifier for this node.
@@ -201,145 +201,155 @@ declare module "tree-sitter" {
* If a new tree is created based on an older tree and reuses
* a node, that node will have the same id in both trees.
*/
- id: number;
+ readonly id: number;
/**
* This node's type as a numeric id
*/
- typeId: number;
+ readonly typeId: number;
/**
* This node's type as a numeric id as it appears in the grammar,
* ignoring aliases
*/
- grammarId: number;
+ readonly grammarId: number;
/**
* This node's type as a string
*/
- type: string;
+ readonly type: string;
/**
* This node's symbol name as it appears in the grammar,
* ignoring aliases
*/
- grammarType: string;
+ readonly grammarType: string;
/**
* Whether this node is named.
* Named nodes correspond to named rules in the grammar,
* whereas anonymous nodes correspond to string literals in the grammar.
*/
- isNamed: boolean;
+ readonly isNamed: boolean;
/**
* Whether this node is missing.
* Missing nodes are inserted by the parser in order to
* recover from certain kinds of syntax errors.
*/
- isMissing: boolean;
+ readonly isMissing: boolean;
/**
* Whether this node is extra.
* Extra nodes represent things like comments, which are not
* required by the grammar but can appear anywhere.
*/
- isExtra: boolean;
+ readonly isExtra: boolean;
/**
* Whether this node has been edited
*/
- hasChanges: boolean;
+ readonly hasChanges: boolean;
/**
* Whether this node represents a syntax error or contains
* any syntax errors within it
*/
- hasError: boolean;
+ readonly hasError: boolean;
/**
* Whether this node represents a syntax error.
* Syntax errors represent parts of the code that could not
* be incorporated into a valid syntax tree.
*/
- isError: boolean;
+ readonly isError: boolean;
/** The text content for this node from the source code */
- text: string;
+ readonly text: string;
/** The parse state of this node */
- parseState: number;
+ readonly parseState: number;
/** The parse state that follows this node */
- nextParseState: number;
+ readonly nextParseState: number;
/** The position where this node starts in terms of rows and columns */
- startPosition: Point;
+ readonly startPosition: Point;
/** The position where this node ends in terms of rows and columns */
- endPosition: Point;
+ readonly endPosition: Point;
/** The byte offset where this node starts */
- startIndex: number;
+ readonly startIndex: number;
/** The byte offset where this node ends */
- endIndex: number;
+ readonly endIndex: number;
/**
* This node's immediate parent.
* For iterating over ancestors, prefer using {@link childWithDescendant}
*/
- parent: SyntaxNode | null;
+ readonly parent: SyntaxNode | null;
/** Array of all child nodes */
- children: Array;
+ readonly children: Array;
/** Array of all named child nodes */
- namedChildren: Array;
+ readonly namedChildren: Array;
/** The number of children this node has */
- childCount: number;
+ readonly childCount: number;
/**
* The number of named children this node has.
* @see {@link isNamed}
*/
- namedChildCount: number;
+ readonly namedChildCount: number;
/** The first child of this node */
- firstChild: SyntaxNode | null;
+ readonly firstChild: SyntaxNode | null;
/** The first named child of this node */
- firstNamedChild: SyntaxNode | null;
+ readonly firstNamedChild: SyntaxNode | null;
/** The last child of this node */
- lastChild: SyntaxNode | null;
+ readonly lastChild: SyntaxNode | null;
/** The last child of this node */
- lastNamedChild: SyntaxNode | null;
+ readonly lastNamedChild: SyntaxNode | null;
/** This node's next sibling */
- nextSibling: SyntaxNode | null;
+ readonly nextSibling: SyntaxNode | null;
/** This node's next named sibling */
- nextNamedSibling: SyntaxNode | null;
+ readonly nextNamedSibling: SyntaxNode | null;
/** This node's previous sibling */
- previousSibling: SyntaxNode | null;
+ readonly previousSibling: SyntaxNode | null;
/** This node's previous named sibling */
- previousNamedSibling: SyntaxNode | null;
+ readonly previousNamedSibling: SyntaxNode | null;
/**
* The number of descendants this node has, including itself
*/
- descendantCount: number;
+ readonly descendantCount: number;
+
+ /**
+ * The names of extra fields available in the subclass, if any.
+ */
+ readonly fields: Array<`${string}Node` | `${string}Nodes`>;
/**
* Convert this node to its string representation
*/
toString(): string;
+ /**
+ * Convert this node to its JSON representation
+ */
+ toJSON(): object;
+
/**
* Get the node's child at the given index, where zero represents the first child.
*
@@ -544,6 +554,10 @@ declare module "tree-sitter" {
* @returns A new cursor positioned at this node
*/
walk(): TreeCursor;
+
+ readonly [name: `${string}Node`]: SyntaxNode;
+
+ readonly [name: `${string}Nodes`]: Array;
}
/** A stateful object for walking a syntax {@link Tree} efficiently */
@@ -626,7 +640,7 @@ declare module "tree-sitter" {
/**
* Move this cursor to the last child of its current node.
- * Note: This may be slower than gotoFirstChild() as it needs to iterate
+ * Note: This may be slower than gotoFirstChild() as it needs to iterate
* through all children to compute the position.
*
* @returns true if cursor successfully moved, false if there were no children
@@ -696,7 +710,7 @@ declare module "tree-sitter" {
/**
* Edit the syntax tree to keep it in sync with source code that has been edited.
- * The edit must be described both in terms of byte offsets and in terms of
+ * The edit must be described both in terms of byte offsets and in terms of
* row/column coordinates.
*
* @param edit - The edit to apply to the tree
@@ -720,11 +734,11 @@ declare module "tree-sitter" {
getText(node: SyntaxNode): string;
/**
- * Compare this edited syntax tree to a new syntax tree representing the
+ * Compare this edited syntax tree to a new syntax tree representing the
* same document, returning ranges whose syntactic structure has changed.
*
* For this to work correctly, this tree must have been edited to match
- * the new tree's ranges. Generally, you'll want to call this right after
+ * the new tree's ranges. Generally, you'll want to call this right after
* parsing, using the old tree that was passed to parse and the new tree
* that was returned.
*
@@ -771,7 +785,7 @@ declare module "tree-sitter" {
* A match of a {@link Query} to a particular set of {@link SyntaxNode}s.
*/
export interface QueryMatch {
- /**
+ /**
* The index of the pattern that was matched.
* Each pattern in a query is assigned a numeric index in sequence.
*/
@@ -950,7 +964,7 @@ declare module "tree-sitter" {
* This returns `null` if the state is invalid for this language.
*
* Iterating {@link LookaheadIterator} will yield valid symbols in the given
- * parse state. Newly created lookahead iterators will have {@link currentType}
+ * parse state. Newly created lookahead iterators will have {@link currentType}
* populated with the `ERROR` symbol.
*
* Lookahead iterators can be useful to generate suggestions and improve
@@ -1030,9 +1044,9 @@ declare module "tree-sitter" {
/** Information about a language */
interface Language {
/** The name of the language */
- name: string;
+ name?: string;
/** The inner language object */
- language: Language;
+ language: unknown;
/** The node type information of the language */
nodeTypeInfo: NodeInfo[];
}
diff --git a/tsconfig.json b/tsconfig.json
index 2873553e..47536892 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,19 +1,19 @@
{
- "compilerOptions": {
- "checkJs": true,
- "allowJs": true,
- "noEmit": true,
- "strict": true,
- "strictNullChecks": false,
- "noImplicitAny": false,
- "lib": [
- "es2020"
- ]
- },
- "include": [
- "./test/*.js"
- ],
- "exclude": [
- "node_modules"
- ]
+ "compilerOptions": {
+ "checkJs": true,
+ "allowJs": true,
+ "noEmit": true,
+ "strict": true,
+ "strictNullChecks": false,
+ "noImplicitAny": false,
+ "lib": [
+ "ES2020"
+ ]
+ },
+ "include": [
+ "test/*.js"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/tsconfig.typedoc.json b/tsconfig.typedoc.json
index ca60b972..63b6c640 100644
--- a/tsconfig.typedoc.json
+++ b/tsconfig.typedoc.json
@@ -1,8 +1,8 @@
{
- "compilerOptions": {
- "allowJs": false
- },
- "include": [
- "./tree-sitter.d.ts"
- ]
+ "compilerOptions": {
+ "allowJs": false
+ },
+ "include": [
+ "tree-sitter.d.ts"
+ ]
}
diff --git a/typedoc.json b/typedoc.json
index e37793a5..7f5de385 100644
--- a/typedoc.json
+++ b/typedoc.json
@@ -2,7 +2,7 @@
"$schema": "https://typedoc.org/schema.json",
"entryPoints": ["tree-sitter.d.ts"],
"entryPointStrategy": "expand",
- "tsconfig": "./tsconfig.typedoc.json",
+ "tsconfig": "tsconfig.typedoc.json",
"out": "docs/api",
"readme": "README.md",
"cleanOutputDir": true,
diff --git a/vendor/tree-sitter b/vendor/tree-sitter
index 460118b4..a467ea85 160000
--- a/vendor/tree-sitter
+++ b/vendor/tree-sitter
@@ -1 +1 @@
-Subproject commit 460118b4c82318b083b4d527c9c750426730f9c0
+Subproject commit a467ea8502d95562171f97953a6dc5b2a8622609