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.



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

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



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

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)



263
264
265
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 263

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



277
278
279
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 277

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



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

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)


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

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



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

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



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

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
# 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)


410
411
412
# File 'lib/rbs/merge/backends/rbs_backend.rb', line 410

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



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

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)


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

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



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

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



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

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)


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

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



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

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