Class: TreeHaver::Backends::FFI::Node Private
- Inherits:
-
Object
- Object
- TreeHaver::Backends::FFI::Node
- Includes:
- Enumerable
- Defined in:
- lib/tree_haver/backends/ffi.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
FFI-based tree-sitter node (raw backend node)
This is a raw backend node that wraps a TSNode by-value struct from the tree-sitter C API. It provides the minimal interface needed for tree-sitter operations but is NOT intended for direct use by application code.
Architecture Note
Unlike pure-Ruby backends (Citrus, Parslet, Prism, Psych) which define Node
classes that inherit from TreeHaver::Base::Node, tree-sitter backends (MRI,
Rust, FFI, Java) define raw wrapper classes that get wrapped by TreeHaver::Node.
The wrapping hierarchy is:
FFI::Node (this class) → TreeHaver::Node → Base::Node
When you use TreeHaver::Parser#parse, the returned tree's nodes are already
wrapped in TreeHaver::Node, which provides the full unified API including:
#children- Array of child nodes#text- Extract text from source#first_child,#last_child- Convenience accessors#start_line,#end_line- 1-based line numbers#source_position- Hash with position info#each,#map, etc. - Enumerable methods#to_s,#inspect- String representations
This raw class only implements methods that require direct FFI calls to the tree-sitter C library. The wrapper adds Ruby-level conveniences.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer?
private
Compare nodes for ordering (used by Comparable module).
-
#child(index) ⇒ Node?
private
Get a child by index.
-
#child_by_field_name(field_name) ⇒ Node?
private
Get a child node by field name.
-
#child_count ⇒ Integer
private
Get the number of children.
-
#descendant_for_byte_range(start_byte, end_byte) ⇒ Node?
private
Find the smallest descendant that spans the given byte range.
-
#descendant_for_point_range(start_point, end_point) ⇒ Node?
private
Find the smallest descendant that spans the given point range.
-
#each {|child| ... } ⇒ Enumerator?
private
Iterate over child nodes.
-
#end_byte ⇒ Integer
private
Get end byte offset.
-
#end_point ⇒ TreeHaver::Point
private
Get end point.
-
#has_error? ⇒ Boolean
private
Check if node has error.
-
#initialize(ts_node_value) ⇒ Node
constructor
private
A new instance of Node.
-
#missing? ⇒ Boolean
private
Check if this is a MISSING node.
-
#named? ⇒ Boolean
private
Check if this is a named node.
-
#named_child(index) ⇒ Node?
private
Get a named child by index.
-
#named_child_count ⇒ Integer
private
Get the count of named children.
-
#named_descendant_for_byte_range(start_byte, end_byte) ⇒ Node?
private
Find the smallest named descendant that spans the given byte range.
-
#named_descendant_for_point_range(start_point, end_point) ⇒ Node?
private
Find the smallest named descendant that spans the given point range.
-
#next_named_sibling ⇒ Node?
private
Get the next named sibling node.
-
#next_sibling ⇒ Node?
private
Get the next sibling node.
-
#parent ⇒ Node?
private
Get the parent node.
-
#prev_named_sibling ⇒ Node?
private
Get the previous named sibling node.
-
#prev_sibling ⇒ Node?
private
Get the previous sibling node.
-
#start_byte ⇒ Integer
private
Get start byte offset.
-
#start_point ⇒ TreeHaver::Point
private
Get start point.
-
#type ⇒ String
private
Get the type name of this node.
Constructor Details
#initialize(ts_node_value) ⇒ Node
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Node.
720 721 722 723 |
# File 'lib/tree_haver/backends/ffi.rb', line 720 def initialize(ts_node_value) # Store by-value struct (FFI will copy); methods pass it back by value @val = ts_node_value end |
Instance Method Details
#<=>(other) ⇒ Integer?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Compare nodes for ordering (used by Comparable module)
Nodes are ordered by their position in the source:
- First by start_byte (earlier nodes come first)
- Then by end_byte for tie-breaking (shorter spans come first)
- Then by type for deterministic ordering
994 995 996 997 998 999 1000 1001 1002 1003 1004 |
# File 'lib/tree_haver/backends/ffi.rb', line 994 def <=>(other) return unless other.is_a?(Node) cmp = start_byte <=> other.start_byte return cmp if cmp.nonzero? cmp = end_byte <=> other.end_byte return cmp if cmp.nonzero? type <=> other.type end |
#child(index) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get a child by index
743 744 745 746 747 748 |
# File 'lib/tree_haver/backends/ffi.rb', line 743 def child(index) return if index >= child_count || index.negative? child_node = Native.ts_node_child(@val, index) Node.new(child_node) end |
#child_by_field_name(field_name) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get a child node by field name
Tree-sitter grammars define named fields for certain child positions. For example, in JSON, a "pair" node has "key" and "value" fields.
760 761 762 763 764 765 766 767 |
# File 'lib/tree_haver/backends/ffi.rb', line 760 def child_by_field_name(field_name) name = String(field_name) child_node = Native.ts_node_child_by_field_name(@val, name, name.bytesize) # ts_node_child_by_field_name returns a null node if field not found return if Native.ts_node_is_null(child_node) Node.new(child_node) end |
#child_count ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the number of children
735 736 737 |
# File 'lib/tree_haver/backends/ffi.rb', line 735 def child_count Native.ts_node_child_count(@val) end |
#descendant_for_byte_range(start_byte, end_byte) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Find the smallest descendant that spans the given byte range
909 910 911 912 913 914 |
# File 'lib/tree_haver/backends/ffi.rb', line 909 def descendant_for_byte_range(start_byte, end_byte) node = Native.ts_node_descendant_for_byte_range(@val, start_byte, end_byte) return if Native.ts_node_is_null(node) Node.new(node) end |
#descendant_for_point_range(start_point, end_point) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Find the smallest descendant that spans the given point range
933 934 935 936 937 938 939 940 941 942 943 944 945 946 |
# File 'lib/tree_haver/backends/ffi.rb', line 933 def descendant_for_point_range(start_point, end_point) start_pt = Native::TSPoint.new start_pt[:row] = start_point.respond_to?(:row) ? start_point.row : start_point[:row] start_pt[:column] = start_point.respond_to?(:column) ? start_point.column : start_point[:column] end_pt = Native::TSPoint.new end_pt[:row] = end_point.respond_to?(:row) ? end_point.row : end_point[:row] end_pt[:column] = end_point.respond_to?(:column) ? end_point.column : end_point[:column] node = Native.ts_node_descendant_for_point_range(@val, start_pt, end_pt) return if Native.ts_node_is_null(node) Node.new(node) end |
#each {|child| ... } ⇒ Enumerator?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Iterate over child nodes
972 973 974 975 976 977 978 979 980 981 982 983 |
# File 'lib/tree_haver/backends/ffi.rb', line 972 def each return enum_for(:each) unless block_given? count = child_count i = 0 while i < count child = Native.ts_node_child(@val, i) yield Node.new(child) i += 1 end nil end |
#end_byte ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get end byte offset
779 780 781 |
# File 'lib/tree_haver/backends/ffi.rb', line 779 def end_byte Native.ts_node_end_byte(@val) end |
#end_point ⇒ TreeHaver::Point
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get end point
795 796 797 798 799 |
# File 'lib/tree_haver/backends/ffi.rb', line 795 def end_point point = Native.ts_node_end_point(@val) # TSPoint is returned by value as an FFI::Struct with :row and :column fields TreeHaver::Point.new(point[:row], point[:column]) end |
#has_error? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if node has error
Returns true if this node or any of its descendants have a syntax error. This is the FFI equivalent of tree-sitter's ts_node_has_error.
807 808 809 810 811 |
# File 'lib/tree_haver/backends/ffi.rb', line 807 def has_error? # Explicit boolean conversion ensures consistent behavior across Ruby versions # FFI :bool return type may behave differently on some platforms !!Native.ts_node_has_error(@val) end |
#missing? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if this is a MISSING node
A MISSING node represents a token that was expected by the grammar but was not found in the source. Tree-sitter inserts MISSING nodes to allow parsing to continue despite syntax errors.
820 821 822 |
# File 'lib/tree_haver/backends/ffi.rb', line 820 def missing? !!Native.ts_node_is_missing(@val) end |
#named? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if this is a named node
Named nodes represent syntactic constructs (e.g., "pair", "object"). Anonymous nodes represent syntax/punctuation (e.g., "{", ",").
830 831 832 |
# File 'lib/tree_haver/backends/ffi.rb', line 830 def named? !!Native.ts_node_is_named(@val) end |
#named_child(index) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get a named child by index
888 889 890 891 892 893 894 895 |
# File 'lib/tree_haver/backends/ffi.rb', line 888 def named_child(index) return if index.negative? || index >= named_child_count child_node = Native.ts_node_named_child(@val, index) return if Native.ts_node_is_null(child_node) Node.new(child_node) end |
#named_child_count ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the count of named children
900 901 902 |
# File 'lib/tree_haver/backends/ffi.rb', line 900 def named_child_count Native.ts_node_named_child_count(@val) end |
#named_descendant_for_byte_range(start_byte, end_byte) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Find the smallest named descendant that spans the given byte range
921 922 923 924 925 926 |
# File 'lib/tree_haver/backends/ffi.rb', line 921 def named_descendant_for_byte_range(start_byte, end_byte) node = Native.ts_node_named_descendant_for_byte_range(@val, start_byte, end_byte) return if Native.ts_node_is_null(node) Node.new(node) end |
#named_descendant_for_point_range(start_point, end_point) ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Find the smallest named descendant that spans the given point range
953 954 955 956 957 958 959 960 961 962 963 964 965 966 |
# File 'lib/tree_haver/backends/ffi.rb', line 953 def named_descendant_for_point_range(start_point, end_point) start_pt = Native::TSPoint.new start_pt[:row] = start_point.respond_to?(:row) ? start_point.row : start_point[:row] start_pt[:column] = start_point.respond_to?(:column) ? start_point.column : start_point[:column] end_pt = Native::TSPoint.new end_pt[:row] = end_point.respond_to?(:row) ? end_point.row : end_point[:row] end_pt[:column] = end_point.respond_to?(:column) ? end_point.column : end_point[:column] node = Native.ts_node_named_descendant_for_point_range(@val, start_pt, end_pt) return if Native.ts_node_is_null(node) Node.new(node) end |
#next_named_sibling ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the next named sibling node
867 868 869 870 871 872 |
# File 'lib/tree_haver/backends/ffi.rb', line 867 def next_named_sibling sibling = Native.ts_node_next_named_sibling(@val) return if Native.ts_node_is_null(sibling) Node.new(sibling) end |
#next_sibling ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the next sibling node
847 848 849 850 851 852 |
# File 'lib/tree_haver/backends/ffi.rb', line 847 def next_sibling sibling = Native.ts_node_next_sibling(@val) return if Native.ts_node_is_null(sibling) Node.new(sibling) end |
#parent ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the parent node
837 838 839 840 841 842 |
# File 'lib/tree_haver/backends/ffi.rb', line 837 def parent parent_node = Native.ts_node_parent(@val) return if Native.ts_node_is_null(parent_node) Node.new(parent_node) end |
#prev_named_sibling ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the previous named sibling node
877 878 879 880 881 882 |
# File 'lib/tree_haver/backends/ffi.rb', line 877 def prev_named_sibling sibling = Native.ts_node_prev_named_sibling(@val) return if Native.ts_node_is_null(sibling) Node.new(sibling) end |
#prev_sibling ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the previous sibling node
857 858 859 860 861 862 |
# File 'lib/tree_haver/backends/ffi.rb', line 857 def prev_sibling sibling = Native.ts_node_prev_sibling(@val) return if Native.ts_node_is_null(sibling) Node.new(sibling) end |
#start_byte ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get start byte offset
772 773 774 |
# File 'lib/tree_haver/backends/ffi.rb', line 772 def start_byte Native.ts_node_start_byte(@val) end |
#start_point ⇒ TreeHaver::Point
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get start point
786 787 788 789 790 |
# File 'lib/tree_haver/backends/ffi.rb', line 786 def start_point point = Native.ts_node_start_point(@val) # TSPoint is returned by value as an FFI::Struct with :row and :column fields TreeHaver::Point.new(point[:row], point[:column]) end |
#type ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the type name of this node
728 729 730 |
# File 'lib/tree_haver/backends/ffi.rb', line 728 def type Native.ts_node_type(@val) end |