parlour 4.0.1 → 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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +208 -20
  4. data/exe/parlour +45 -6
  5. data/lib/parlour.rb +27 -1
  6. data/lib/parlour/conversion/converter.rb +34 -0
  7. data/lib/parlour/conversion/rbi_to_rbs.rb +223 -0
  8. data/lib/parlour/detached_rbs_generator.rb +25 -0
  9. data/lib/parlour/generator.rb +34 -0
  10. data/lib/parlour/options.rb +71 -0
  11. data/lib/parlour/rbi_generator.rb +24 -37
  12. data/lib/parlour/rbi_generator/arbitrary.rb +5 -2
  13. data/lib/parlour/rbi_generator/attribute.rb +14 -5
  14. data/lib/parlour/rbi_generator/class_namespace.rb +8 -3
  15. data/lib/parlour/rbi_generator/constant.rb +17 -6
  16. data/lib/parlour/rbi_generator/enum_class_namespace.rb +8 -3
  17. data/lib/parlour/rbi_generator/extend.rb +5 -2
  18. data/lib/parlour/rbi_generator/include.rb +5 -2
  19. data/lib/parlour/rbi_generator/method.rb +15 -10
  20. data/lib/parlour/rbi_generator/module_namespace.rb +7 -2
  21. data/lib/parlour/rbi_generator/namespace.rb +39 -12
  22. data/lib/parlour/rbi_generator/parameter.rb +11 -5
  23. data/lib/parlour/rbi_generator/rbi_object.rb +19 -78
  24. data/lib/parlour/rbi_generator/struct_class_namespace.rb +9 -2
  25. data/lib/parlour/rbi_generator/struct_prop.rb +12 -9
  26. data/lib/parlour/rbi_generator/type_alias.rb +101 -0
  27. data/lib/parlour/rbs_generator.rb +24 -0
  28. data/lib/parlour/rbs_generator/arbitrary.rb +92 -0
  29. data/lib/parlour/rbs_generator/attribute.rb +82 -0
  30. data/lib/parlour/rbs_generator/block.rb +49 -0
  31. data/lib/parlour/rbs_generator/class_namespace.rb +106 -0
  32. data/lib/parlour/rbs_generator/constant.rb +95 -0
  33. data/lib/parlour/rbs_generator/extend.rb +92 -0
  34. data/lib/parlour/rbs_generator/include.rb +92 -0
  35. data/lib/parlour/rbs_generator/interface_namespace.rb +34 -0
  36. data/lib/parlour/rbs_generator/method.rb +146 -0
  37. data/lib/parlour/rbs_generator/method_signature.rb +104 -0
  38. data/lib/parlour/rbs_generator/module_namespace.rb +35 -0
  39. data/lib/parlour/rbs_generator/namespace.rb +627 -0
  40. data/lib/parlour/rbs_generator/parameter.rb +145 -0
  41. data/lib/parlour/rbs_generator/rbs_object.rb +78 -0
  42. data/lib/parlour/rbs_generator/type_alias.rb +96 -0
  43. data/lib/parlour/type_parser.rb +152 -0
  44. data/lib/parlour/typed_object.rb +87 -0
  45. data/lib/parlour/types.rb +445 -0
  46. data/lib/parlour/version.rb +1 -1
  47. data/parlour.gemspec +1 -1
  48. data/rbi/parlour.rbi +982 -76
  49. metadata +30 -7
  50. data/lib/parlour/rbi_generator/options.rb +0 -74
@@ -1,11 +1,11 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents miscellaneous Ruby code.
5
5
  class Arbitrary < RbiObject
6
6
  sig do
7
7
  params(
8
- generator: RbiGenerator,
8
+ generator: Generator,
9
9
  code: String,
10
10
  block: T.nilable(T.proc.params(x: Arbitrary).void)
11
11
  ).void
@@ -87,6 +87,9 @@ module Parlour
87
87
  def describe
88
88
  "Arbitrary code (#{code})"
89
89
  end
90
+
91
+ sig { override.void }
92
+ def generalize_from_rbi!; end # Nothing to do
90
93
  end
91
94
  end
92
95
  end
@@ -1,14 +1,14 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents an attribute reader, writer or accessor.
5
5
  class Attribute < Method
6
6
  sig do
7
7
  params(
8
- generator: RbiGenerator,
8
+ generator: Generator,
9
9
  name: String,
10
10
  kind: Symbol,
11
- type: String,
11
+ type: Types::TypeLike,
12
12
  class_attribute: T::Boolean,
13
13
  block: T.nilable(T.proc.params(x: Attribute).void)
14
14
  ).void
@@ -20,8 +20,7 @@ module Parlour
20
20
  # @param name [String] The name of this attribute.
21
21
  # @param kind [Symbol] The kind of attribute this is; one of :writer, :reader or
22
22
  # :accessor.
23
- # @param type [String] A Sorbet string of this attribute's type, such as
24
- # +"String"+ or +"T.untyped"+.
23
+ # @param type [String, Types::Type] This attribute's type.
25
24
  # @param class_attribute [Boolean] Whether this attribute belongs to the
26
25
  # singleton class.
27
26
  # @param block A block which the new instance yields itself to.
@@ -32,6 +31,7 @@ module Parlour
32
31
  # attr_accessor and attr_reader should have: sig { returns(X) }
33
32
  # attr_writer :foo should have: sig { params(foo: X).returns(X) }
34
33
 
34
+ @type = type
35
35
  @kind = kind
36
36
  @class_attribute = class_attribute
37
37
  case kind
@@ -55,6 +55,10 @@ module Parlour
55
55
  # Whether this attribute belongs to the singleton class.
56
56
  attr_reader :class_attribute
57
57
 
58
+ sig { returns(Types::TypeLike) }
59
+ # The type of this attribute.
60
+ attr_reader :type
61
+
58
62
  sig { override.params(other: Object).returns(T::Boolean) }
59
63
  # Returns true if this instance is equal to another attribute.
60
64
  #
@@ -69,6 +73,11 @@ module Parlour
69
73
  )
70
74
  end
71
75
 
76
+ sig { override.void }
77
+ def generalize_from_rbi!
78
+ @type = TypeParser.parse_single_type(@type) if String === @type
79
+ end
80
+
72
81
  private
73
82
 
74
83
  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 class definition.
5
5
  class ClassNamespace < 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
  superclass: T.nilable(String),
@@ -47,7 +47,7 @@ module Parlour
47
47
  class_definition = superclass.nil? \
48
48
  ? "class #{name}"
49
49
  : "class #{name} < #{superclass}"
50
-
50
+
51
51
  lines = generate_comments(indent_level, options)
52
52
  lines << options.indented(indent_level, class_definition)
53
53
  lines += [options.indented(indent_level + 1, "abstract!"), ""] if abstract
@@ -116,6 +116,11 @@ module Parlour
116
116
  "#{"abstract, " if abstract}#{children.length} children, " +
117
117
  "#{includes.length} includes, #{extends.length} extends"
118
118
  end
119
+
120
+ sig { override.void }
121
+ def generalize_from_rbi!
122
+ super
123
+ end
119
124
  end
120
125
  end
121
126
  end
@@ -1,13 +1,13 @@
1
1
  # typed: true
2
2
  module Parlour
3
- class RbiGenerator
3
+ class RbiGenerator < Generator
4
4
  # Represents a constant definition.
5
5
  class Constant < RbiObject
6
6
  sig do
7
7
  params(
8
- generator: RbiGenerator,
8
+ generator: Generator,
9
9
  name: String,
10
- value: String,
10
+ value: Types::TypeLike,
11
11
  eigen_constant: T::Boolean,
12
12
  block: T.nilable(T.proc.params(x: Constant).void)
13
13
  ).void
@@ -25,8 +25,8 @@ module Parlour
25
25
  yield_self(&block) if block
26
26
  end
27
27
 
28
- # @return [String] The value of the constant, as a Ruby code string.
29
- sig { returns(String) }
28
+ # @return [String] The value or type of the constant.
29
+ sig { returns(Types::TypeLike) }
30
30
  attr_reader :value
31
31
 
32
32
  # @return [Boolean] Whether this constant is defined on the eigenclass
@@ -56,7 +56,11 @@ module Parlour
56
56
  # @param options [Options] The formatting options to use.
57
57
  # @return [Array<String>] The RBI lines, formatted as specified.
58
58
  def generate_rbi(indent_level, options)
59
- [options.indented(indent_level, "#{name} = #{value}")]
59
+ if String === @value
60
+ [options.indented(indent_level, "#{name} = #{@value}")]
61
+ else
62
+ [options.indented(indent_level, "#{name} = T.let(nil, #{@value.generate_rbi})")]
63
+ end
60
64
  end
61
65
 
62
66
  sig do
@@ -98,6 +102,13 @@ module Parlour
98
102
  def describe
99
103
  "Constant (#{name} = #{value})"
100
104
  end
105
+
106
+ sig { override.void }
107
+ def generalize_from_rbi!
108
+ # There's a good change this is an untyped constant, so rescue
109
+ # ParseError and use untyped
110
+ @value = (TypeParser.parse_single_type(@value) if String === @value) rescue Types::Untyped.new
111
+ end
101
112
  end
102
113
  end
103
114
  end
@@ -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
@@ -107,6 +107,11 @@ module Parlour
107
107
  @enums = other.enums if enums.empty?
108
108
  end
109
109
  end
110
+
111
+ sig { override.void }
112
+ def generalize_from_rbi!
113
+ super
114
+ end
110
115
  end
111
116
  end
112
117
  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>]
@@ -260,7 +271,7 @@ module Parlour
260
271
  params(
261
272
  name: String,
262
273
  parameters: T.nilable(T::Array[Parameter]),
263
- return_type: T.nilable(String),
274
+ return_type: T.nilable(Types::TypeLike),
264
275
  returns: T.nilable(String),
265
276
  abstract: T::Boolean,
266
277
  implementation: T::Boolean,
@@ -320,7 +331,7 @@ module Parlour
320
331
  params(
321
332
  name: String,
322
333
  kind: Symbol,
323
- type: String,
334
+ type: Types::TypeLike,
324
335
  class_attribute: T::Boolean,
325
336
  block: T.nilable(T.proc.params(x: Attribute).void)
326
337
  ).returns(Attribute)
@@ -376,7 +387,7 @@ module Parlour
376
387
  sig do
377
388
  params(
378
389
  name: String,
379
- type: String,
390
+ type: Types::TypeLike,
380
391
  class_attribute: T::Boolean,
381
392
  block: T.nilable(T.proc.params(x: Attribute).void)
382
393
  ).returns(Attribute)
@@ -397,7 +408,7 @@ module Parlour
397
408
  sig do
398
409
  params(
399
410
  name: String,
400
- type: String,
411
+ type: Types::TypeLike,
401
412
  class_attribute: T::Boolean,
402
413
  block: T.nilable(T.proc.params(x: Attribute).void)
403
414
  ).returns(Attribute)
@@ -418,7 +429,7 @@ module Parlour
418
429
  sig do
419
430
  params(
420
431
  name: String,
421
- type: String,
432
+ type: Types::TypeLike,
422
433
  class_attribute: T::Boolean,
423
434
  block: T.nilable(T.proc.params(x: Attribute).void)
424
435
  ).returns(Attribute)
@@ -552,7 +563,7 @@ module Parlour
552
563
  new_constant
553
564
  end
554
565
 
555
- 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) }
556
567
  # Adds a new type alias, in the form of a constant, to this namespace.
557
568
  #
558
569
  # @example Add a +MyType+ type alias, to +Integer+, to the class.
@@ -563,7 +574,15 @@ module Parlour
563
574
  # @param block A block which the new instance yields itself to.
564
575
  # @return [RbiGenerator::Constant]
565
576
  def create_type_alias(name, type:, &block)
566
- 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
567
586
  end
568
587
 
569
588
  sig do
@@ -615,12 +634,17 @@ module Parlour
615
634
  "includes, #{extends.length} extends, #{constants.length} constants"
616
635
  end
617
636
 
637
+ sig { override.void }
638
+ def generalize_from_rbi!
639
+ children.each(&:generalize_from_rbi!)
640
+ end
641
+
618
642
  private
619
643
 
620
644
  sig do
621
645
  overridable.params(
622
646
  indent_level: Integer,
623
- options: Options
647
+ options: Options,
624
648
  ).returns(T::Array[String])
625
649
  end
626
650
  # Generates the RBI lines for the body of this namespace. This consists of
@@ -639,13 +663,16 @@ module Parlour
639
663
  eigen_constants, non_eigen_constants = constants.partition(&:eigen_constant)
640
664
  eigen_constants.sort_by!(&:name) if options.sort_namespaces
641
665
 
642
- if includes.any? || extends.any? || non_eigen_constants.any?
666
+ if includes.any? || extends.any? || aliases.any? || non_eigen_constants.any?
643
667
  result += (options.sort_namespaces ? includes.sort_by(&:name) : includes)
644
668
  .flat_map { |x| x.generate_rbi(indent_level, options) }
645
669
  .reject { |x| x.strip == '' }
646
670
  result += (options.sort_namespaces ? extends.sort_by(&:name) : extends)
647
671
  .flat_map { |x| x.generate_rbi(indent_level, options) }
648
672
  .reject { |x| x.strip == '' }
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 == '' }
649
676
  result += (options.sort_namespaces ? non_eigen_constants.sort_by(&:name) : non_eigen_constants)
650
677
  .flat_map { |x| x.generate_rbi(indent_level, options) }
651
678
  .reject { |x| x.strip == '' }
@@ -695,7 +722,7 @@ module Parlour
695
722
 
696
723
  first, *rest = remaining_children.reject do |child|
697
724
  # We already processed these kinds of children
698
- 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)
699
726
  end
700
727
  unless first
701
728
  # Remove any trailing whitespace due to includes or class attributes