parlour 4.0.1 → 5.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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