Class: TreeHaver::Base::Tree Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/tree_haver/base/tree.rb

Overview

This class is abstract.

Subclasses must implement #root_node

Base class for all backend Tree implementations

This class defines the API contract for Tree objects across all backends. It provides shared implementation and documents required/optional methods.

Backend Architecture

TreeHaver supports two categories of backends:

Tree-sitter Backends (MRI, Rust, FFI, Java)

These backends use the native tree-sitter library (via different bindings). They return raw ::TreeSitter::Tree objects which are wrapped by TreeHaver::Tree (which inherits from this class).

  • Backend Parser returns: ::TreeSitter::Tree (raw)

  • TreeHaver::Parser wraps it in: TreeHaver::Tree

  • These backends do NOT define their own Tree/Node classes

Pure-Ruby/Plugin Backends (Citrus, Prism, Psych, Commonmarker, Markly)

These backends define their own complete implementations:

  • Backend::X::Tree - wraps parser-specific tree objects

  • Backend::X::Node - wraps parser-specific node objects

For consistency, these should also inherit from Base::Tree and Base::Node.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inner_tree = nil, source: nil, lines: nil) ⇒ Tree

Create a new Tree

Parameters:

  • inner_tree (Object) (defaults to: nil)

    The backend-specific tree object

  • source (String, nil) (defaults to: nil)

    The source code

  • lines (Array<String>, nil) (defaults to: nil)

    Pre-split lines (optional, derived from source if not provided)



53
54
55
56
57
# File 'lib/tree_haver/base/tree.rb', line 53

def initialize(inner_tree = nil, source: nil, lines: nil)
  @inner_tree = inner_tree
  @source = source
  @lines = lines || source&.lines || []
end

Instance Attribute Details

#inner_treeObject (readonly)

The underlying backend-specific tree object

Returns:

  • (Object)

    Backend tree



38
39
40
# File 'lib/tree_haver/base/tree.rb', line 38

def inner_tree
  @inner_tree
end

#linesArray<String> (readonly)

Source lines for byte offset calculations

Returns:

  • (Array<String>)

    Lines of source



46
47
48
# File 'lib/tree_haver/base/tree.rb', line 46

def lines
  @lines
end

#sourceString (readonly)

The source text

Returns:

  • (String)

    The original source code



42
43
44
# File 'lib/tree_haver/base/tree.rb', line 42

def source
  @source
end

Instance Method Details

#commentsArray

Get comments from the document

Returns:

  • (Array)

    Comments (empty for most pure-Ruby backends)



83
84
85
# File 'lib/tree_haver/base/tree.rb', line 83

def comments
  []
end

#edit(start_byte:, old_end_byte:, new_end_byte:, start_point:, old_end_point:, new_end_point:) ⇒ void

This method returns an undefined value.

Mark the tree as edited for incremental re-parsing



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/tree_haver/base/tree.rb', line 89

def edit(
  start_byte:,
  old_end_byte:,
  new_end_byte:,
  start_point:,
  old_end_point:,
  new_end_point:
)
  # Default implementation: no-op (incremental parsing not supported)
  # Backends that support it should override this
end

#errorsArray

Get parse errors

Returns:

  • (Array)

    Errors (empty for most pure-Ruby backends)



71
72
73
# File 'lib/tree_haver/base/tree.rb', line 71

def errors
  []
end

#has_error?Boolean

Check if this tree has syntax errors

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/tree_haver/base/tree.rb', line 103

def has_error?
  root = root_node
  return false unless root
  return true if root.has_error?

  # Deep check: traverse tree looking for error nodes
  # Use queue-based traversal to avoid deep recursion
  queue = [root]
  while (node = queue.shift)
    return true if node.has_error? || node.missing?

    # Add children to queue
    node.each { |child| queue.push(child) }
  end

  false
end

#inspectString

Human-readable representation

Returns:

  • (String)


123
124
125
# File 'lib/tree_haver/base/tree.rb', line 123

def inspect
  "#<#{self.class.name}>"
end

#root_nodeNode

Get the root node of the tree

Returns:

  • (Node)

    Root node

Raises:

  • (NotImplementedError)


63
64
65
# File 'lib/tree_haver/base/tree.rb', line 63

def root_node
  raise NotImplementedError, "#{self.class}#root_node must be implemented"
end

#warningsArray

Get parse warnings

Returns:

  • (Array)

    Warnings (empty for most pure-Ruby backends)



77
78
79
# File 'lib/tree_haver/base/tree.rb', line 77

def warnings
  []
end