diff --git a/tree_sitter/__init__.pyi b/tree_sitter/__init__.pyi new file mode 100644 index 0000000..3373a91 --- /dev/null +++ b/tree_sitter/__init__.pyi @@ -0,0 +1,412 @@ +from collections.abc import Callable, Hashable, Iterator, Sized +from typing import Annotated, Any, Final, NamedTuple, SupportsBytes, overload + +Ptr = Annotated[int, "TSLanguage *"] + +Point = NamedTuple("Point", [("row", int), ("column", int)]) + +ParseCB = Callable[[int, Point], bytes] + + +class Language(Hashable): + def __init__(self, ptr: Ptr, name: str): ... + + @property + def version(self) -> int: ... + + @property + def node_kind_count(self) -> int: ... + + @property + def parse_state_count(self) -> int: ... + + @property + def field_count(self) -> int: ... + + def node_kind_for_id(self, id: int) -> str | None: ... + + def id_for_node_kind(self, kind: str, named: bool) -> int | None: ... + + def node_kind_is_named(self, id: int) -> bool: ... + + def node_kind_is_visible(self, id: int) -> bool: ... + + def field_name_for_id(self, field_id: int) -> str | None: ... + + def field_id_for_name(self, name: str) -> int | None: ... + + def next_state(self, state: int, id: int) -> int: ... + + def lookahead_iterator(self, state: int) -> LookaheadIterator | None: ... + + def query(self, source: str) -> Query: ... + + def __repr__(self) -> str: ... + + def __str__(self) -> str: ... + + def __eq__(self, other: Any) -> bool: ... + + def __ne__(self, other: Any) -> bool: ... + + def __hash__(self) -> int: ... + + +class Node(Hashable, SupportsBytes): + @property + def id(self) -> int: ... + + @property + def kind_id(self) -> int: ... + + @property + def grammar_id(self) -> int: ... + + @property + def grammar_name(self) -> str: ... + + @property + def type(self) -> str: ... + + @property + def is_named(self) -> bool: ... + + @property + def is_extra(self) -> bool: ... + + @property + def has_changes(self) -> bool: ... + + @property + def has_error(self) -> bool: ... + + @property + def is_error(self) -> bool: ... + + @property + def parse_state(self) -> int: ... + + @property + def next_parse_state(self) -> int: ... + + @property + def is_missing(self) -> bool: ... + + @property + def start_byte(self) -> int: ... + + @property + def end_byte(self) -> int: ... + + @property + def byte_range(self) -> tuple[int, int]: ... + + @property + def range(self) -> Range: ... + + @property + def start_point(self) -> Point: ... + + @property + def end_point(self) -> Point: ... + + @property + def children(self) -> list[Node]: ... + + @property + def child_count(self) -> int: ... + + @property + def named_children(self) -> list[Node]: ... + + @property + def named_child_count(self) -> int: ... + + @property + def parent(self) -> Node | None: ... + + @property + def next_sibling(self) -> Node | None: ... + + @property + def prev_sibling(self) -> Node | None: ... + + @property + def next_named_sibling(self) -> Node | None: ... + + @property + def prev_named_sibling(self) -> Node | None: ... + + @property + def descendant_count(self) -> int: ... + + @property + def text(self) -> bytes: ... + + def walk(self) -> TreeCursor: ... + + def edit( + self, + start_byte: int, + old_end_byte: int, + new_end_byte: int, + start_point: Point, + old_end_point: Point, + new_end_point: Point, + ): ... + + def child(self, index: int) -> Node | None: ... + + def named_child(self, index: int) -> Node | None: ... + + def child_by_field_id(self, id: int) -> Node | None: ... + + def child_by_field_name(self, name: str) -> Node | None: ... + + def children_by_field_id(self, id: int) -> list[Node]: ... + + def children_by_field_name(self, name: str) -> list[Node]: ... + + def field_name_for_child(self, child_index: int) -> str | None: ... + + def descendant_for_byte_range( + self, + start_byte: int, + end_byte: int, + ) -> Node | None: ... + + def named_descendant_for_byte_range( + self, + start_byte: int, + end_byte: int, + ) -> Node | None: ... + + def descendant_for_point_range( + self, + start_point: Point, + end_point: Point, + ) -> Node | None: ... + + def named_descendant_for_point_range( + self, + start_point: Point, + end_point: Point, + ) -> Node | None: ... + + # NOTE: deprecated + def sexp(self) -> str: ... + + def __bytes__(self) -> bytes: ... + + def __repr__(self) -> str: ... + + def __str__(self) -> str: ... + + def __eq__(self, other: Any) -> bool: ... + + def __ne__(self, other: Any) -> bool: ... + + def __hash__(self) -> int: ... + + +class Tree: + @property + def root_node(self) -> Node: ... + + @property + def included_ranges(self) -> list[Range]: ... + + @property + def text(self) -> bytes: ... + + def root_node_with_offset( + self, + offset_bytes: int, + offset_extent: Point, + ) -> Node | None: ... + + def edit( + self, + start_byte: int, + old_end_byte: int, + new_end_byte: int, + start_point: Point, + old_end_point: Point, + new_end_point: Point, + ): ... + + def walk(self) -> TreeCursor: ... + + def changed_ranges(self, old_tree: Tree) -> list[Range]: ... + + def __bytes__(self) -> bytes: ... + +class TreeCursor(Sized): + @property + def node(self) -> Node: ... + + @property + def field_id(self) -> int | None: ... + + @property + def field_name(self) -> str | None: ... + + @property + def depth(self) -> int: ... + + def copy(self) -> TreeCursor: ... + + def reset(self, node: Node): ... + + def reset_to(self, cursor: TreeCursor): ... + + def descendant_index(self) -> int: ... + + def goto_first_child(self) -> bool: ... + + def goto_last_child(self) -> bool: ... + + def goto_parent(self) -> bool: ... + + def goto_next_sibling(self) -> bool: ... + + def goto_previous_sibling(self) -> bool: ... + + def goto_descendant(self, index: int): ... + + def goto_first_child_for_byte(self, byte: int) -> bool: ... + + @overload + def goto_first_child_for_point(self, point: Point) -> bool: ... + + # NOTE: deprecated + @overload + def goto_first_child_for_point(self, row: int, column: int) -> bool: ... + + def __copy__(self) -> TreeCursor: ... + + def __len__(self) -> int: ... + + +class Parser: + def __init__(self, language: Ptr | None): ... + + @property + def language(self) -> int: ... + + @language.setter + def language(self, language: Ptr): ... + + @property + def included_ranges(self) -> list[Range]: ... + + @included_ranges.setter + def included_ranges(self, ranges: list[Range]): ... + + @property + def timeout_micros(self) -> int: ... + + @timeout_micros.setter + def timeout_micros(self, timeout: int): ... + + def parse( + self, + source: bytes | ParseCB | None, + /, + old_tree: Tree | None = None, + # NOTE: deprecated + keep_text: bool = True, + ) -> Tree: ... + + def reset(self): ... + + # NOTE: deprecated + def set_language(self, language: Ptr): ... + + # NOTE: deprecated + def set_included_ranges(self, ranges: list[Range]): ... + + # NOTE: deprecated + def set_timeout_micros(self, timeout: int): ... + + +# TODO(0.23): implement the core methods +class Query: + # TODO(0.23): return `dict[str, Node]` + def captures( + self, + node: Node, + *, + start_point: Point = Point(0, 0), + end_point: Point = Point(0xFFFFFFFF, 0xFFFFFFFF), + start_byte: int = 0, + end_byte: int = 0xFFFFFFFF, + ) -> list[tuple[Node, str]]: ... + + def matches( + self, + node: Node, + *, + start_point: Point = Point(0, 0), + end_point: Point = Point(0xFFFFFFFF, 0xFFFFFFFF), + start_byte: int = 0, + end_byte: int = 0xFFFFFFFF, + ) -> list[tuple[int, dict[str, Node | list[Node]]]]: ... + + +class LookaheadIterator(Iterator[int]): + @property + def language(self) -> int: ... + + @property + def current_symbol(self) -> int: ... + + @property + def current_symbol_name(self) -> str: ... + + def reset(self, language: Ptr, state: int): ... + + def reset_state(self, state: int): ... + + def iter_names(self) -> LookaheadNamesIterator: ... + + def __next__(self) -> int: ... + + +class LookaheadNamesIterator(Iterator[str]): + def __next__(self) -> str: ... + + +class Range(Hashable): + def __init__( + self, + start_point: Point, + end_point: Point, + start_byte: int, + end_byte: int, + ): ... + + @property + def start_point(self): Point + + @property + def end_point(self): Point + + @property + def start_byte(self): int + + @property + def end_byte(self): int + + def __eq__(self, other: Any) -> bool: ... + + def __ne__(self, other: Any) -> bool: ... + + def __repr__(self) -> str: ... + + def __hash__(self) -> int: ... + + +LANGUAGE_VERSION: Final[int] + +MIN_COMPATIBLE_LANGUAGE_VERSION: Final[int] diff --git a/tree_sitter/_binding.pyi b/tree_sitter/_binding.pyi deleted file mode 100644 index b53b824..0000000 --- a/tree_sitter/_binding.pyi +++ /dev/null @@ -1,474 +0,0 @@ -from dataclasses import dataclass -from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union - -import tree_sitter - -class Node: - """A syntax node""" - - def sexp(self) -> str: - """Get an S-expression representing the node.""" - - def walk(self) -> TreeCursor: - """Get a tree cursor for walking the tree starting at this node.""" - - def edit( - self, - start_byte: int, - old_end_byte: int, - new_end_byte: int, - start_point: Tuple[int, int], - old_end_point: Tuple[int, int], - new_end_point: Tuple[int, int], - ) -> None: - """Edit this node to keep it in-sync with source code that has been edited.""" - - def child(self, index: int) -> Optional[Node]: - """Get child at the given index.""" - - def named_child(self, index: int) -> Optional[Node]: - """Get named child at the given index.""" - - def child_by_field_id(self, id: int) -> Optional[Node]: - """Get child for the given field id.""" - - def child_by_field_name(self, name: str) -> Optional[Node]: - """Get child for the given field name.""" - - def children_by_field_id(self, id: int) -> List[Node]: - """Get a list of child nodes for the given field id.""" - - def children_by_field_name(self, name: str) -> List[Node]: - """Get a list of child nodes for the given field name.""" - - def field_name_for_child(self, child_index: int) -> Optional[str]: - """Get the field name of a child node by the index of child.""" - - def descendant_for_byte_range(self, start_byte: int, end_byte: int) -> Optional[Node]: - """Get the smallest node within the given byte range.""" - - def named_descendant_for_byte_range(self, start_byte: int, end_byte: int) -> Optional[Node]: - """Get the smallest named node within the given byte range.""" - - def descendant_for_point_range( - self, start_point: Tuple[int, int], end_point: Tuple[int, int] - ) -> Optional[Node]: - """Get the smallest node within this node that spans the given point range.""" - - def named_descendant_for_point_range( - self, start_point: Tuple[int, int], end_point: Tuple[int, int] - ) -> Optional[Node]: - """Get the smallest named node within this node that spans the given point range.""" - - @property - def id(self) -> int: - """The node's numeric id""" - - @property - def kind_id(self) -> int: - """The node's type as a numerical id""" - - @property - def grammar_id(self) -> int: - """The node's grammar type as a numerical id""" - - @property - def grammar_name(self) -> str: - """The node's grammar name as a string""" - - @property - def type(self) -> str: - """The node's type""" - - @property - def is_named(self) -> bool: - """Is this a named node""" - - @property - def is_extra(self) -> bool: - """Is this an extra node""" - - @property - def has_changes(self) -> bool: - """Does this node have text changes since it was parsed""" - - @property - def has_error(self) -> bool: - """Does this node contain any errors""" - - @property - def is_error(self) -> bool: - """Is this node an error""" - - @property - def parse_state(self) -> int: - """The node's parse state""" - - @property - def next_parse_state(self) -> int: - """The parse state after this node's""" - - @property - def is_missing(self) -> bool: - """Is this a node inserted by the parser""" - - @property - def start_byte(self) -> int: - """The node's start byte""" - - @property - def end_byte(self) -> int: - """The node's end byte""" - - @property - def byte_range(self) -> Tuple[int, int]: - """The node's byte range""" - - @property - def range(self) -> Range: - """The node's range""" - - @property - def start_point(self) -> Tuple[int, int]: - """The node's start point""" - - @property - def end_point(self) -> Tuple[int, int]: - """The node's end point""" - - @property - def children(self) -> List[Node]: - """The node's children""" - - @property - def child_count(self) -> int: - """The number of children for a node""" - - @property - def named_children(self) -> List[Node]: - """The node's named children""" - - @property - def named_child_count(self) -> int: - """The number of named children for a node""" - - @property - def parent(self) -> Optional[Node]: - """The node's parent""" - - @property - def next_sibling(self) -> Optional[Node]: - """The node's next sibling""" - - @property - def prev_sibling(self) -> Optional[Node]: - """The node's previous sibling""" - - @property - def next_named_sibling(self) -> Optional[Node]: - """The node's next named sibling""" - - @property - def prev_named_sibling(self) -> Optional[Node]: - """The node's previous named sibling""" - - @property - def descendant_count(self) -> int: - """The number of descendants for a node, including itself""" - - @property - def text(self) -> bytes: - """The node's text, if tree has not been edited""" - -class Tree: - """A Syntax Tree""" - - def root_node_with_offset( - self, offset_bytes: int, offset_extent: Tuple[int, int] - ) -> Optional[Node]: - """Get the root node of the syntax tree, but with its position shifted forward by the given offset.""" - - def walk(self) -> TreeCursor: - """Get a tree cursor for walking this tree.""" - - def edit( - self, - start_byte: int, - old_end_byte: int, - new_end_byte: int, - start_point: Tuple[int, int], - old_end_point: Tuple[int, int], - new_end_point: Tuple[int, int], - ) -> None: - """Edit the syntax tree.""" - - def changed_ranges(self, old_tree: Tree) -> List[Range]: - """Get a list of ranges that were edited.""" - - @property - def included_ranges(self) -> List[Range]: - """Get the included ranges that were used to parse the syntax tree.""" - - @property - def root_node(self) -> Node: - """The root node of this tree.""" - - @property - def text(self) -> bytes: - """The source text for this tree, if unedited.""" - -class TreeCursor: - """A syntax tree cursor.""" - - def descendant_index(self) -> int: - """Get the index of the cursor's current node out of all of the descendants of the original node.""" - - def goto_first_child(self) -> bool: - """Go to the first child. - If the current node has children, move to the first child and - return True. Otherwise, return False. - """ - - def goto_last_child(self) -> bool: - """Go to the last child. - If the current node has children, move to the last child and - return True. Otherwise, return False. - """ - - def goto_parent(self) -> bool: - """Go to the parent. - If the current node is not the root, move to its parent and - return True. Otherwise, return False. - """ - - def goto_next_sibling(self) -> bool: - """Go to the next sibling. - - If the current node has a next sibling, move to the next sibling - and return True. Otherwise, return False. - """ - - def goto_previous_sibling(self) -> bool: - """Go to the previous sibling. - - If the current node has a previous sibling, move to the previous sibling - and return True. Otherwise, return False. - """ - - def goto_descendant(self, index: int) -> None: - """Go to the descendant at the given index. - - If the current node has a descendant at the given index, move to the - descendant and return True. Otherwise, return False. - """ - - def goto_first_child_for_byte(self, byte: int) -> bool: - """Go to the first child that extends beyond the given byte. - - If the current node has a child that includes the given byte, move to the - child and return True. Otherwise, return False. - """ - - def goto_first_child_for_point(self, row: int, column: int) -> bool: - """Go to the first child that extends beyond the given point. - - If the current node has a child that includes the given point, move to the - child and return True. Otherwise, return False. - """ - - def reset(self, node: Node) -> None: - """Re-initialize a tree cursor to start at a different node.""" - - def reset_to(self, cursor: TreeCursor) -> None: - """Re-initialize the cursor to the same position as the given cursor. - - Unlike `reset`, this will not lose parent information and allows reusing already created cursors - """ - - def copy(self) -> TreeCursor: - """Create a copy of the cursor.""" - - @property - def node(self) -> Node: - """The current node.""" - - @property - def field_id(self) -> Optional[int]: - """Get the field id of the tree cursor's current node. - - If the current node has the field id, return int. Otherwise, return None. - """ - - @property - def field_name(self) -> Optional[str]: - """Get the field name of the tree cursor's current node. - - If the current node has the field name, return str. Otherwise, return None. - """ - - @property - def depth(self) -> int: - """Get the depth of the cursor's current node relative to the original node.""" - -class Parser: - """A Parser""" - - def parse( - self, - source_code: bytes | Callable[[int, Tuple[int, int]], Optional[bytes]], - old_tree: Optional[Tree] = None, - keep_text: Optional[bool] = True, - ) -> Tree: - """Parse source code, creating a syntax tree. - Note that by default `keep_text` will be True, unless source_code is a callable. - """ - - def reset(self) -> None: - """Instruct the parser to start the next parse from the beginning.""" - - def set_timeout_micros(self, timeout: int) -> None: - """Set the maximum duration in microseconds that parsing should be allowed to take before halting.""" - - def set_included_ranges(self, ranges: List[Range]) -> None: - """Set the ranges of text that the parser should include when parsing.""" - - def set_language(self, language: tree_sitter.Language) -> None: - """Set the parser language.""" - - @property - def timeout_micros(self) -> int: - """The timeout for parsing, in microseconds.""" - -class Query: - """A set of patterns to search for in a syntax tree.""" - - def matches( - self, - node: Node, - start_point: Optional[Tuple[int, int]] = None, - end_point: Optional[Tuple[int, int]] = None, - start_byte: Optional[int] = None, - end_byte: Optional[int] = None, - ) -> List[Tuple[int, Dict[str, Union[Node, List[Node]]]]]: - """Get a list of all of the matches within the given node.""" - - def captures( - self, - node: Node, - start_point: Optional[Tuple[int, int]] = None, - end_point: Optional[Tuple[int, int]] = None, - start_byte: Optional[int] = None, - end_byte: Optional[int] = None, - ) -> List[Tuple[Node, str]]: - """Get a list of all of the captures within the given node.""" - -class LookaheadIterator(Iterable): - def reset(self, language: int, state: int) -> None: - """Reset the lookahead iterator to a new language and parse state. - - This returns `True` if the language was set successfully, and `False` otherwise. - """ - - def reset_state(self, state: int) -> None: - """Reset the lookahead iterator to another state. - - This returns `True` if the iterator was reset to the given state, and `False` otherwise. - """ - - @property - def language(self) -> int: - """Get the language.""" - - @property - def current_symbol(self) -> int: - """Get the current symbol.""" - - @property - def current_symbol_name(self) -> str: - """Get the current symbol name.""" - - def __next__(self) -> int: - """Get the next symbol.""" - - def __iter__(self) -> LookaheadIterator: - """Get an iterator for the lookahead iterator.""" - - def iter_names(self) -> LookaheadNamesIterator: - """Get an iterator for the lookahead iterator.""" - -class LookaheadNamesIterator(Iterable): - def __next__(self) -> str: - """Get the next symbol name.""" - - def __iter__(self) -> LookaheadNamesIterator: - """Get an iterator for the lookahead names iterator.""" - -@dataclass -class Range: - """A range within a document.""" - - start_point: Tuple[int, int] - """The start point of this range""" - - end_point: Tuple[int, int] - """The end point of this range""" - - start_byte: int - """The start byte of this range""" - - end_byte: int - """The end byte of this range""" - - def __init__( - self, - start_point: Tuple[int, int], - end_point: Tuple[int, int], - start_byte: int, - end_byte: int, - ) -> None: - """Create a new range.""" - - def __repr__(self) -> str: - """Get a string representation of the range.""" - - def __eq__(self, other: Any) -> bool: - """Check if two ranges are equal.""" - - def __ne__(self, other: Any) -> bool: - """Check if two ranges are not equal.""" - -def _language_version(language_id: int) -> int: - ... - -def _language_symbol_count(language_id: int) -> int: - ... - -def _language_state_count(language_id: int) -> int: - ... - -def _language_symbol_name(language_id: int, id: int) -> Optional[str]: - ... - -def _language_symbol_for_name(language_id: int, name: str, named: bool) -> Optional[int]: - ... - -def _language_symbol_type(language_id: int, id: int) -> int: - ... - -def _language_field_count(language_id: int) -> int: - ... - -def _language_field_name_for_id(language_id: int, field_id: int) -> Optional[str]: - ... - -def _language_field_id_for_name(language_id: int, name: str) -> Optional[int]: - ... - -def _language_query(language_id: int, source: str) -> Query: - ... - -def _lookahead_iterator(language_id: int, state: int) -> Optional[LookaheadIterator]: - ... - -def _next_state(language_id: int, state: int, symbol: int) -> int: - ...