CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-web-tree-sitter

Tree-sitter bindings for the web providing WebAssembly-based incremental parsing of source code

Pending
Overview
Eval results
Files

tree-node.mddocs/

Tree & Node

Syntax tree navigation and manipulation functionality. Trees represent the complete parsed structure of source code, while Nodes represent individual elements within the tree hierarchy.

Tree Capabilities

Tree Creation and Management

Trees are created by parsers and represent immutable syntax structures.

/**
 * Create a shallow copy of the syntax tree (very fast operation)
 * @returns New Tree instance sharing internal structure
 */
copy(): Tree;

/**
 * Delete the syntax tree and free its resources
 */
delete(): void;

/** The language that was used to parse the syntax tree */
language: Language;

Root Node Access

Access the root node of the syntax tree.

/**
 * Get the root node of the syntax tree
 */
get rootNode(): Node;

/**
 * Get the root node with its position shifted forward by the given offset
 * @param offsetBytes - Byte offset to apply
 * @param offsetExtent - Point offset to apply
 * @returns Root node with adjusted position
 */
rootNodeWithOffset(offsetBytes: number, offsetExtent: Point): Node;

Usage Example:

const tree = parser.parse("let x = 1 + 2;");
const root = tree.rootNode;

console.log(root.type); // "program"
console.log(root.toString()); // S-expression representation

// Get root with offset (useful for embedded parsing)
const offsetRoot = tree.rootNodeWithOffset(10, { row: 1, column: 0 });

Tree Editing

Synchronize trees with source code changes for incremental parsing.

/**
 * Edit the syntax tree to keep it in sync with source code changes
 * @param edit - Description of the edit in both byte offsets and row/column coordinates
 */
edit(edit: Edit): void;

/**
 * Compare this tree to a new tree and get ranges where structure changed
 * @param other - New tree representing the same document after edits
 * @returns Array of ranges with syntactic structure changes
 */
getChangedRanges(other: Tree): Range[];

Usage Example:

const tree = parser.parse("let x = 1;");

// Edit the tree to reflect source change: "let x = 1;" → "let x = 42;"
tree.edit({
  startIndex: 8,
  oldEndIndex: 9,
  newEndIndex: 10,
  startPosition: { row: 0, column: 8 },
  oldEndPosition: { row: 0, column: 9 },
  newEndPosition: { row: 0, column: 10 }
});

// Parse the updated source
const newTree = parser.parse("let x = 42;", tree);

// Get changed ranges
const changes = tree.getChangedRanges(newTree);
console.log("Changed ranges:", changes);

Tree Navigation

Create tree cursors and access parsing ranges.

/**
 * Create a new TreeCursor starting from the root of the tree
 * @returns TreeCursor for efficient tree traversal
 */
walk(): TreeCursor;

/**
 * Get the included ranges that were used to parse the syntax tree
 * @returns Array of ranges that were included during parsing
 */
getIncludedRanges(): Range[];

Node Capabilities

Node Identity and Position

Access node identification and location information.

/** Unique numeric ID for this node within the tree */
id: number;

/** The byte index where this node starts */
startIndex: number;

/** The position where this node starts */
startPosition: Point;

/** The tree that this node belongs to */
tree: Tree;

/**
 * Get the byte index where this node ends
 */
get endIndex(): number;

/**
 * Get the position where this node ends
 */
get endPosition(): Point;

Node Type Information

Access node type and classification details.

/**
 * Get this node's type as a numerical id
 */
get typeId(): number;

/**
 * Get the node's type as a numerical id as it appears in the grammar, ignoring aliases
 */
get grammarId(): number;

/**
 * Get this node's type as a string
 */
get type(): string;

/**
 * Get this node's symbol name as it appears in the grammar, ignoring aliases
 */
get grammarType(): string;

Usage Example:

const root = tree.rootNode;
const firstChild = root.firstChild;

if (firstChild) {
  console.log("Type:", firstChild.type); // e.g., "lexical_declaration"
  console.log("Type ID:", firstChild.typeId); // e.g., 42
  console.log("Grammar type:", firstChild.grammarType);
  console.log("Position:", firstChild.startPosition); // { row: 0, column: 0 }
  console.log("Byte range:", firstChild.startIndex, "-", firstChild.endIndex);
}

Node Classification

Check node properties and error states.

/**
 * Check if this node is named (corresponds to named rules in grammar)
 */
get isNamed(): boolean;

/**
 * Check if this node is extra (like comments, not required by grammar)
 */
get isExtra(): boolean;

/**
 * Check if this node represents a syntax error
 */
get isError(): boolean;

/**
 * Check if this node is missing (inserted by parser for error recovery)
 */
get isMissing(): boolean;

/**
 * Check if this node has been edited
 */
get hasChanges(): boolean;

/**
 * Check if this node contains any syntax errors anywhere within it
 */
get hasError(): boolean;

Node Content and State

Access node text content and parse state information.

/**
 * Get the string content of this node
 */
get text(): string;

/**
 * Get this node's parse state
 */
get parseState(): number;

/**
 * Get the parse state after this node
 */
get nextParseState(): number;

Node Comparison

Compare nodes for equality.

/**
 * Check if this node is equal to another node
 * @param other - Node to compare with
 * @returns True if nodes are equal
 */
equals(other: Node): boolean;

Child Node Access

Access child nodes by index and field.

/**
 * Get the node's child at the given index (0-based)
 * @param index - Child index to retrieve
 * @returns Child node or null if index is out of bounds
 */
child(index: number): Node | null;

/**
 * Get this node's named child at the given index
 * @param index - Named child index to retrieve
 * @returns Named child node or null if index is out of bounds
 */
namedChild(index: number): Node | null;

/**
 * Get this node's child with the given numerical field id
 * @param fieldId - Field ID to look up
 * @returns Child node or null if no child has this field
 */
childForFieldId(fieldId: number): Node | null;

/**
 * Get the first child with the given field name
 * @param fieldName - Field name to look up
 * @returns Child node or null if no child has this field
 */
childForFieldName(fieldName: string): Node | null;

Usage Examples:

const statement = tree.rootNode.firstChild; // e.g., "lexical_declaration"

if (statement) {
  // Access by index
  const firstChild = statement.child(0); // e.g., "let" keyword
  
  // Access by field name
  const declarations = statement.childForFieldName("declarations");
  
  // Get field names
  const fieldName = statement.fieldNameForChild(1);
  console.log("Field name for child 1:", fieldName);
}

Field Name Lookup

Get field names for child nodes.

/**
 * Get the field name of this node's child at the given index
 * @param index - Child index to check
 * @returns Field name or null if child has no field name
 */
fieldNameForChild(index: number): string | null;

/**
 * Get the field name of this node's named child at the given index
 * @param index - Named child index to check
 * @returns Field name or null if child has no field name
 */
fieldNameForNamedChild(index: number): string | null;

Multiple Children Access

Get arrays of children by field.

/**
 * Get an array of this node's children with a given field name
 * @param fieldName - Field name to filter by
 * @returns Array of child nodes with the given field name
 */
childrenForFieldName(fieldName: string): (Node | null)[];

/**
 * Get an array of this node's children with a given field id
 * @param fieldId - Field ID to filter by
 * @returns Array of child nodes with the given field ID
 */
childrenForFieldId(fieldId: number): (Node | null)[];

Child Navigation by Position

Find children by byte offset.

/**
 * Get the node's first child that contains or starts after the given byte offset
 * @param index - Byte offset to search from
 * @returns Child node or null if no such child exists
 */
firstChildForIndex(index: number): Node | null;

/**
 * Get the node's first named child that contains or starts after the given byte offset
 * @param index - Byte offset to search from
 * @returns Named child node or null if no such child exists
 */
firstNamedChildForIndex(index: number): Node | null;

Child Counts and Direct Access

Get child counts and direct child access.

/**
 * Get this node's number of children
 */
get childCount(): number;

/**
 * Get this node's number of named children
 */
get namedChildCount(): number;

/**
 * Get this node's first child
 */
get firstChild(): Node | null;

/**
 * Get this node's first named child
 */
get firstNamedChild(): Node | null;

/**
 * Get this node's last child
 */
get lastChild(): Node | null;

/**
 * Get this node's last named child
 */
get lastNamedChild(): Node | null;

/**
 * Get array of all children
 */
get children(): (Node | null)[];

/**
 * Get array of all named children
 */
get namedChildren(): (Node | null)[];

Sibling Navigation

Navigate between sibling nodes.

/**
 * Get this node's next sibling
 */
get nextSibling(): Node | null;

/**
 * Get this node's previous sibling
 */
get previousSibling(): Node | null;

/**
 * Get this node's next named sibling
 */
get nextNamedSibling(): Node | null;

/**
 * Get this node's previous named sibling
 */
get previousNamedSibling(): Node | null;

Descendant Operations

Work with descendant nodes in the subtree.

/**
 * Get the descendants of this node that are the given type(s)
 * @param types - Node type name or array of type names to search for
 * @param startPosition - Optional start position to limit search
 * @param endPosition - Optional end position to limit search
 * @returns Array of matching descendant nodes
 */
descendantsOfType(types: string | string[], startPosition?: Point, endPosition?: Point): (Node | null)[];

/**
 * Get the node's number of descendants, including one for the node itself
 */
get descendantCount(): number;

/**
 * Get the smallest node within this node that spans the given byte range
 * @param start - Start byte index
 * @param end - End byte index (optional, defaults to start)
 * @returns Smallest node spanning the range or null
 */
descendantForIndex(start: number, end?: number): Node | null;

/**
 * Get the smallest named node within this node that spans the given byte range
 * @param start - Start byte index
 * @param end - End byte index (optional, defaults to start)
 * @returns Smallest named node spanning the range or null
 */
namedDescendantForIndex(start: number, end?: number): Node | null;

/**
 * Get the smallest node within this node that spans the given point range
 * @param start - Start position
 * @param end - End position (optional, defaults to start)
 * @returns Smallest node spanning the range or null
 */
descendantForPosition(start: Point, end?: Point): Node | null;

/**
 * Get the smallest named node within this node that spans the given point range
 * @param start - Start position
 * @param end - End position (optional, defaults to start)
 * @returns Smallest named node spanning the range or null
 */
namedDescendantForPosition(start: Point, end?: Point): Node | null;

Usage Examples:

// Find all identifier nodes
const identifiers = tree.rootNode.descendantsOfType("identifier");
console.log("Found identifiers:", identifiers.length);

// Find node at specific position
const nodeAtCursor = tree.rootNode.descendantForPosition({ row: 0, column: 5 });
console.log("Node at cursor:", nodeAtCursor?.type);

// Find all function declarations
const functions = tree.rootNode.descendantsOfType("function_declaration");

Parent and Ancestor Navigation

Navigate up the tree hierarchy.

/**
 * Get this node's immediate parent
 */
get parent(): Node | null;

/**
 * Get the node that contains the given descendant
 * @param descendant - Descendant node to find container for
 * @returns Node containing the descendant (may be descendant itself)
 */
childWithDescendant(descendant: Node): Node | null;

Tree Cursor Creation

Create efficient tree cursors from nodes.

/**
 * Create a new TreeCursor starting from this node
 * Note: The given node is considered the root of the cursor
 * @returns TreeCursor for efficient traversal
 */
walk(): TreeCursor;

Node Editing

Edit individual nodes to sync with source changes.

/**
 * Edit this node to keep it in-sync with source code changes
 * Only needed when keeping specific Node instances after tree edits
 * @param edit - Description of the edit
 */
edit(edit: Edit): void;

String Representation

Get textual representation of nodes.

/**
 * Get the S-expression representation of this node
 * @returns String representation showing the tree structure
 */
toString(): string;

Usage Example:

const tree = parser.parse("let x = 1 + 2;");
console.log(tree.rootNode.toString());
// Output: (program (lexical_declaration (let) (variable_declarator (identifier) (number))))

Install with Tessl CLI

npx tessl i tessl/npm-web-tree-sitter

docs

index.md

language.md

parser.md

query.md

tree-cursor.md

tree-node.md

tile.json