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
@@ -0,0 +1,82 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents an attribute reader, writer or accessor.
5
+ class Attribute < RbsGenerator::Method
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ generator: Generator,
11
+ name: String,
12
+ kind: Symbol,
13
+ type: Types::TypeLike,
14
+ block: T.nilable(T.proc.params(x: Attribute).void)
15
+ ).void
16
+ end
17
+ # Creates a new attribute.
18
+ # @note You should use {Namespace#create_attribute} rather than this directly.
19
+ #
20
+ # @param generator [RbsGenerator] The current RbsGenerator.
21
+ # @param name [String] The name of this attribute.
22
+ # @param kind [Symbol] The kind of attribute this is; one of :writer, :reader or
23
+ # :accessor.
24
+ # @param type [String, Types::Type] This attribute's type.
25
+ # @param block A block which the new instance yields itself to.
26
+ # @return [void]
27
+ def initialize(generator, name, kind, type, &block)
28
+ @type = type
29
+ @kind = kind
30
+ case kind
31
+ when :accessor, :reader
32
+ super(generator, name, [MethodSignature.new([], type)], &block)
33
+ when :writer
34
+ super(generator, name, [MethodSignature.new([
35
+ Parameter.new(name, type: type)
36
+ ], type)], &block)
37
+ else
38
+ raise 'unknown kind'
39
+ end
40
+ end
41
+
42
+ sig { returns(Symbol) }
43
+ # The kind of attribute this is; one of +:writer+, +:reader+, or +:accessor+.
44
+ # @return [Symbol]
45
+ attr_reader :kind
46
+
47
+ sig { returns(Types::TypeLike) }
48
+ # The type of this attribute.
49
+ attr_reader :type
50
+
51
+ sig do
52
+ override.params(
53
+ indent_level: Integer,
54
+ options: Options
55
+ ).returns(T::Array[String])
56
+ end
57
+ # Generates the RBS lines for this arbstrary code.
58
+ #
59
+ # @param indent_level [Integer] The indentation level to generate the lines at.
60
+ # @param options [Options] The formatting options to use.
61
+ # @return [Array<String>] The RBS lines, formatted as specified.
62
+ def generate_rbs(indent_level, options)
63
+ [options.indented(
64
+ indent_level,
65
+ "attr_#{kind} #{name}: #{String === @type ? @type : @type.generate_rbs}"
66
+ )]
67
+ end
68
+
69
+ sig { override.params(other: Object).returns(T::Boolean) }
70
+ # Returns true if this instance is equal to another attribute.
71
+ #
72
+ # @param other [Object] The other instance. If this is not a {Attribute}
73
+ # (or a subclass of it), this will always return false.
74
+ # @return [Boolean]
75
+ def ==(other)
76
+ T.must(
77
+ super(other) && Attribute === other && kind == other.kind
78
+ )
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a block in a method signature.
5
+ # (This is not an RbsObject because it doesn't generate a full line.)
6
+ class Block
7
+ extend T::Sig
8
+
9
+ sig { params(type: Types::Proc, required: T::Boolean).void }
10
+ # Creates a new block for a method signature.
11
+ #
12
+ # @param type [Types::Proc] The type of this block.
13
+ # @param required [T::Boolean] Whether this block is required.
14
+ def initialize(type, required)
15
+ @type = type
16
+ @required = required
17
+ end
18
+
19
+ sig { overridable.params(other: Object).returns(T::Boolean).checked(:never) }
20
+ # Returns true if this instance is equal to another method signature.
21
+ #
22
+ # @param other [Object] The other instance. If this is not a {MethodSignature} (or a
23
+ # subclass of it), this will always return false.
24
+ # @return [Boolean]
25
+ def ==(other)
26
+ Block === other && type == other.type && required == other.required
27
+ end
28
+
29
+ sig { returns(Types::Proc) }
30
+ # The type of this block.
31
+ # @return [Types::Proc]
32
+ attr_reader :type
33
+
34
+ sig { returns(T::Boolean) }
35
+ # Whether this block is required.
36
+ # @return [Boolean]
37
+ attr_reader :required
38
+
39
+ sig { params(options: Options).returns(T::Array[String]) }
40
+ # Generates the RBS string for this signature.
41
+ #
42
+ # @param options [Options] The formatting options to use.
43
+ # @return [Array<String>] The RBS string, formatted as specified.
44
+ def generate_rbs(options)
45
+ ["#{required ? '' : '?'}{ #{type.generate_rbs} }"]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,106 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a class definition.
5
+ class ClassNamespace < Namespace
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ generator: Generator,
11
+ name: String,
12
+ superclass: T.nilable(Types::TypeLike),
13
+ block: T.nilable(T.proc.params(x: ClassNamespace).void)
14
+ ).void
15
+ end
16
+ # Creates a new class definition.
17
+ # @note You should use {Namespace#create_class} rather than this directly.
18
+ #
19
+ # @param generator [RbsGenerator] The current RbsGenerator.
20
+ # @param name [String] The name of this class.
21
+ # @param final [Boolean] Whether this namespace is final.
22
+ # @param superclass [String, nil] The superclass of this class, or nil if it doesn't
23
+ # have one.
24
+ # @param abstract [Boolean] A boolean indicating whether this class is abstract.
25
+ # @param block A block which the new instance yields itself to.
26
+ # @return [void]
27
+ def initialize(generator, name, superclass, &block)
28
+ super(generator, name, &block)
29
+ @superclass = superclass
30
+ end
31
+
32
+ sig do
33
+ override.params(
34
+ indent_level: Integer,
35
+ options: Options
36
+ ).returns(T::Array[String])
37
+ end
38
+ def generate_rbs(indent_level, options)
39
+ class_definition = @superclass.nil? \
40
+ ? "class #{name}"
41
+ : "class #{name} < #{String === @superclass ? @superclass : @superclass.generate_rbs}"
42
+
43
+ lines = generate_comments(indent_level, options)
44
+ lines << options.indented(indent_level, class_definition)
45
+ lines += generate_body(indent_level + 1, options)
46
+ lines << options.indented(indent_level, "end")
47
+ end
48
+
49
+ sig { returns(T.nilable(Types::TypeLike)) }
50
+ # The superclass of this class, or nil if it doesn't have one.
51
+ # @return [Types::TypeLike, nil]
52
+ attr_reader :superclass
53
+
54
+ sig do
55
+ override.params(
56
+ others: T::Array[RbsGenerator::RbsObject]
57
+ ).returns(T::Boolean)
58
+ end
59
+ # Given an array of {Namespace} instances, returns true if they may
60
+ # be merged into this instance using {merge_into_self}. For instances to
61
+ # be mergeable, they must either all be abstract or all not be abstract,
62
+ # and they must define the same superclass (or none at all).
63
+ #
64
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {Namespace} instances.
65
+ # @return [Boolean] Whether this instance may be merged with them.
66
+ def mergeable?(others)
67
+ others = T.cast(others, T::Array[Namespace]) rescue (return false)
68
+ all = others + [self]
69
+
70
+ all_classes = T.cast(all.select { |x| ClassNamespace === x }, T::Array[ClassNamespace])
71
+
72
+ all_classes.map(&:superclass).compact.uniq.length <= 1
73
+ end
74
+
75
+ sig do
76
+ override.params(
77
+ others: T::Array[RbsGenerator::RbsObject]
78
+ ).void
79
+ end
80
+ # Given an array of {ClassNamespace} instances, merges them into this one.
81
+ # You MUST ensure that {mergeable?} is true for those instances.
82
+ #
83
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {ClassNamespace} instances.
84
+ # @return [void]
85
+ def merge_into_self(others)
86
+ super
87
+
88
+ others.each do |other|
89
+ next unless ClassNamespace === other
90
+ other = T.cast(other, ClassNamespace)
91
+
92
+ @superclass = other.superclass unless superclass
93
+ end
94
+ end
95
+
96
+ sig { override.returns(String) }
97
+ # Returns a human-readable brief string description of this class.
98
+ # @return [String]
99
+ def describe
100
+ "Class #{name} - #{"superclass #{superclass}, " if superclass}" +
101
+ "#{children.length} children, " +
102
+ "#{includes.length} includes, #{extends.length} extends"
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,95 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a constant definition.
5
+ class Constant < RbsObject
6
+ sig do
7
+ params(
8
+ generator: Generator,
9
+ name: String,
10
+ type: Types::TypeLike,
11
+ block: T.nilable(T.proc.params(x: Constant).void)
12
+ ).void
13
+ end
14
+ # Creates a new constant definition.
15
+ #
16
+ # @param name [String] The name of the constant.
17
+ # @param value [String] The value of the constant, as a Ruby code string.
18
+ # eigenclass of the current namespace.
19
+ def initialize(generator, name, type:, &block)
20
+ super(generator, name)
21
+ @type = type
22
+ yield_self(&block) if block
23
+ end
24
+
25
+ # @return [Types::TypeLike] The type of the constant.
26
+ sig { returns(Types::TypeLike) }
27
+ attr_reader :type
28
+
29
+ sig { params(other: Object).returns(T::Boolean) }
30
+ # Returns true if this instance is equal to another extend.
31
+ #
32
+ # @param other [Object] The other instance. If this is not a {Extend} (or a
33
+ # subclass of it), this will always return false.
34
+ # @return [Boolean]
35
+ def ==(other)
36
+ Constant === other && name == other.name && type == other.type
37
+ end
38
+
39
+ sig do
40
+ override.params(
41
+ indent_level: Integer,
42
+ options: Options
43
+ ).returns(T::Array[String])
44
+ end
45
+ # Generates the RBS lines for this constant.
46
+ #
47
+ # @param indent_level [Integer] The indentation level to generate the lines at.
48
+ # @param options [Options] The formatting options to use.
49
+ # @return [Array<String>] The RBS lines, formatted as specified.
50
+ def generate_rbs(indent_level, options)
51
+ [options.indented(indent_level, "#{name}: #{String === @type ? @type : @type.generate_rbs}")]
52
+ end
53
+
54
+ sig do
55
+ override.params(
56
+ others: T::Array[RbsGenerator::RbsObject]
57
+ ).returns(T::Boolean)
58
+ end
59
+ # Given an array of {Constant} instances, returns true if they may be
60
+ # merged into this instance using {merge_into_self}. This is always false.
61
+ #
62
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
63
+ # {Constant} instances.
64
+ # @return [Boolean] Whether this instance may be merged with them.
65
+ def mergeable?(others)
66
+ others.all? { |other| self == other }
67
+ end
68
+
69
+ sig do
70
+ override.params(
71
+ others: T::Array[RbsGenerator::RbsObject]
72
+ ).void
73
+ end
74
+ # Given an array of {Constant} instances, merges them into this one.
75
+ # This particular implementation will simply do nothing, as instances
76
+ # are only mergeable if they are indentical.
77
+ # You MUST ensure that {mergeable?} is true for those instances.
78
+ #
79
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
80
+ # {Extend} instances.
81
+ # @return [void]
82
+ def merge_into_self(others)
83
+ # We don't need to change anything! We only merge identical constants
84
+ end
85
+
86
+ sig { override.returns(String) }
87
+ # Returns a human-readable brief string description of this code.
88
+ #
89
+ # @return [String]
90
+ def describe
91
+ "Constant (#{name} = #{type})"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,92 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents an +extend+ call.
5
+ class Extend < RbsObject
6
+ sig do
7
+ params(
8
+ generator: Generator,
9
+ type: Types::TypeLike,
10
+ block: T.nilable(T.proc.params(x: Extend).void)
11
+ ).void
12
+ end
13
+ # Creates a new +extend+ call.
14
+ #
15
+ # @param type [Types::TypeLike] The type to extend.
16
+ def initialize(generator, type:, &block)
17
+ super(generator, '')
18
+ @type = type
19
+ yield_self(&block) if block
20
+ end
21
+
22
+ sig { params(other: Object).returns(T::Boolean) }
23
+ # Returns true if this instance is equal to another extend.
24
+ #
25
+ # @param other [Object] The other instance. If this is not a {Extend} (or a
26
+ # subclass of it), this will always return false.
27
+ # @return [Boolean]
28
+ def ==(other)
29
+ Extend === other && type == other.type
30
+ end
31
+
32
+ sig { returns(Types::TypeLike) }
33
+ # @return [Types::TypeLike] The type to extend.
34
+ attr_reader :type
35
+
36
+ sig do
37
+ override.params(
38
+ indent_level: Integer,
39
+ options: Options
40
+ ).returns(T::Array[String])
41
+ end
42
+ # Generates the RBS lines for this extend.
43
+ #
44
+ # @param indent_level [Integer] The indentation level to generate the lines at.
45
+ # @param options [Options] The formatting options to use.
46
+ # @return [Array<String>] The RBS lines, formatted as specified.
47
+ def generate_rbs(indent_level, options)
48
+ [options.indented(indent_level, "extend #{String === @type ? @type : @type.generate_rbs}")]
49
+ end
50
+
51
+ sig do
52
+ override.params(
53
+ others: T::Array[RbsGenerator::RbsObject]
54
+ ).returns(T::Boolean)
55
+ end
56
+ # Given an array of {Extend} instances, returns true if they may be
57
+ # merged into this instance using {merge_into_self}. This is always false.
58
+ #
59
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
60
+ # {Extend} instances.
61
+ # @return [Boolean] Whether this instance may be merged with them.
62
+ def mergeable?(others)
63
+ others.all? { |other| self == other }
64
+ end
65
+
66
+ sig do
67
+ override.params(
68
+ others: T::Array[RbsGenerator::RbsObject]
69
+ ).void
70
+ end
71
+ # Given an array of {Extend} instances, merges them into this one.
72
+ # This particular implementation will simply do nothing, as instances
73
+ # are only mergeable if they are indentical.
74
+ # You MUST ensure that {mergeable?} is true for those instances.
75
+ #
76
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
77
+ # {Extend} instances.
78
+ # @return [void]
79
+ def merge_into_self(others)
80
+ # We don't need to change anything! We only merge identical extends
81
+ end
82
+
83
+ sig { override.returns(String) }
84
+ # Returns a human-readable brief string description of this code.
85
+ #
86
+ # @return [String]
87
+ def describe
88
+ "Extend (#{@type})"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,92 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents an +include+ call.
5
+ class Include < RbsObject
6
+ sig do
7
+ params(
8
+ generator: Generator,
9
+ type: Types::TypeLike,
10
+ block: T.nilable(T.proc.params(x: Include).void)
11
+ ).void
12
+ end
13
+ # Creates a new +include+ call.
14
+ #
15
+ # @param type [Types::TypeLike] The type to include.
16
+ def initialize(generator, type:, &block)
17
+ super(generator, '')
18
+ @type = type
19
+ yield_self(&block) if block
20
+ end
21
+
22
+ sig { params(other: Object).returns(T::Boolean) }
23
+ # Returns true if this instance is equal to another include.
24
+ #
25
+ # @param other [Object] The other instance. If this is not a {Include} (or a
26
+ # subclass of it), this will always return false.
27
+ # @return [Boolean]
28
+ def ==(other)
29
+ Include === other && type == other.type
30
+ end
31
+
32
+ sig { returns(Types::TypeLike) }
33
+ # @return [Types::TypeLike] The type to include.
34
+ attr_reader :type
35
+
36
+ sig do
37
+ override.params(
38
+ indent_level: Integer,
39
+ options: Options
40
+ ).returns(T::Array[String])
41
+ end
42
+ # Generates the RBS lines for this include.
43
+ #
44
+ # @param indent_level [Integer] The indentation level to generate the lines at.
45
+ # @param options [Options] The formatting options to use.
46
+ # @return [Array<String>] The RBS lines, formatted as specified.
47
+ def generate_rbs(indent_level, options)
48
+ [options.indented(indent_level, "include #{String === @type ? @type : @type.generate_rbs}")]
49
+ end
50
+
51
+ sig do
52
+ override.params(
53
+ others: T::Array[RbsGenerator::RbsObject]
54
+ ).returns(T::Boolean)
55
+ end
56
+ # Given an array of {Include} instances, returns true if they may be
57
+ # merged into this instance using {merge_into_self}. This is always false.
58
+ #
59
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
60
+ # {Include} instances.
61
+ # @return [Boolean] Whether this instance may be merged with them.
62
+ def mergeable?(others)
63
+ others.all? { |other| self == other }
64
+ end
65
+
66
+ sig do
67
+ override.params(
68
+ others: T::Array[RbsGenerator::RbsObject]
69
+ ).void
70
+ end
71
+ # Given an array of {Include} instances, merges them into this one.
72
+ # This particular implementation will simply do nothing, as instances
73
+ # are only mergeable if they are indentical.
74
+ # You MUST ensure that {mergeable?} is true for those instances.
75
+ #
76
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
77
+ # {Include} instances.
78
+ # @return [void]
79
+ def merge_into_self(others)
80
+ # We don't need to change anything! We only merge identical includes
81
+ end
82
+
83
+ sig { override.returns(String) }
84
+ # Returns a human-readable brief string description of this code.
85
+ #
86
+ # @return [String]
87
+ def describe
88
+ "Include (#{@type})"
89
+ end
90
+ end
91
+ end
92
+ end