From f2bb6813e065ad82b349749e692db2d82249036c Mon Sep 17 00:00:00 2001 From: Dorian Czichotzki Date: Mon, 26 Jul 2021 18:12:46 +0200 Subject: [PATCH 1/3] Add type stub file --- MANIFEST.in | 1 + tree_sitter/binding.pyi | 179 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 tree_sitter/binding.pyi diff --git a/MANIFEST.in b/MANIFEST.in index f5b018d..ea476cb 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include README.md include LICENSE +include tree_sitter/binding.pyi prune tree_sitter/core graft tree_sitter/core/lib/src graft tree_sitter/core/lib/include/tree_sitter diff --git a/tree_sitter/binding.pyi b/tree_sitter/binding.pyi new file mode 100644 index 0000000..bb018cb --- /dev/null +++ b/tree_sitter/binding.pyi @@ -0,0 +1,179 @@ +from typing import Optional, List, Tuple, Any + +import tree_sitter + +# ----------------------------------- Node ----------------------------------- # + +class Node: + """A syntax node""" + + def walk(self) -> TreeCursor: + """Get a tree cursor for walking the tree starting at this node.""" + ... + + def sexp(self) -> str: + """Get an S-expression representing the node.""" + ... + + 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.""" + ... + + @property + def type(self) -> str: + """The node's type""" + ... + @property + def is_named(self) -> bool: + """Is this a named node""" + ... + @property + def is_missing(self) -> bool: + """Is this a node inserted by the parser""" + ... + @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 start_byte(self) -> int: + """The node's start byte""" + ... + @property + def end_byte(self) -> int: + """The node's end byte""" + ... + @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_child_count(self) -> int: + """The number of named children for a node""" + ... + @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 parent(self) -> Optional[Node]: + """The node's parent""" + ... + +class Tree: + """A Syntax Tree""" + + 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.""" + ... + + @property + def root_node(self) -> Node: + """The root node of this tree.""" + ... + +class TreeCursor: + """A syntax tree cursor.""" + + def current_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. + """ + ... + + def goto_parent(self) -> bool: + """Go to parent. + + If the current node is not the root, move to its parent and + return True. Otherwise, return False. + """ + ... + + def goto_first_child(self) -> bool: + """Go to first child. + + If the current node has children, move to the first child and + return True. Otherwise, return False. + """ + ... + + def goto_next_sibling(self) -> bool: + """Go to next sibling. + + If the current node has a next sibling, move to the next sibling + and return True. Otherwise, return False. + """ + ... + + @property + def node(self) -> Node: + """The current node.""" + ... + +class Parser: + """A Parser""" + + def parse(self, source_code: bytes, old_tree: Tree = None) -> Tree: + """Parse source code, creating a syntax tree.""" + ... + + def set_language(self, language: tree_sitter.Language) -> None: + """Set the parser language.""" + ... + +class Query: + """A set of patterns to search for in a syntax tree.""" + + def matches(self, node: Node): + """Get a list of all of the matches within the given node.""" + ... + + def captures(self, node: Node, start_point: Tuple[int,int] = None, end_point: Tuple[int,int] = None) -> List[Tuple[Node, str]]: + """Get a list of all of the captures within the given node.""" + ... + + +def _language_field_id_for_name(language_id: Any, name: str) -> int: + """(internal)""" + ... + +def _language_query(language_id: Any, source: str) -> Query: + """(internal)""" + ... From 966bc3ea80eeb4baf86f8b7d49391a2e930a7b0c Mon Sep 17 00:00:00 2001 From: Dorian Czichotzki Date: Tue, 27 Jul 2021 11:21:32 +0200 Subject: [PATCH 2/3] Add mypy test to CI --- .github/workflows/ci.yml | 8 ++++++-- .travis.yml | 1 - mypy.ini | 11 +++++++++++ tree_sitter/binding.pyi | 3 ++- 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 mypy.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbb5615..7d09a42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,8 @@ jobs: if: ${{ matrix.install_libcxx }} run: | DEBIAN_FRONTEND=noninteractive sudo apt-get install -y libc++-dev libc++abi-dev - - name: Install flake8 - run: python -m pip install flake8 + - name: Install flake8 & mypy + run: python -m pip install flake8 mypy - name: Fetch fixtures run: ./script/fetch-fixtures - name: Lint @@ -55,3 +55,7 @@ jobs: shell: bash run: | CFLAGS="-O0 -g" python setup.py test + - name: Type Check + shell: bash + run: | + mypy --config-file mypy.ini tests/test_tree_sitter.py diff --git a/.travis.yml b/.travis.yml index ebdd67f..9542635 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ script: - script/lint - script/test - matrix: include: - python: 3.5 diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..9504881 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,11 @@ +[mypy] +warn_unused_configs= true +warn_incomplete_stub = true + +[mypy-tree_sitter.binding] +disallow_incomplete_defs = true +disallow_untyped_defs = true + +[mypy-tests.*] +check_untyped_defs = true +strict_optional = false diff --git a/tree_sitter/binding.pyi b/tree_sitter/binding.pyi index bb018cb..06705bf 100644 --- a/tree_sitter/binding.pyi +++ b/tree_sitter/binding.pyi @@ -161,7 +161,8 @@ class Parser: class Query: """A set of patterns to search for in a syntax tree.""" - def matches(self, node: Node): + # Not implemented yet. Return type is wrong + def matches(self, node: Node) -> None: """Get a list of all of the matches within the given node.""" ... From 62e7fcda6ee3191642cfab03440578a1331a662d Mon Sep 17 00:00:00 2001 From: Dorian Czichotzki Date: Wed, 28 Jul 2021 23:04:10 +0200 Subject: [PATCH 3/3] Remove mypy and type checks from pypy tests --- .github/workflows/ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d09a42..8c82290 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,8 @@ jobs: if: ${{ matrix.install_libcxx }} run: | DEBIAN_FRONTEND=noninteractive sudo apt-get install -y libc++-dev libc++abi-dev - - name: Install flake8 & mypy - run: python -m pip install flake8 mypy + - name: Install flake8 + run: python -m pip install flake8 - name: Fetch fixtures run: ./script/fetch-fixtures - name: Lint @@ -55,7 +55,11 @@ jobs: shell: bash run: | CFLAGS="-O0 -g" python setup.py test - - name: Type Check + - name: Install mypy + if: ${{ !startsWith(matrix.python, 'pypy') }} + run: python -m pip install mypy + - name: Check types shell: bash + if: ${{ !startsWith(matrix.python, 'pypy') }} run: | mypy --config-file mypy.ini tests/test_tree_sitter.py