Class: Parlour::RbsGenerator::Namespace

Inherits:
RbsObject show all
Extended by:
T::Generic, T::Sig
Includes:
Mixin::Searchable
Defined in:
lib/parlour/rbs_generator/namespace.rb

Overview

A generic namespace. This shouldn’t be used, except as the type of #root.

Constant Summary collapse

Child =
type_member {{ fixed: RbsObject }}

Instance Attribute Summary collapse

Attributes inherited from RbsObject

#generator

Attributes inherited from TypedObject

#comments, #generated_by, #name

Instance Method Summary collapse

Methods included from Mixin::Searchable

#find, #find_all

Methods inherited from TypedObject

#add_comment, #describe, #describe_tree

Constructor Details

#initialize(generator, name = nil, &block) ⇒ void

Note:

Unless you’re doing something impressively hacky, this shouldn’t be invoked outside of Parlour::RbsGenerator#initialize.

Creates a new namespace.

Parameters:

  • generator (RbsGenerator)

    The current RbsGenerator.

  • name (String, nil) (defaults to: nil)

    The name of this module.

  • final (Boolean)

    Whether this namespace is final.

  • block

    A block which the new instance yields itself to.



42
43
44
45
46
47
# File 'lib/parlour/rbs_generator/namespace.rb', line 42

def initialize(generator, name = nil, &block)
  super(generator, name || '<anonymous namespace>')
  @children = []
  @next_comments = []
  yield_self(&block) if block
end

Instance Attribute Details

#childrenArray<RbsObject> (readonly)

The child RbsObject instances inside this namespace.

Returns:



52
53
54
# File 'lib/parlour/rbs_generator/namespace.rb', line 52

def children
  @children
end

Instance Method Details

#add_comment_to_next_child(comment) ⇒ void

This method returns an undefined value.

Adds one or more comments to the next child RBS object to be created.

Examples:

Creating a module with a comment.

namespace.add_comment_to_next_child('This is a module')
namespace.create_module('M')

Creating a class with a multi-line comment.

namespace.add_comment_to_next_child(['This is a multi-line comment!', 'It can be as long as you want!'])
namespace.create_class('C')

Parameters:

  • comment (String, Array<String>)

    The new comment(s).



139
140
141
142
143
144
145
# File 'lib/parlour/rbs_generator/namespace.rb', line 139

def add_comment_to_next_child(comment)
  if comment.is_a?(String)
    @next_comments << comment
  elsif comment.is_a?(Array)
    @next_comments.concat(comment)
  end
end

#aliasesArray<RbsGenerator::TypeAlias> Also known as: type_aliases

The TypeAlias objects from #children.

Returns:



80
81
82
83
84
85
# File 'lib/parlour/rbs_generator/namespace.rb', line 80

def aliases
  T.cast(
    children.select { |c| c.is_a?(RbsGenerator::TypeAlias) },
    T::Array[RbsGenerator::TypeAlias]
  )
end

#constantsArray<RbsGenerator::Constant>

The Constant objects from #children.

Returns:



91
92
93
94
95
96
# File 'lib/parlour/rbs_generator/namespace.rb', line 91

def constants
  T.cast(
    children.select { |c| c.is_a?(RbsGenerator::Constant) },
    T::Array[RbsGenerator::Constant]
  )
end

#create_arbitrary(code:, &block) ⇒ RbsGenerator::Arbitrary

Creates a new arbitrary code section. You should rarely have to use this!

Parameters:

  • code (String)

    The code to insert.

  • block

    A block which the new instance yields itself to.

Returns:



357
358
359
360
361
362
363
364
365
366
# File 'lib/parlour/rbs_generator/namespace.rb', line 357

def create_arbitrary(code:, &block)
  new_arbitrary = RbsGenerator::Arbitrary.new(
    generator,
    code: code,
    &block
  )
  move_next_comments(new_arbitrary)
  children << new_arbitrary
  new_arbitrary
end

#create_attr_accessor(name, type:, &block) ⇒ RbsGenerator::Attribute

Creates a new read and write attribute (attr_accessor).

Parameters:

  • name (String)

    The name of this attribute.

  • type (Types::TypeLike)

    This attribute’s type.

  • class_attribute (Boolean)

    Whether this attribute belongs to the singleton class.

  • block

    A block which the new instance yields itself to.

Returns:



347
348
349
# File 'lib/parlour/rbs_generator/namespace.rb', line 347

def create_attr_accessor(name, type:, &block)
  create_attribute(name, kind: :accessor, type: type, &block)
end

#create_attr_reader(name, type:, &block) ⇒ RbsGenerator::Attribute

Creates a new read-only attribute (attr_reader).

Parameters:

  • name (String)

    The name of this attribute.

  • type (Types::TypeLike)

    This attribute’s type.

  • class_attribute (Boolean)

    Whether this attribute belongs to the singleton class.

  • block

    A block which the new instance yields itself to.

Returns:



309
310
311
# File 'lib/parlour/rbs_generator/namespace.rb', line 309

def create_attr_reader(name, type:, &block)
  create_attribute(name, kind: :reader, type: type, &block)
end

#create_attr_writer(name, type:, &block) ⇒ RbsGenerator::Attribute

Creates a new write-only attribute (attr_writer).

Parameters:

  • name (String)

    The name of this attribute.

  • type (Types::TypeLike)

    This attribute’s type.

  • class_attribute (Boolean)

    Whether this attribute belongs to the singleton class.

  • block

    A block which the new instance yields itself to.

Returns:



328
329
330
# File 'lib/parlour/rbs_generator/namespace.rb', line 328

def create_attr_writer(name, type:, &block)
  create_attribute(name, kind: :writer, type: type, &block)
end

#create_attribute(name, kind:, type:, &block) ⇒ RbsGenerator::Attribute Also known as: create_attr

Creates a new attribute.

Examples:

Create an attr_reader.

module.create_attribute('readable', kind: :reader, type: 'String')
# #=> attr_reader readable: String

Create an attr_writer.

module.create_attribute('writable', kind: :writer, type: 'Integer')
# #=> attr_writer writable: Integer

Create an attr_accessor.

module.create_attribute('accessible', kind: :accessor, type: Types::Boolean.new)
# #=> attr_accessor accessible: bool

Parameters:

  • name (String)

    The name of this attribute.

  • kind (Symbol)

    The kind of attribute this is; one of :writer, :reader, or :accessor.

  • type (Types::TypeLike)

    This attribute’s type.

  • class_attribute (Boolean)

    Whether this attribute belongs to the singleton class.

  • block

    A block which the new instance yields itself to.

Returns:



280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/parlour/rbs_generator/namespace.rb', line 280

def create_attribute(name, kind:, type:, &block)
  new_attribute = RbsGenerator::Attribute.new(
    generator,
    name,
    kind,
    type,
    &block
  )
  move_next_comments(new_attribute)
  children << new_attribute
  new_attribute
end

#create_class(name, superclass: nil, &block) ⇒ ClassNamespace

Creates a new class definition as a child of this namespace.

Examples:

Create a class with a nested module.

namespace.create_class('Foo') do |foo|
  foo.create_module('Bar')
end

Create a class that is the child of another class.

namespace.create_class('Bar', superclass: 'Foo') #=> class Bar < Foo

Parameters:

  • name (String)

    The name of this class.

  • superclass (String, nil) (defaults to: nil)

    The superclass of this class, or nil if it doesn’t have one.

  • block

    A block which the new instance yields itself to.

Returns:



169
170
171
172
173
174
# File 'lib/parlour/rbs_generator/namespace.rb', line 169

def create_class(name, superclass: nil, &block)
  new_class = ClassNamespace.new(generator, name, superclass, &block)
  move_next_comments(new_class)
  children << new_class
  new_class
end

#create_constant(name, type:, &block) ⇒ RbsGenerator::Constant

Adds a new constant definition to this namespace.

Examples:

Add an Elem constant to the class.

class.create_constant('FOO', type: 'String') #=> FOO: String

Parameters:

  • name (String)

    The name of the constant.

  • type (Types::TypeLike)

    The type of the constant, as a Ruby code string.

  • block

    A block which the new instance yields itself to.

Returns:



450
451
452
453
454
455
456
457
458
459
460
# File 'lib/parlour/rbs_generator/namespace.rb', line 450

def create_constant(name, type:, &block)
  new_constant = RbsGenerator::Constant.new(
    generator,
    name,
    type: type,
    &block
  )
  move_next_comments(new_constant)
  children << new_constant
  new_constant
end

#create_extend(type, &block) ⇒ RbsGenerator::Extend

Adds a new extend to this namespace.

Examples:

Add an extend to a class.

class.create_extend('ExtendableClass') #=> extend ExtendableClass

Parameters:

  • type (Types::TypeLike)

    The type to extend.

  • block

    A block which the new instance yields itself to.

Returns:



377
378
379
380
381
382
383
384
385
386
# File 'lib/parlour/rbs_generator/namespace.rb', line 377

def create_extend(type, &block)
  new_extend = RbsGenerator::Extend.new(
    generator,
    type: type,
    &block
  )
  move_next_comments(new_extend)
  children << new_extend
  new_extend
end

#create_extends(extendables) ⇒ Array<RbsGenerator::Extend>

Adds new extends to this namespace.

Examples:

Add extends to a class.

class.create_extends(['Foo', 'Bar'])

Parameters:

Returns:



396
397
398
399
400
401
402
# File 'lib/parlour/rbs_generator/namespace.rb', line 396

def create_extends(extendables)
  returned_extendables = []
  extendables.each do |extendable|
    returned_extendables << create_extend(extendable)
  end
  returned_extendables
end

#create_include(type, &block) ⇒ RbsGenerator::Include

Adds a new include to this namespace.

Examples:

Add an include to a class.

class.create_include('IncludableClass') #=> include IncludableClass

Parameters:

  • type (Types::TypeLike)

    The type to extend.

  • block

    A block which the new instance yields itself to.

Returns:



413
414
415
416
417
418
419
420
421
422
# File 'lib/parlour/rbs_generator/namespace.rb', line 413

def create_include(type, &block)
  new_include = RbsGenerator::Include.new(
    generator,
    type: type,
    &block
  )
  move_next_comments(new_include)
  children << new_include
  new_include
end

#create_includes(includables) ⇒ Array<RbsGenerator::Include>

Adds new includes to this namespace.

Examples:

Add includes to a class.

class.create_includes(['Foo', 'Bar'])

Parameters:

Returns:



432
433
434
435
436
437
438
# File 'lib/parlour/rbs_generator/namespace.rb', line 432

def create_includes(includables)
  returned_includables = []
  includables.each do |includable|
    returned_includables << create_include(includable)
  end
  returned_includables
end

#create_interface(name, &block) ⇒ InterfaceNamespace

Creates a new interface definition as a child of this namespace.

Examples:

Create a basic interface.

namespace.create_interface('Foo')

Parameters:

  • name (String)

    The name of this interface.

  • block

    A block which the new instance yields itself to.

Returns:



211
212
213
214
215
216
# File 'lib/parlour/rbs_generator/namespace.rb', line 211

def create_interface(name, &block)
  new_interface = InterfaceNamespace.new(generator, name, &block)
  move_next_comments(new_interface)
  children << new_interface
  new_interface
end

#create_method(name, signatures = nil, class_method: false, &block) ⇒ Method

Creates a new method definition as a child of this namespace.

Parameters:

  • name (String)

    The name of this method. You should not specify self. in this - use the class_method parameter instead.

  • signatures (Array<MethodSignature>) (defaults to: nil)

    The signatures for each overload of this method.

  • class_method (Boolean) (defaults to: false)

    Whether this method is a class method; that is, it it is defined using self..

  • block

    A block which the new instance yields itself to.

Returns:



236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/parlour/rbs_generator/namespace.rb', line 236

def create_method(name, signatures = nil, class_method: false, &block)
  raise 'cannot have a method with no signatures' if signatures&.empty?
  new_method = RbsGenerator::Method.new(
    generator,
    name,
    signatures || [MethodSignature.new([], nil)],
    class_method: class_method,
    &block
  )
  move_next_comments(new_method)
  children << new_method
  new_method
end

#create_module(name, &block) ⇒ ModuleNamespace

Creates a new module definition as a child of this namespace.

Examples:

Create a basic module.

namespace.create_module('Foo')

Parameters:

  • name (String)

    The name of this module.

  • block

    A block which the new instance yields itself to.

Returns:



190
191
192
193
194
195
# File 'lib/parlour/rbs_generator/namespace.rb', line 190

def create_module(name, &block)
  new_module = ModuleNamespace.new(generator, name, &block)
  move_next_comments(new_module)
  children << new_module
  new_module
end

#create_type_alias(name, type:, &block) ⇒ RbsGenerator::TypeAlias

Adds a new type alias, in the form of a constant, to this namespace.

Examples:

Add a MyType type alias, to Integer, to the class.

class.create_type_alias('MyType', type: 'Integer') #=> type MyType = Integer

Parameters:

  • name (String)

    The name of the type alias.

  • value (Types::TypeLike)

    The type to alias.

  • block

    A block which the new instance yields itself to.

Returns:



472
473
474
475
476
477
478
479
480
481
482
# File 'lib/parlour/rbs_generator/namespace.rb', line 472

def create_type_alias(name, type:, &block)
  new_type_alias = TypeAlias.new(
    generator,
    name: name,
    type: type,
    &block
  )
  move_next_comments(new_type_alias)
  children << new_type_alias
  new_type_alias
end

#describe_attrsObject



525
526
527
# File 'lib/parlour/rbs_generator/namespace.rb', line 525

def describe_attrs
  [:children]
end

#extendsArray<RbsGenerator::Extend>

The Extend objects from #children.

Returns:



60
61
62
63
64
65
# File 'lib/parlour/rbs_generator/namespace.rb', line 60

def extends
  T.cast(
    children.select { |c| c.is_a?(RbsGenerator::Extend) },
    T::Array[RbsGenerator::Extend]
  )
end

#generate_rbs(indent_level, options) ⇒ Array<String>

Generates the RBS lines for this namespace.

Parameters:

  • indent_level (Integer)

    The indentation level to generate the lines at.

  • options (Options)

    The formatting options to use.

Returns:

  • (Array<String>)

    The RBS lines, formatted as specified.



21
22
23
24
# File 'lib/parlour/rbs_generator/namespace.rb', line 21

def generate_rbs(indent_level, options)
  generate_comments(indent_level, options) +
    generate_body(indent_level, options)
end

#includesArray<RbsGenerator::Include>

The Include objects from #children.

Returns:



70
71
72
73
74
75
# File 'lib/parlour/rbs_generator/namespace.rb', line 70

def includes
  T.cast(
    children.select { |c| c.is_a?(RbsGenerator::Include) },
    T::Array[RbsGenerator::Include]
  )
end

#merge_into_self(others) ⇒ void

This method returns an undefined value.

Given an array of Parlour::RbsGenerator::Namespace instances, merges them into this one. All children, constants, extends and includes are copied into this instance.

There may also be Method instances in the stream, which are ignored.

Parameters:



515
516
517
518
519
520
521
522
# File 'lib/parlour/rbs_generator/namespace.rb', line 515

def merge_into_self(others)
  others.each do |other|
    next if other.is_a?(RbsGenerator::Method)
    other = T.cast(other, Namespace)

    other.children.each { |c| children << c }
  end
end

#mergeable?(others) ⇒ true

Given an array of Parlour::RbsGenerator::Namespace instances, returns true if they may be merged into this instance using #merge_into_self. All bare namespaces can be merged into each other, as they lack definitions for themselves, so there is nothing to conflict. (This isn’t the case for subclasses such as ClassNamespace.)

Parameters:

Returns:

  • (true)

    Always true.



497
498
499
# File 'lib/parlour/rbs_generator/namespace.rb', line 497

def mergeable?(others)
  true
end

#path(object, &block) ⇒ Object

Given a Class or Module object, generates all classes and modules in the path to that object, then executes the given block on the last Parlour::RbsGenerator::Namespace. This should only be executed on the root namespace.

Parameters:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/parlour/rbs_generator/namespace.rb', line 104

def path(object, &block)
  raise 'only call #path on root' if is_a?(ClassNamespace) || is_a?(ModuleNamespace)

  parts = object.to_s.split('::')
  parts_with_types = parts.size.times.map do |i|
    [parts[i], Module.const_get(parts[0..i].join('::')).class]
  end

  current_part = self
  parts_with_types.each do |(name, type)|
    if type == Class
      current_part = current_part.create_class(name)
    elsif type == Module
      current_part = current_part.create_module(name)
    else
      raise "unexpected type: path part #{name} is a #{type}"
    end
  end

  block.call(current_part)
end