parlour 4.0.0 → 5.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
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 +0 -0
  6. data/.rspec +0 -0
  7. data/.travis.yml +0 -0
  8. data/CHANGELOG.md +52 -0
  9. data/CODE_OF_CONDUCT.md +0 -0
  10. data/Gemfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +208 -20
  13. data/Rakefile +0 -0
  14. data/exe/parlour +45 -6
  15. data/lib/parlour.rb +27 -1
  16. data/lib/parlour/conflict_resolver.rb +31 -9
  17. data/lib/parlour/conversion/converter.rb +34 -0
  18. data/lib/parlour/conversion/rbi_to_rbs.rb +229 -0
  19. data/lib/parlour/debugging.rb +0 -0
  20. data/lib/parlour/detached_rbi_generator.rb +0 -0
  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 +0 -0
  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 +17 -6
  32. data/lib/parlour/rbi_generator/enum_class_namespace.rb +8 -3
  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 +40 -13
  38. data/lib/parlour/rbi_generator/parameter.rb +11 -5
  39. data/lib/parlour/rbi_generator/rbi_object.rb +19 -78
  40. data/lib/parlour/rbi_generator/struct_class_namespace.rb +9 -2
  41. data/lib/parlour/rbi_generator/struct_prop.rb +12 -9
  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 +146 -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 +0 -0
  60. data/lib/parlour/type_parser.rb +174 -5
  61. data/lib/parlour/typed_object.rb +87 -0
  62. data/lib/parlour/types.rb +539 -0
  63. data/lib/parlour/version.rb +1 -1
  64. data/parlour.gemspec +1 -1
  65. data/plugin_examples/foobar_plugin.rb +0 -0
  66. data/rbi/parlour.rbi +1404 -441
  67. metadata +33 -10
  68. data/lib/parlour/rbi_generator/options.rb +0 -74
@@ -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
@@ -0,0 +1,34 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents an interface definition.
5
+ class InterfaceNamespace < Namespace
6
+ extend T::Sig
7
+
8
+ sig do
9
+ override.params(
10
+ indent_level: Integer,
11
+ options: Options
12
+ ).returns(T::Array[String])
13
+ end
14
+ # Generates the RBS lines for this interface.
15
+ #
16
+ # @param indent_level [Integer] The indentation level to generate the lines at.
17
+ # @param options [Options] The formatting options to use.
18
+ # @return [Array<String>] The RBS lines, formatted as specified.
19
+ def generate_rbs(indent_level, options)
20
+ lines = generate_comments(indent_level, options)
21
+ lines << options.indented(indent_level, "interface #{name}")
22
+ lines += generate_body(indent_level + 1, options)
23
+ lines << options.indented(indent_level, "end")
24
+ end
25
+
26
+ sig { override.returns(String) }
27
+ # Returns a human-readable brief string description of this interface.
28
+ # @return [String]
29
+ def describe
30
+ "Interface #{name} - #{children.length}"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,146 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a method definition.
5
+ class Method < RbsObject
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ generator: Generator,
11
+ name: String,
12
+ signatures: T::Array[MethodSignature],
13
+ class_method: T::Boolean,
14
+ block: T.nilable(T.proc.params(x: Method).void)
15
+ ).void
16
+ end
17
+ # Creates a new method definition.
18
+ # @note You should use {Namespace#create_method} rather than this directly.
19
+ #
20
+ # @param generator [RbsGenerator] The current RbsGenerator.
21
+ # @param name [String] The name of this method. You should not specify +self.+ in
22
+ # this - use the +class_method+ parameter instead.
23
+ # @param signatures [Array<MethodSignature>] The signatures for each
24
+ # overload of this method.
25
+ # @param class_method [Boolean] Whether this method is a class method; that is, it
26
+ # it is defined using +self.+.
27
+ # @param block A block which the new instance yields itself to.
28
+ # @return [void]
29
+ def initialize(generator, name, signatures, class_method: false, &block)
30
+ super(generator, name)
31
+ @signatures = signatures
32
+ @class_method = class_method
33
+ yield_self(&block) if block
34
+ end
35
+
36
+ sig { overridable.params(other: Object).returns(T::Boolean).checked(:never) }
37
+ # Returns true if this instance is equal to another method.
38
+ #
39
+ # @param other [Object] The other instance. If this is not a {Method} (or a
40
+ # subclass of it), this will always return false.
41
+ # @return [Boolean]
42
+ def ==(other)
43
+ Method === other &&
44
+ name == other.name &&
45
+ signatures == other.signatures &&
46
+ class_method == other.class_method
47
+ end
48
+
49
+ sig { returns(T::Array[MethodSignature]) }
50
+ # The signatures for each overload of this method.
51
+ # @return [Array<MethodSignature>]
52
+ attr_reader :signatures
53
+
54
+ sig { returns(T::Boolean) }
55
+ # Whether this method is a class method; that is, it it is defined using
56
+ # +self.+.
57
+ # @return [Boolean]
58
+ attr_reader :class_method
59
+
60
+ sig do
61
+ override.params(
62
+ indent_level: Integer,
63
+ options: Options
64
+ ).returns(T::Array[String])
65
+ end
66
+ # Generates the RBS lines for this method.
67
+ #
68
+ # @param indent_level [Integer] The indentation level to generate the lines at.
69
+ # @param options [Options] The formatting options to use.
70
+ # @return [Array<String>] The RBS lines, formatted as specified.
71
+ def generate_rbs(indent_level, options)
72
+ definition = "def #{class_method ? 'self.' : ''}#{name}: "
73
+ lines = generate_comments(indent_level, options)
74
+
75
+ # Handle each signature
76
+ signatures.each.with_index do |sig, i|
77
+ this_sig_lines = []
78
+
79
+ # Start off the first line of the signature, either with the definition
80
+ # for the first signature, or a pipe for the rest
81
+ if i == 0
82
+ this_sig_lines << options.indented(indent_level, definition)
83
+ else
84
+ this_sig_lines << options.indented(indent_level, "#{' ' * (definition.length - 2)}| ")
85
+ end
86
+
87
+ # Generate the signature's lines, we'll append them afterwards
88
+ partial_sig_lines = sig.generate_rbs(options)
89
+
90
+ # Merge the first signature line, and indent & concat the rest
91
+ first_line, *rest_lines = *partial_sig_lines
92
+ this_sig_lines[0] += first_line
93
+ rest_lines&.each do |line|
94
+ this_sig_lines << ' ' * definition.length + options.indented(indent_level, line)
95
+ end
96
+
97
+ # Add on all this signature's lines to the complete lines
98
+ lines += this_sig_lines
99
+ end
100
+
101
+ lines
102
+ end
103
+
104
+ sig do
105
+ override.params(
106
+ others: T::Array[RbsGenerator::RbsObject]
107
+ ).returns(T::Boolean)
108
+ end
109
+ # Given an array of {Method} instances, returns true if they may be merged
110
+ # into this instance using {merge_into_self}. For instances to be
111
+ # mergeable, their signatures and definitions must be identical.
112
+ #
113
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {Method} instances.
114
+ # @return [Boolean] Whether this instance may be merged with them.
115
+ def mergeable?(others)
116
+ others.all? { |other| self == other }
117
+ end
118
+
119
+ sig do
120
+ override.params(
121
+ others: T::Array[RbsGenerator::RbsObject]
122
+ ).void
123
+ end
124
+ # Given an array of {Method} instances, merges them into this one.
125
+ # This particular implementation in fact does nothing, because {Method}
126
+ # instances are only mergeable if they are identical, so nothing needs
127
+ # to be changed.
128
+ # You MUST ensure that {mergeable?} is true for those instances.
129
+ #
130
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {Method} instances.
131
+ # @return [void]
132
+ def merge_into_self(others)
133
+ # TODO: merge signatures of different definitions
134
+ end
135
+
136
+ sig { override.returns(String) }
137
+ # Returns a human-readable brief string description of this method.
138
+ #
139
+ # @return [String]
140
+ def describe
141
+ # TODO: more info
142
+ "Method #{name} - #{signatures.length} signatures"
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,104 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents one signature in a method definition.
5
+ # (This is not an RbsObject because it doesn't generate a full line.)
6
+ class MethodSignature
7
+ extend T::Sig
8
+
9
+ sig do
10
+ params(
11
+ parameters: T::Array[Parameter],
12
+ return_type: T.nilable(Types::TypeLike),
13
+ block: T.nilable(Block),
14
+ type_parameters: T.nilable(T::Array[Symbol])
15
+ ).void
16
+ end
17
+ # Creates a new method signature.
18
+ #
19
+ # @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
20
+ # method's parameters.
21
+ # @param return_type [Types::TypeLike, nil] What this method returns. Passing nil denotes a void return.
22
+ # @param block [Types::TypeLike, nil] The block this method accepts. Passing nil denotes none.
23
+ # @param type_parameters [Array<Symbol>, nil] This method's type parameters.
24
+ # @return [void]
25
+ def initialize(parameters, return_type = nil, block: nil, type_parameters: nil)
26
+ @parameters = parameters
27
+ @return_type = return_type
28
+ @block = block
29
+ @type_parameters = type_parameters || []
30
+ end
31
+
32
+ sig { overridable.params(other: Object).returns(T::Boolean).checked(:never) }
33
+ # Returns true if this instance is equal to another method signature.
34
+ #
35
+ # @param other [Object] The other instance. If this is not a {MethodSignature} (or a
36
+ # subclass of it), this will always return false.
37
+ # @return [Boolean]
38
+ def ==(other)
39
+ MethodSignature === other &&
40
+ parameters == other.parameters &&
41
+ return_type == other.return_type &&
42
+ block == other.block &&
43
+ type_parameters == other.type_parameters
44
+ end
45
+
46
+ sig { returns(T::Array[Parameter]) }
47
+ # An array of {Parameter} instances representing this method's parameters.
48
+ # @return [Array<Parameter>]
49
+ attr_reader :parameters
50
+
51
+ sig { returns(T.nilable(Types::TypeLike)) }
52
+ # What this method returns. Passing nil denotes a void return.
53
+ # @return [Types::TypeLike, nil]
54
+ attr_reader :return_type
55
+
56
+ sig { returns(T.nilable(Block)) }
57
+ # The block this method accepts.
58
+ # @return [Block, nil]
59
+ attr_reader :block
60
+
61
+ sig { returns(T::Array[Symbol]) }
62
+ # This method's type parameters.
63
+ # @return [Array<Symbol>]
64
+ attr_reader :type_parameters
65
+
66
+ sig { params(options: Options).returns(T::Array[String]) }
67
+ # Generates the RBS string for this signature.
68
+ #
69
+ # @param options [Options] The formatting options to use.
70
+ # @return [Array<String>] The RBS string, formatted as specified.
71
+ def generate_rbs(options)
72
+ block_type = @block&.generate_rbs(options)
73
+
74
+ rbs_params = parameters.reject { |x| x.kind == :block }.map(&:to_rbs_param)
75
+ rbs_return_type = String === @return_type ? @return_type : @return_type&.generate_rbs
76
+
77
+ generated_params = parameters.length >= options.break_params \
78
+ ? ["("] +
79
+ (
80
+ parameters.empty? ? [] : rbs_params.map.with_index do |x, i|
81
+ options.indented(
82
+ 1,
83
+ # Don't include the comma on the last parameter.
84
+ parameters.length == i + 1 ? "#{x}" : "#{x},"
85
+ )
86
+ end
87
+ ) +
88
+ [")"]
89
+
90
+ : ["(#{rbs_params.join(', ')})"]
91
+
92
+ generated_params[0] = "#{
93
+ type_parameters.any? ? "[#{type_parameters.join(', ')}] " : ''
94
+ }" + T.must(generated_params[0])
95
+
96
+ generated_params[-1] = T.must(generated_params[-1]) + "#{
97
+ (block_type && block_type.first != 'untyped') ? " #{block_type.first}" : '' # TODO: doesn't support multi-line block types
98
+ } -> #{rbs_return_type || 'void'}"
99
+
100
+ generated_params
101
+ end
102
+ end
103
+ end
104
+ end