parlour 2.0.0 → 5.0.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  3. data/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  4. data/.gitignore +1 -1
  5. data/.parlour +5 -0
  6. data/.rspec +0 -0
  7. data/.travis.yml +3 -3
  8. data/CHANGELOG.md +64 -0
  9. data/CODE_OF_CONDUCT.md +0 -0
  10. data/Gemfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +233 -19
  13. data/Rakefile +0 -0
  14. data/exe/parlour +109 -4
  15. data/lib/parlour.rb +29 -1
  16. data/lib/parlour/conflict_resolver.rb +75 -27
  17. data/lib/parlour/conversion/converter.rb +34 -0
  18. data/lib/parlour/conversion/rbi_to_rbs.rb +223 -0
  19. data/lib/parlour/debugging.rb +0 -0
  20. data/lib/parlour/detached_rbi_generator.rb +1 -6
  21. data/lib/parlour/detached_rbs_generator.rb +25 -0
  22. data/lib/parlour/generator.rb +34 -0
  23. data/lib/parlour/kernel_hack.rb +0 -0
  24. data/lib/parlour/options.rb +71 -0
  25. data/lib/parlour/parse_error.rb +0 -0
  26. data/lib/parlour/plugin.rb +1 -1
  27. data/lib/parlour/rbi_generator.rb +24 -37
  28. data/lib/parlour/rbi_generator/arbitrary.rb +5 -2
  29. data/lib/parlour/rbi_generator/attribute.rb +14 -5
  30. data/lib/parlour/rbi_generator/class_namespace.rb +8 -3
  31. data/lib/parlour/rbi_generator/constant.rb +28 -8
  32. data/lib/parlour/rbi_generator/enum_class_namespace.rb +32 -5
  33. data/lib/parlour/rbi_generator/extend.rb +5 -2
  34. data/lib/parlour/rbi_generator/include.rb +5 -2
  35. data/lib/parlour/rbi_generator/method.rb +15 -10
  36. data/lib/parlour/rbi_generator/module_namespace.rb +7 -2
  37. data/lib/parlour/rbi_generator/namespace.rb +115 -27
  38. data/lib/parlour/rbi_generator/parameter.rb +13 -7
  39. data/lib/parlour/rbi_generator/rbi_object.rb +19 -78
  40. data/lib/parlour/rbi_generator/struct_class_namespace.rb +110 -0
  41. data/lib/parlour/rbi_generator/struct_prop.rb +139 -0
  42. data/lib/parlour/rbi_generator/type_alias.rb +101 -0
  43. data/lib/parlour/rbs_generator.rb +24 -0
  44. data/lib/parlour/rbs_generator/arbitrary.rb +92 -0
  45. data/lib/parlour/rbs_generator/attribute.rb +82 -0
  46. data/lib/parlour/rbs_generator/block.rb +49 -0
  47. data/lib/parlour/rbs_generator/class_namespace.rb +106 -0
  48. data/lib/parlour/rbs_generator/constant.rb +95 -0
  49. data/lib/parlour/rbs_generator/extend.rb +92 -0
  50. data/lib/parlour/rbs_generator/include.rb +92 -0
  51. data/lib/parlour/rbs_generator/interface_namespace.rb +34 -0
  52. data/lib/parlour/rbs_generator/method.rb +146 -0
  53. data/lib/parlour/rbs_generator/method_signature.rb +104 -0
  54. data/lib/parlour/rbs_generator/module_namespace.rb +35 -0
  55. data/lib/parlour/rbs_generator/namespace.rb +627 -0
  56. data/lib/parlour/rbs_generator/parameter.rb +145 -0
  57. data/lib/parlour/rbs_generator/rbs_object.rb +78 -0
  58. data/lib/parlour/rbs_generator/type_alias.rb +96 -0
  59. data/lib/parlour/type_loader.rb +30 -10
  60. data/lib/parlour/type_parser.rb +440 -43
  61. data/lib/parlour/typed_object.rb +87 -0
  62. data/lib/parlour/types.rb +445 -0
  63. data/lib/parlour/version.rb +1 -1
  64. data/parlour.gemspec +2 -2
  65. data/plugin_examples/foobar_plugin.rb +0 -0
  66. data/rbi/parlour.rbi +1799 -0
  67. metadata +42 -15
  68. data/lib/parlour/rbi_generator/options.rb +0 -74
@@ -1,13 +1,13 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents an enum definition; that is, a class with an +enum+ call.
5
5
  class EnumClassNamespace < ClassNamespace
6
6
  extend T::Sig
7
7
 
8
8
  sig do
9
9
  params(
10
- generator: RbiGenerator,
10
+ generator: Generator,
11
11
  name: String,
12
12
  final: T::Boolean,
13
13
  enums: T::Array[T.any([String, String], String)],
@@ -38,7 +38,7 @@ module Parlour
38
38
  sig do
39
39
  override.params(
40
40
  indent_level: Integer,
41
- options: Options
41
+ options: Options,
42
42
  ).returns(T::Array[String])
43
43
  end
44
44
  # Generates the RBI lines for the body of this enum. This consists of
@@ -80,10 +80,37 @@ module Parlour
80
80
  # @param others [Array<RbiGenerator::RbiObject>] An array of other {EnumClassNamespace} instances.
81
81
  # @return [Boolean] Whether this instance may be merged with them.
82
82
  def mergeable?(others)
83
- others = T.cast(others, T::Array[EnumClassNamespace]) rescue (return false)
83
+ others = T.cast(others, T::Array[Namespace]) rescue (return false)
84
84
  all = others + [self]
85
+ all_enums = T.cast(all.select { |x| EnumClassNamespace === x }, T::Array[EnumClassNamespace])
85
86
 
86
- T.must(super && all.map(&:enums).uniq.length <= 1)
87
+ T.must(super && all_enums.map { |e| e.enums.sort }.reject(&:empty?).uniq.length <= 1)
88
+ end
89
+
90
+ sig do
91
+ override.params(
92
+ others: T::Array[RbiGenerator::RbiObject]
93
+ ).void
94
+ end
95
+ # Given an array of {EnumClassNamespace} instances, merges them into this one.
96
+ # You MUST ensure that {mergeable?} is true for those instances.
97
+ #
98
+ # @param others [Array<RbiGenerator::RbiObject>] An array of other {EnumClassNamespace} instances.
99
+ # @return [void]
100
+ def merge_into_self(others)
101
+ super
102
+
103
+ others.each do |other|
104
+ next unless EnumClassNamespace === other
105
+ other = T.cast(other, EnumClassNamespace)
106
+
107
+ @enums = other.enums if enums.empty?
108
+ end
109
+ end
110
+
111
+ sig { override.void }
112
+ def generalize_from_rbi!
113
+ super
87
114
  end
88
115
  end
89
116
  end
@@ -1,11 +1,11 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents an +extend+ call.
5
5
  class Extend < RbiObject
6
6
  sig do
7
7
  params(
8
- generator: RbiGenerator,
8
+ generator: Generator,
9
9
  name: String,
10
10
  block: T.nilable(T.proc.params(x: Extend).void)
11
11
  ).void
@@ -82,6 +82,9 @@ module Parlour
82
82
  def describe
83
83
  "Extend (#{name})"
84
84
  end
85
+
86
+ sig { override.void }
87
+ def generalize_from_rbi!; end # Nothing to do
85
88
  end
86
89
  end
87
90
  end
@@ -1,11 +1,11 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents an +include+ call.
5
5
  class Include < RbiObject
6
6
  sig do
7
7
  params(
8
- generator: RbiGenerator,
8
+ generator: Generator,
9
9
  name: String,
10
10
  block: T.nilable(T.proc.params(x: Include).void)
11
11
  ).void
@@ -82,6 +82,9 @@ module Parlour
82
82
  def describe
83
83
  "Include (#{name})"
84
84
  end
85
+
86
+ sig { override.void }
87
+ def generalize_from_rbi!; end # Nothing to do
85
88
  end
86
89
  end
87
90
  end
@@ -1,16 +1,16 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents a method definition.
5
5
  class Method < RbiObject
6
6
  extend T::Sig
7
7
 
8
8
  sig do
9
9
  params(
10
- generator: RbiGenerator,
10
+ generator: Generator,
11
11
  name: String,
12
12
  parameters: T::Array[Parameter],
13
- return_type: T.nilable(String),
13
+ return_type: T.nilable(Types::TypeLike),
14
14
  abstract: T::Boolean,
15
15
  implementation: T::Boolean,
16
16
  override: T::Boolean,
@@ -29,8 +29,7 @@ module Parlour
29
29
  # this - use the +class_method+ parameter instead.
30
30
  # @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
31
31
  # method's parameters.
32
- # @param return_type [String, nil] A Sorbet string of what this method returns, such as
33
- # +"String"+ or +"T.untyped"+. Passing nil denotes a void return.
32
+ # @param return_type [Types::TypeLike, nil] What this method returns. Passing nil denotes a void return.
34
33
  # @param abstract [Boolean] Whether this method is abstract.
35
34
  # @param implementation [Boolean] DEPRECATED: Whether this method is an
36
35
  # implementation of a parent abstract method.
@@ -82,10 +81,9 @@ module Parlour
82
81
  # @return [Array<Parameter>]
83
82
  attr_reader :parameters
84
83
 
85
- sig { returns(T.nilable(String)) }
86
- # A Sorbet string of what this method returns, such as "String" or
87
- # "T.untyped". Passing nil denotes a void return.
88
- # @return [String, nil]
84
+ sig { returns(T.nilable(Types::TypeLike)) }
85
+ # What this method returns. Passing nil denotes a void return.
86
+ # @return [Types::TypeLike, nil]
89
87
  attr_reader :return_type
90
88
 
91
89
  sig { returns(T::Boolean) }
@@ -140,7 +138,7 @@ module Parlour
140
138
  # @param options [Options] The formatting options to use.
141
139
  # @return [Array<String>] The RBI lines, formatted as specified.
142
140
  def generate_rbi(indent_level, options)
143
- return_call = return_type ? "returns(#{return_type})" : 'void'
141
+ return_call = @return_type ? "returns(#{String === @return_type ? @return_type : @return_type.generate_rbi})" : 'void'
144
142
  sig_args = final ? '(:final)' : ''
145
143
 
146
144
  sig_params = parameters.map(&:to_sig_param)
@@ -218,6 +216,13 @@ module Parlour
218
216
  " returns #{return_type}"
219
217
  end
220
218
 
219
+ sig { override.void }
220
+ def generalize_from_rbi!
221
+ @return_type = TypeParser.parse_single_type(@return_type) if String === @return_type
222
+
223
+ parameters.each(&:generalize_from_rbi!)
224
+ end
225
+
221
226
  private
222
227
 
223
228
  sig do
@@ -1,13 +1,13 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents a module definition.
5
5
  class ModuleNamespace < Namespace
6
6
  extend T::Sig
7
7
 
8
8
  sig do
9
9
  params(
10
- generator: RbiGenerator,
10
+ generator: Generator,
11
11
  name: String,
12
12
  final: T::Boolean,
13
13
  interface: T::Boolean,
@@ -96,6 +96,11 @@ module Parlour
96
96
  "Module #{name} - #{"interface, " if interface}#{children.length} " +
97
97
  "children, #{includes.length} includes, #{extends.length} extends"
98
98
  end
99
+
100
+ sig { override.void }
101
+ def generalize_from_rbi!
102
+ super
103
+ end
99
104
  end
100
105
  end
101
106
  end
@@ -1,6 +1,6 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # A generic namespace. This shouldn't be used, except as the type of
5
5
  # {RbiGenerator#root}.
6
6
  class Namespace < RbiObject
@@ -24,7 +24,7 @@ module Parlour
24
24
 
25
25
  sig do
26
26
  params(
27
- generator: RbiGenerator,
27
+ generator: Generator,
28
28
  name: T.nilable(String),
29
29
  final: T::Boolean,
30
30
  block: T.nilable(T.proc.params(x: Namespace).void)
@@ -77,6 +77,17 @@ module Parlour
77
77
  )
78
78
  end
79
79
 
80
+ sig { returns(T::Array[RbiGenerator::TypeAlias]) }
81
+ # The {RbiGenerator::TypeAlias} objects from {children}.
82
+ # @return [Array<RbiGenerator::TypeAlias>]
83
+ def aliases
84
+ T.cast(
85
+ children.select { |c| c.is_a?(RbiGenerator::TypeAlias) },
86
+ T::Array[RbiGenerator::TypeAlias]
87
+ )
88
+ end
89
+ alias type_aliases aliases
90
+
80
91
  sig { returns(T::Array[RbiGenerator::Constant]) }
81
92
  # The {RbiGenerator::Constant} objects from {children}.
82
93
  # @return [Array<RbiGenerator::Constant>]
@@ -196,6 +207,35 @@ module Parlour
196
207
  new_enum_class
197
208
  end
198
209
 
210
+ sig do
211
+ params(
212
+ name: String,
213
+ final: T::Boolean,
214
+ props: T.nilable(T::Array[StructProp]),
215
+ abstract: T::Boolean,
216
+ block: T.nilable(T.proc.params(x: StructClassNamespace).void)
217
+ ).returns(StructClassNamespace)
218
+ end
219
+ # Creates a new struct class definition as a child of this namespace.
220
+ #
221
+ # @example Create a person struct.
222
+ # namespace.create_class('Person', props: [
223
+ # Parlour::RbiGenerator::StructProp.new('name', 'String')
224
+ # ])
225
+ #
226
+ # @param name [String] The name of this class.
227
+ # @param final [Boolean] Whether this namespace is final.
228
+ # @param props [Array<StructProp>] The props of the struct.
229
+ # @param abstract [Boolean] A boolean indicating whether this class is abstract.
230
+ # @param block A block which the new instance yields itself to.
231
+ # @return [EnumClassNamespace]
232
+ def create_struct_class(name, final: false, props: nil, abstract: false, &block)
233
+ new_struct_class = StructClassNamespace.new(generator, name, final, props || [], abstract, &block)
234
+ move_next_comments(new_struct_class)
235
+ children << new_struct_class
236
+ new_struct_class
237
+ end
238
+
199
239
  sig do
200
240
  params(
201
241
  name: String,
@@ -231,7 +271,7 @@ module Parlour
231
271
  params(
232
272
  name: String,
233
273
  parameters: T.nilable(T::Array[Parameter]),
234
- return_type: T.nilable(String),
274
+ return_type: T.nilable(Types::TypeLike),
235
275
  returns: T.nilable(String),
236
276
  abstract: T::Boolean,
237
277
  implementation: T::Boolean,
@@ -247,13 +287,13 @@ module Parlour
247
287
  #
248
288
  # @param name [String] The name of this method. You should not specify +self.+ in
249
289
  # this - use the +class_method+ parameter instead.
250
- # @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
290
+ # @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
251
291
  # method's parameters.
252
292
  # @param return_type [String, nil] A Sorbet string of what this method returns, such as
253
293
  # +"String"+ or +"T.untyped"+. Passing nil denotes a void return.
254
294
  # @param returns [String, nil] Same as return_type.
255
295
  # @param abstract [Boolean] Whether this method is abstract.
256
- # @param implementation [Boolean] DEPRECATED: Whether this method is an
296
+ # @param implementation [Boolean] DEPRECATED: Whether this method is an
257
297
  # implementation of a parent abstract method.
258
298
  # @param override [Boolean] Whether this method is overriding a parent overridable
259
299
  # method, or implementing a parent abstract method.
@@ -291,7 +331,7 @@ module Parlour
291
331
  params(
292
332
  name: String,
293
333
  kind: Symbol,
294
- type: String,
334
+ type: Types::TypeLike,
295
335
  class_attribute: T::Boolean,
296
336
  block: T.nilable(T.proc.params(x: Attribute).void)
297
337
  ).returns(Attribute)
@@ -347,7 +387,7 @@ module Parlour
347
387
  sig do
348
388
  params(
349
389
  name: String,
350
- type: String,
390
+ type: Types::TypeLike,
351
391
  class_attribute: T::Boolean,
352
392
  block: T.nilable(T.proc.params(x: Attribute).void)
353
393
  ).returns(Attribute)
@@ -368,7 +408,7 @@ module Parlour
368
408
  sig do
369
409
  params(
370
410
  name: String,
371
- type: String,
411
+ type: Types::TypeLike,
372
412
  class_attribute: T::Boolean,
373
413
  block: T.nilable(T.proc.params(x: Attribute).void)
374
414
  ).returns(Attribute)
@@ -389,7 +429,7 @@ module Parlour
389
429
  sig do
390
430
  params(
391
431
  name: String,
392
- type: String,
432
+ type: Types::TypeLike,
393
433
  class_attribute: T::Boolean,
394
434
  block: T.nilable(T.proc.params(x: Attribute).void)
395
435
  ).returns(Attribute)
@@ -498,7 +538,7 @@ module Parlour
498
538
  returned_includables
499
539
  end
500
540
 
501
- sig { params(name: String, value: String, block: T.nilable(T.proc.params(x: Constant).void)).returns(Constant) }
541
+ sig { params(name: String, value: String, eigen_constant: T::Boolean, block: T.nilable(T.proc.params(x: Constant).void)).returns(Constant) }
502
542
  # Adds a new constant definition to this namespace.
503
543
  #
504
544
  # @example Add an +Elem+ constant to the class.
@@ -506,13 +546,16 @@ module Parlour
506
546
  #
507
547
  # @param name [String] The name of the constant.
508
548
  # @param value [String] The value of the constant, as a Ruby code string.
549
+ # @param eigen_constant [Boolean] Whether this constant is defined on the
550
+ # eigenclass of the current namespace.
509
551
  # @param block A block which the new instance yields itself to.
510
552
  # @return [RbiGenerator::Constant]
511
- def create_constant(name, value:, &block)
553
+ def create_constant(name, value:, eigen_constant: false, &block)
512
554
  new_constant = RbiGenerator::Constant.new(
513
555
  generator,
514
556
  name: name,
515
557
  value: value,
558
+ eigen_constant: eigen_constant,
516
559
  &block
517
560
  )
518
561
  move_next_comments(new_constant)
@@ -520,7 +563,7 @@ module Parlour
520
563
  new_constant
521
564
  end
522
565
 
523
- sig { params(name: String, type: String, block: T.nilable(T.proc.params(x: Constant).void)).returns(Constant) }
566
+ sig { params(name: String, type: Types::TypeLike, block: T.nilable(T.proc.params(x: TypeAlias).void)).returns(TypeAlias) }
524
567
  # Adds a new type alias, in the form of a constant, to this namespace.
525
568
  #
526
569
  # @example Add a +MyType+ type alias, to +Integer+, to the class.
@@ -531,7 +574,15 @@ module Parlour
531
574
  # @param block A block which the new instance yields itself to.
532
575
  # @return [RbiGenerator::Constant]
533
576
  def create_type_alias(name, type:, &block)
534
- create_constant(name, value: "T.type_alias { #{type} }", &block)
577
+ new_type_alias = RbiGenerator::TypeAlias.new(
578
+ generator,
579
+ name: name,
580
+ type: type,
581
+ &block
582
+ )
583
+ move_next_comments(new_type_alias)
584
+ children << new_type_alias
585
+ new_type_alias
535
586
  end
536
587
 
537
588
  sig do
@@ -544,25 +595,25 @@ module Parlour
544
595
  # can be merged into each other, as they lack definitions for themselves,
545
596
  # so there is nothing to conflict. (This isn't the case for subclasses
546
597
  # such as {ClassNamespace}.)
547
- #
598
+ #
548
599
  # @param others [Array<RbiGenerator::RbiObject>] An array of other {Namespace} instances.
549
600
  # @return [true] Always true.
550
601
  def mergeable?(others)
551
602
  true
552
603
  end
553
604
 
554
- sig do
605
+ sig do
555
606
  override.overridable.params(
556
607
  others: T::Array[RbiGenerator::RbiObject]
557
608
  ).void
558
609
  end
559
610
  # Given an array of {Namespace} instances, merges them into this one.
560
- # All children, constants, extends and includes are copied into this
611
+ # All children, constants, extends and includes are copied into this
561
612
  # instance.
562
613
  #
563
614
  # There may also be {RbiGenerator::Method} instances in the stream, which
564
615
  # are ignored.
565
- #
616
+ #
566
617
  # @param others [Array<RbiGenerator::RbiObject>] An array of other {Namespace} instances.
567
618
  # @return [void]
568
619
  def merge_into_self(others)
@@ -583,12 +634,17 @@ module Parlour
583
634
  "includes, #{extends.length} extends, #{constants.length} constants"
584
635
  end
585
636
 
637
+ sig { override.void }
638
+ def generalize_from_rbi!
639
+ children.each(&:generalize_from_rbi!)
640
+ end
641
+
586
642
  private
587
643
 
588
644
  sig do
589
645
  overridable.params(
590
646
  indent_level: Integer,
591
- options: Options
647
+ options: Options,
592
648
  ).returns(T::Array[String])
593
649
  end
594
650
  # Generates the RBI lines for the body of this namespace. This consists of
@@ -602,39 +658,71 @@ module Parlour
602
658
 
603
659
  result += [options.indented(indent_level, 'final!'), ''] if final
604
660
 
605
- if includes.any? || extends.any? || constants.any?
661
+ # Split away the eigen constants; these need to be put in a
662
+ # "class << self" block later
663
+ eigen_constants, non_eigen_constants = constants.partition(&:eigen_constant)
664
+ eigen_constants.sort_by!(&:name) if options.sort_namespaces
665
+
666
+ if includes.any? || extends.any? || aliases.any? || non_eigen_constants.any?
606
667
  result += (options.sort_namespaces ? includes.sort_by(&:name) : includes)
607
668
  .flat_map { |x| x.generate_rbi(indent_level, options) }
608
669
  .reject { |x| x.strip == '' }
609
670
  result += (options.sort_namespaces ? extends.sort_by(&:name) : extends)
610
671
  .flat_map { |x| x.generate_rbi(indent_level, options) }
611
672
  .reject { |x| x.strip == '' }
612
- result += (options.sort_namespaces ? constants.sort_by(&:name) : constants)
673
+ result += (options.sort_namespaces ? aliases.sort_by(&:name) : aliases)
674
+ .flat_map { |x| x.generate_rbi(indent_level, options) }
675
+ .reject { |x| x.strip == '' }
676
+ result += (options.sort_namespaces ? non_eigen_constants.sort_by(&:name) : non_eigen_constants)
613
677
  .flat_map { |x| x.generate_rbi(indent_level, options) }
614
678
  .reject { |x| x.strip == '' }
615
679
  result << ""
616
680
  end
617
681
 
618
682
  # Process singleton class attributes
619
- class_attributes, remaining_children = \
620
- (options.sort_namespaces ? children.sort_by(&:name) : children)
621
- .partition { |child| child.is_a?(Attribute) && child.class_attribute }
622
-
623
- if class_attributes.any?
624
- result << options.indented(indent_level, 'class << self')
683
+ sorted_children = (
684
+ if options.sort_namespaces
685
+ # sort_by can be unstable (and is in current MRI).
686
+ # Use the this work around to preserve order for ties
687
+ children.sort_by.with_index { |child, i| [child.name, i] }
688
+ else
689
+ children
690
+ end
691
+ )
692
+ class_attributes, remaining_children = sorted_children.partition do |child|
693
+ child.is_a?(Attribute) && child.class_attribute
694
+ end
695
+
696
+ # Handle the "class << self block"
697
+ result << options.indented(indent_level, 'class << self') \
698
+ if class_attributes.any? || eigen_constants.any?
699
+
700
+ if eigen_constants.any?
701
+ first, *rest = eigen_constants
702
+ result += T.must(first).generate_rbi(indent_level + 1, options) + T.must(rest)
703
+ .map { |obj| obj.generate_rbi(indent_level + 1, options) }
704
+ .map { |lines| [""] + lines }
705
+ .flatten
706
+ end
707
+
708
+ result << '' if eigen_constants.any? && class_attributes.any?
625
709
 
710
+ if class_attributes.any?
626
711
  first, *rest = class_attributes
627
712
  result += T.must(first).generate_rbi(indent_level + 1, options) + T.must(rest)
628
713
  .map { |obj| obj.generate_rbi(indent_level + 1, options) }
629
714
  .map { |lines| [""] + lines }
630
715
  .flatten
716
+ end
717
+
718
+ if class_attributes.any? || eigen_constants.any?
631
719
  result << options.indented(indent_level, 'end')
632
720
  result << ''
633
721
  end
634
722
 
635
723
  first, *rest = remaining_children.reject do |child|
636
724
  # We already processed these kinds of children
637
- child.is_a?(Include) || child.is_a?(Extend) || child.is_a?(Constant)
725
+ child.is_a?(Include) || child.is_a?(Extend) || child.is_a?(Constant) || child.is_a?(TypeAlias)
638
726
  end
639
727
  unless first
640
728
  # Remove any trailing whitespace due to includes or class attributes