Class: TreeHaver::Backends::Prism::Node Private

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tree_haver/backends/prism.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.

Prism node wrapper

Wraps Prism::Node objects to provide tree-sitter-compatible node API.

Prism nodes provide:

  • type: class name without “Node” suffix (e.g., ProgramNode → “program”)

  • location: ::Prism::Location with start/end offsets and line/column

  • child_nodes: array of child nodes

  • Various node-specific accessors

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, source) ⇒ 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.



330
331
332
333
# File 'lib/tree_haver/backends/prism.rb', line 330

def initialize(node, source)
  @inner_node = node
  @source = source
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, **kwargs, &block) ⇒ Object

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.

Delegate unknown methods to the underlying Prism node

This provides passthrough access for Prism-specific node methods like receiver, message, arguments, etc.

Parameters:

  • method_name (Symbol)

    method to call

  • args (Array)

    arguments to pass

  • kwargs (Hash)

    keyword arguments

  • block (Proc)

    block to pass

Returns:

  • (Object)

    result from the underlying node



614
615
616
617
618
619
620
# File 'lib/tree_haver/backends/prism.rb', line 614

def method_missing(method_name, *args, **kwargs, &block)
  if @inner_node&.respond_to?(method_name)
    @inner_node.public_send(method_name, *args, **kwargs, &block)
  else
    super
  end
end

Instance Attribute Details

#inner_node::Prism::Node (readonly)

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 the underlying Prism node.

Returns:

  • (::Prism::Node)

    the underlying Prism node



325
326
327
# File 'lib/tree_haver/backends/prism.rb', line 325

def inner_node
  @inner_node
end

#sourceString (readonly)

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 the source code.

Returns:

  • (String)

    the source code



328
329
330
# File 'lib/tree_haver/backends/prism.rb', line 328

def source
  @source
end

Instance Method Details

#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 node by index

Parameters:

  • index (Integer)

    child index

Returns:

  • (Node, nil)

    wrapped child node



466
467
468
469
470
471
472
473
474
# File 'lib/tree_haver/backends/prism.rb', line 466

def child(index)
  return if @inner_node.nil?
  return unless @inner_node.respond_to?(:child_nodes)

  children_array = @inner_node.child_nodes.compact
  return if index >= children_array.size

  Node.new(children_array[index], @source)
end

#child_by_field_name(name) ⇒ Node? Also known as: field

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 field name (Prism node accessor)

Prism nodes have specific accessors for their children. This method tries to call that accessor.

Parameters:

  • name (String, Symbol)

    field/accessor name

Returns:

  • (Node, nil)

    wrapped child node



541
542
543
544
545
546
547
548
549
550
551
552
# File 'lib/tree_haver/backends/prism.rb', line 541

def child_by_field_name(name)
  return if @inner_node.nil?
  return unless @inner_node.respond_to?(name)

  result = @inner_node.public_send(name)
  return if result.nil?

  # Wrap if it's a node, otherwise return nil
  if result.is_a?(::Prism::Node)
    Node.new(result, @source)
  end
end

#child_countInteger

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 child nodes

Returns:

  • (Integer)


456
457
458
459
460
# File 'lib/tree_haver/backends/prism.rb', line 456

def child_count
  return 0 if @inner_node.nil?
  return 0 unless @inner_node.respond_to?(:child_nodes)
  @inner_node.child_nodes.compact.size
end

#childrenArray<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 all child nodes

Returns:

  • (Array<Node>)

    array of wrapped child nodes



479
480
481
482
483
484
# File 'lib/tree_haver/backends/prism.rb', line 479

def children
  return [] if @inner_node.nil?
  return [] unless @inner_node.respond_to?(:child_nodes)

  @inner_node.child_nodes.compact.map { |n| Node.new(n, @source) }
end

#each {|Node| ... } ⇒ 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

Yields:

  • (Node)

    each child node

Returns:

  • (Enumerator, nil)


490
491
492
493
# File 'lib/tree_haver/backends/prism.rb', line 490

def each(&block)
  return to_enum(__method__) unless block_given?
  children.each(&block)
end

#end_byteInteger

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 byte offset where the node ends

Returns:

  • (Integer)


365
366
367
368
369
# File 'lib/tree_haver/backends/prism.rb', line 365

def end_byte
  return 0 if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  loc&.end_offset || 0
end

#end_lineInteger

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 1-based line number where this node ends

Returns:

  • (Integer)

    1-based line number



407
408
409
410
411
# File 'lib/tree_haver/backends/prism.rb', line 407

def end_line
  return 1 if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  loc&.end_line || 1
end

#end_pointHash{Symbol => 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 end position as row/column

Returns:

  • (Hash{Symbol => Integer})

    with :row and :column keys



386
387
388
389
390
391
392
393
# File 'lib/tree_haver/backends/prism.rb', line 386

def end_point
  return {row: 0, column: 0} if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  return {row: 0, column: 0} unless loc

  # Prism uses 1-based lines internally but we need 0-based for tree-sitter compat
  {row: (loc.end_line - 1), column: loc.end_column}
end

#first_childNode?

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 first child node

Returns:

  • (Node, nil)

    First child or nil



431
432
433
# File 'lib/tree_haver/backends/prism.rb', line 431

def first_child
  child(0)
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 this node has errors

Returns:

  • (Boolean)


498
499
500
501
502
503
504
505
506
507
# File 'lib/tree_haver/backends/prism.rb', line 498

def has_error?
  return false if @inner_node.nil?

  # Check if this is an error node type
  return true if type.include?("missing") || type.include?("error")

  # Check children recursively (Prism error nodes are usually children)
  return false unless @inner_node.respond_to?(:child_nodes)
  @inner_node.child_nodes.compact.any? { |n| n.class.name.to_s.include?("Missing") }
end

#inspectString

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.

String representation for debugging

Returns:

  • (String)


583
584
585
# File 'lib/tree_haver/backends/prism.rb', line 583

def inspect
  "#<#{self.class} type=#{type} bytes=#{start_byte}..#{end_byte}>"
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 node is a “missing” node (error recovery)

Returns:

  • (Boolean)


512
513
514
515
# File 'lib/tree_haver/backends/prism.rb', line 512

def missing?
  return false if @inner_node.nil?
  type.include?("missing")
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 (structural vs punctuation)

In Prism, all nodes are “named” in tree-sitter terminology (there’s no distinction between named and anonymous nodes).

Returns:

  • (Boolean)


523
524
525
# File 'lib/tree_haver/backends/prism.rb', line 523

def named?
  true
end

#next_siblingvoid

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.

This method returns an undefined value.

Get next sibling

Raises:

  • (NotImplementedError)

    Prism nodes don’t have sibling references



568
569
570
# File 'lib/tree_haver/backends/prism.rb', line 568

def next_sibling
  raise NotImplementedError, "Prism backend does not support sibling navigation"
end

#parentvoid

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.

This method returns an undefined value.

Get the parent node

Raises:

  • (NotImplementedError)

    Prism nodes don’t have parent references



560
561
562
# File 'lib/tree_haver/backends/prism.rb', line 560

def parent
  raise NotImplementedError, "Prism backend does not support parent navigation"
end

#prev_siblingvoid

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.

This method returns an undefined value.

Get previous sibling

Raises:

  • (NotImplementedError)

    Prism nodes don’t have sibling references



576
577
578
# File 'lib/tree_haver/backends/prism.rb', line 576

def prev_sibling
  raise NotImplementedError, "Prism backend does not support sibling navigation"
end

#respond_to_missing?(method_name, include_private = false) ⇒ 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 responds to a method (includes delegation to inner_node)

Parameters:

  • method_name (Symbol)

    method to check

  • include_private (Boolean) (defaults to: false)

    include private methods

Returns:

  • (Boolean)


599
600
601
602
# File 'lib/tree_haver/backends/prism.rb', line 599

def respond_to_missing?(method_name, include_private = false)
  return false if @inner_node.nil?
  @inner_node.respond_to?(method_name, include_private) || super
end

#source_positionHash{Symbol => 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 position information as a hash

Returns a hash with 1-based line numbers and 0-based columns. Compatible with *-merge gems’ FileAnalysisBase.

Returns:

  • (Hash{Symbol => Integer})

    Position hash



419
420
421
422
423
424
425
426
# File 'lib/tree_haver/backends/prism.rb', line 419

def source_position
  {
    start_line: start_line,
    end_line: end_line,
    start_column: start_point[:column],
    end_column: end_point[:column],
  }
end

#start_byteInteger

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 byte offset where the node starts

Returns:

  • (Integer)


356
357
358
359
360
# File 'lib/tree_haver/backends/prism.rb', line 356

def start_byte
  return 0 if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  loc&.start_offset || 0
end

#start_lineInteger

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 1-based line number where this node starts

Returns:

  • (Integer)

    1-based line number



398
399
400
401
402
# File 'lib/tree_haver/backends/prism.rb', line 398

def start_line
  return 1 if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  loc&.start_line || 1
end

#start_pointHash{Symbol => 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 start position as row/column

Returns:

  • (Hash{Symbol => Integer})

    with :row and :column keys



374
375
376
377
378
379
380
381
# File 'lib/tree_haver/backends/prism.rb', line 374

def start_point
  return {row: 0, column: 0} if @inner_node.nil? || !@inner_node.respond_to?(:location)
  loc = @inner_node.location
  return {row: 0, column: 0} unless loc

  # Prism uses 1-based lines internally but we need 0-based for tree-sitter compat
  {row: (loc.start_line - 1), column: loc.start_column}
end

#structural?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 structural node

Returns:

  • (Boolean)


530
531
532
# File 'lib/tree_haver/backends/prism.rb', line 530

def structural?
  true
end

#textString Also known as: slice

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 text content of this node

Returns:

  • (String)


438
439
440
441
442
443
444
445
446
447
448
# File 'lib/tree_haver/backends/prism.rb', line 438

def text
  return "" if @inner_node.nil?

  if @inner_node.respond_to?(:slice)
    @inner_node.slice
  elsif @source
    @source[start_byte...end_byte] || ""
  else
    ""
  end
end

#to_sString

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.

String representation

Returns:

  • (String)


590
591
592
# File 'lib/tree_haver/backends/prism.rb', line 590

def to_s
  text
end

#typeString Also known as: kind

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 node type from Prism class name

Converts PrismClassName to tree-sitter-style type string. Example: CallNode → “call_node”, ProgramNode → “program_node”

Returns:

  • (String)

    node type in snake_case



341
342
343
344
345
346
347
348
# File 'lib/tree_haver/backends/prism.rb', line 341

def type
  return "nil" if @inner_node.nil?

  # Convert class name to snake_case type
  # ProgramNode → program_node, CallNode → call_node
  class_name = @inner_node.class.name.split("::").last
  class_name.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, "")
end