Class: Parlour::RbsGenerator::Namespace

Inherits:
RbsObject show all
Extended by:
T::Sig
Defined in:
lib/parlour/rbs_generator/namespace.rb

Overview

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

Instance Attribute Summary collapse

Attributes inherited from RbsObject

#generator

Attributes inherited from TypedObject

#comments, #generated_by, #name

Instance Method Summary collapse

Methods inherited from TypedObject

#add_comment

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.



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

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:



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

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



135
136
137
138
139
140
141
# File 'lib/parlour/rbs_generator/namespace.rb', line 135

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:



76
77
78
79
80
81
# File 'lib/parlour/rbs_generator/namespace.rb', line 76

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:



87
88
89
90
91
92
# File 'lib/parlour/rbs_generator/namespace.rb', line 87

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:



353
354
355
356
357
358
359
360
361
362
# File 'lib/parlour/rbs_generator/namespace.rb', line 353

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:



343
344
345
# File 'lib/parlour/rbs_generator/namespace.rb', line 343

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:



305
306
307
# File 'lib/parlour/rbs_generator/namespace.rb', line 305

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:



324
325
326
# File 'lib/parlour/rbs_generator/namespace.rb', line 324

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:



276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/parlour/rbs_generator/namespace.rb', line 276

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:



165
166
167
168
169
170
# File 'lib/parlour/rbs_generator/namespace.rb', line 165

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:



446
447
448
449
450
451
452
453
454
455
456
# File 'lib/parlour/rbs_generator/namespace.rb', line 446

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:



373
374
375
376
377
378
379
380
381
382
# File 'lib/parlour/rbs_generator/namespace.rb', line 373

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:



392
393
394
395
396
397
398
# File 'lib/parlour/rbs_generator/namespace.rb', line 392

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:



409
410
411
412
413
414
415
416
417
418
# File 'lib/parlour/rbs_generator/namespace.rb', line 409

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:



428
429
430
431
432
433
434
# File 'lib/parlour/rbs_generator/namespace.rb', line 428

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:



207
208
209
210
211
212
# File 'lib/parlour/rbs_generator/namespace.rb', line 207

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:



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/parlour/rbs_generator/namespace.rb', line 232

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:



186
187
188
189
190
191
# File 'lib/parlour/rbs_generator/namespace.rb', line 186

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:



468
469
470
471
472
473
474
475
476
477
478
# File 'lib/parlour/rbs_generator/namespace.rb', line 468

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

#describeString

Returns a human-readable brief string description of this namespace.

Returns:

  • (String)


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

def describe
  "Namespace #{name} - #{children.length} children, #{includes.length} " +
    "includes, #{extends.length} extends, #{constants.length} constants"
end

#extendsArray<RbsGenerator::Extend>

The Extend objects from #children.

Returns:



56
57
58
59
60
61
# File 'lib/parlour/rbs_generator/namespace.rb', line 56

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.



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

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:



66
67
68
69
70
71
# File 'lib/parlour/rbs_generator/namespace.rb', line 66

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:



511
512
513
514
515
516
517
518
# File 'lib/parlour/rbs_generator/namespace.rb', line 511

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.



493
494
495
# File 'lib/parlour/rbs_generator/namespace.rb', line 493

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:



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/parlour/rbs_generator/namespace.rb', line 100

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