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 behind the current TreeHaver 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.



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

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



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

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)



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

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



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

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



445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 445

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
  return unless result.respond_to?(:location)

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



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

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

  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)


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

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



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

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



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

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)


474
475
476
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 474

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)


463
464
465
466
467
468
469
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 463

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)


490
491
492
493
494
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 490

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)


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

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



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

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)


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

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



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

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



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

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)


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

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

  loc = @inner_node.location
  source.byteslice(loc.start_pos, loc.end_pos - loc.start_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)


481
482
483
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 481

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



290
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
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 290

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