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.



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

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



627
628
629
630
631
632
633
# File 'lib/tree_haver/backends/prism.rb', line 627

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



338
339
340
# File 'lib/tree_haver/backends/prism.rb', line 338

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



341
342
343
# File 'lib/tree_haver/backends/prism.rb', line 341

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



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

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



554
555
556
557
558
559
560
561
562
563
564
565
# File 'lib/tree_haver/backends/prism.rb', line 554

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)


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

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



492
493
494
495
496
497
# File 'lib/tree_haver/backends/prism.rb', line 492

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)


503
504
505
506
# File 'lib/tree_haver/backends/prism.rb', line 503

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)


378
379
380
381
382
# File 'lib/tree_haver/backends/prism.rb', line 378

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



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

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



399
400
401
402
403
404
405
406
# File 'lib/tree_haver/backends/prism.rb', line 399

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



444
445
446
# File 'lib/tree_haver/backends/prism.rb', line 444

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)


511
512
513
514
515
516
517
518
519
520
# File 'lib/tree_haver/backends/prism.rb', line 511

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)


596
597
598
# File 'lib/tree_haver/backends/prism.rb', line 596

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)


525
526
527
528
# File 'lib/tree_haver/backends/prism.rb', line 525

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)


536
537
538
# File 'lib/tree_haver/backends/prism.rb', line 536

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



581
582
583
# File 'lib/tree_haver/backends/prism.rb', line 581

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



573
574
575
# File 'lib/tree_haver/backends/prism.rb', line 573

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



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

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)


612
613
614
615
# File 'lib/tree_haver/backends/prism.rb', line 612

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



432
433
434
435
436
437
438
439
# File 'lib/tree_haver/backends/prism.rb', line 432

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)


369
370
371
372
373
# File 'lib/tree_haver/backends/prism.rb', line 369

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



411
412
413
414
415
# File 'lib/tree_haver/backends/prism.rb', line 411

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



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

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)


543
544
545
# File 'lib/tree_haver/backends/prism.rb', line 543

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)


451
452
453
454
455
456
457
458
459
460
461
# File 'lib/tree_haver/backends/prism.rb', line 451

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)


603
604
605
# File 'lib/tree_haver/backends/prism.rb', line 603

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



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

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