Class: Rbs::Merge::Backends::RbsBackend::Node Private

Inherits:
TreeHaver::Base::Node
  • Object
show all
Defined in:
lib/rbs/merge/backends/rbs_backend.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.

RBS node wrapper

Wraps RBS AST nodes to provide tree-sitter-compatible node API.

RBS nodes provide:

  • Various declaration types (Class, Module, Interface, TypeAlias, etc.)
  • Member types (MethodDefinition, Alias, AttrReader, etc.)
  • Location information via .location

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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



268
269
270
271
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 268

def initialize(node, source: nil, lines: nil, children_array: nil)
  super(node, source: source, lines: lines)
  @children_array = children_array
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 RBS node

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



505
506
507
508
509
510
511
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 505

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

#children_arrayArray<Object> (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 child nodes (for synthetic root).

Returns:

  • (Array<Object>)

    child nodes (for synthetic root)



266
267
268
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 266

def children_array
  @children_array
end

Class Method Details

.new_root(declarations, source: nil, lines: nil) ⇒ 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.

Create a synthetic root node containing all declarations

Parameters:

  • declarations (Array)

    the declarations

  • source (String) (defaults to: nil)

    the source code

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

    pre-split source lines

Returns:

  • (Node)

    synthetic root node



280
281
282
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 280

def new_root(declarations, source: nil, lines: nil)
  new(nil, source: source, lines: lines, children_array: declarations)
end

Instance Method Details

#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 (RBS node accessor)

RBS 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



448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 448

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.respond_to?(:location)
    Node.new(result, source: source, lines: lines)
  end
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



431
432
433
434
435
436
437
438
439
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 431

def children
  if root_node?
    return @children_array.map { |n| Node.new(n, source: source, lines: lines) }
  end

  return [] unless @inner_node.respond_to?(:members)

  @inner_node.members.map { |n| Node.new(n, source: source, lines: lines) }
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)


342
343
344
345
346
347
348
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 342

def end_byte
  return source.bytesize if root_node? && source
  return 0 if root_node?
  return 0 unless @inner_node.respond_to?(:location) && @inner_node.location

  @inner_node.location.end_pos
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



390
391
392
393
394
395
396
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 390

def end_line
  return lines.size if root_node? && lines.any?
  return 1 if root_node?
  return 1 unless @inner_node.respond_to?(:location) && @inner_node.location

  @inner_node.location.end_line
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 (0-based)

Returns:

  • (Hash{Symbol => Integer})

    with :row and :column keys



364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 364

def end_point
  if root_node? && source
    last_line = lines.size - 1
    last_col = lines.last&.size || 0
    return {row: last_line, column: last_col}
  end
  return {row: 0, column: 0} if root_node?
  return {row: 0, column: 0} unless @inner_node.respond_to?(:location) && @inner_node.location

  loc = @inner_node.location
  {row: loc.end_line - 1, column: loc.end_column}
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)


477
478
479
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 477

def inspect
  "#<#{self.class} type=#{type} lines=#{start_line}..#{end_line}>"
end

#nameString?

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 name of this declaration/member

Returns:

  • (String, nil)


466
467
468
469
470
471
472
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 466

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

  n = @inner_node.name
  n.respond_to?(:to_s) ? n.to_s : n
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)


493
494
495
496
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 493

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

#root_node?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 synthetic root node

Returns:

  • (Boolean)


413
414
415
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 413

def root_node?
  @inner_node.nil? && @children_array
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:

  • (Hash{Symbol => Integer})

    Position hash



401
402
403
404
405
406
407
408
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 401

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)


332
333
334
335
336
337
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 332

def start_byte
  return 0 if root_node?
  return 0 unless @inner_node.respond_to?(:location) && @inner_node.location

  @inner_node.location.start_pos
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



380
381
382
383
384
385
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 380

def start_line
  return 1 if root_node?
  return 1 unless @inner_node.respond_to?(:location) && @inner_node.location

  @inner_node.location.start_line
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 (0-based)

Returns:

  • (Hash{Symbol => Integer})

    with :row and :column keys



353
354
355
356
357
358
359
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 353

def start_point
  return {row: 0, column: 0} if root_node?
  return {row: 0, column: 0} unless @inner_node.respond_to?(:location) && @inner_node.location

  loc = @inner_node.location
  {row: loc.start_line - 1, column: loc.start_column}
end

#textString

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)


420
421
422
423
424
425
426
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 420

def text
  return source.to_s if root_node?
  return "" unless @inner_node.respond_to?(:location) && @inner_node.location

  loc = @inner_node.location
  source[loc.start_pos...loc.end_pos] || ""
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)


484
485
486
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 484

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 RBS class name

Maps RBS::AST class names to tree-sitter-style type strings.
For synthetic root, returns “program”.

Returns:

  • (String)

    node type



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 291

def type
  return "program" if root_node?

  return "unknown" if @inner_node.nil?

  # Map RBS class to canonical type
  case @inner_node
  when ::RBS::AST::Declarations::Class then "class_decl"
  when ::RBS::AST::Declarations::Module then "module_decl"
  when ::RBS::AST::Declarations::Interface then "interface_decl"
  when ::RBS::AST::Declarations::TypeAlias then "type_alias_decl"
  when ::RBS::AST::Declarations::Constant then "const_decl"
  when ::RBS::AST::Declarations::Global then "global_decl"
  when ::RBS::AST::Declarations::ClassAlias then "class_alias_decl"
  when ::RBS::AST::Declarations::ModuleAlias then "module_alias_decl"
  when ::RBS::AST::Members::MethodDefinition then "method_member"
  when ::RBS::AST::Members::Alias then "alias_member"
  when ::RBS::AST::Members::AttrReader then "attr_reader_member"
  when ::RBS::AST::Members::AttrWriter then "attr_writer_member"
  when ::RBS::AST::Members::AttrAccessor then "attr_accessor_member"
  when ::RBS::AST::Members::Include then "include_member"
  when ::RBS::AST::Members::Extend then "extend_member"
  when ::RBS::AST::Members::Prepend then "prepend_member"
  when ::RBS::AST::Members::InstanceVariable then "ivar_member"
  when ::RBS::AST::Members::ClassInstanceVariable then "civar_member"
  when ::RBS::AST::Members::ClassVariable then "cvar_member"
  when ::RBS::AST::Members::Public then "public_member"
  when ::RBS::AST::Members::Private then "private_member"
  else
    # Fallback to class name conversion
    @inner_node.class.name.split("::").last
      .gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, "")
  end
end