emacs-tree-sitter / elisp-tree-sitter

Emacs Lisp bindings for tree-sitter
https://emacs-tree-sitter.github.io
MIT License
815 stars 73 forks source link

Returned parent node doesn't contain given node as child #274

Open mathrick opened 4 months ago

mathrick commented 4 months ago
(let* ((parser (tsc-make-parser))
       (parsed (progn
                 (tsc-set-language parser (tree-sitter-require 'python))
                 (tsc-root-node (tsc-parse-string parser "def dupa(foo):")))))
  (message "parsed is %s" parsed)
  (tsc-traverse-mapc (lambda (node)
                       (let ((parent (tsc-get-parent node)))
                         (when (and parent
                                    (zerop (tsc-count-children parent)))
                           (error "Our parent has zero children!? %s" (tsc-node-to-sexp node)))))
                     parsed))

This results in:

tsc-traverse-mapc: Our parent has zero children!? ("_newline")

For some reason, the node returns the trailing ":" as its parent, but it is actually its sibling in the traversal order (ie. (tsc-node-eq node (tsc-get-next-sibling parent)) => t).

ubolonton commented 3 months ago

Seems like a bug in the underlying C API of tsc-get-parent. I could reproduce this with the Python binding:

>>> from tree_sitter import *
>>> py = Language("python.dylib", "python")
>>> p = Parser()
>>> p.set_language(py)
>>> tree = p.parse("def dupa(foo):".encode('utf-8')); tree
<tree_sitter.Tree object at 0x1027d2410>
>>>
>>> fd = tree.root_node.child(0); fd
<Node type=function_definition, start_point=(0, 0), end_point=(0, 14)>
>>>
>>> blk = fd.child(4); blk
<Node type=block, start_point=(0, 14), end_point=(0, 14)>
>>>
>>> blk.parent
<Node type=":", start_point=(0, 13), end_point=(0, 14)>