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
@@ -0,0 +1,87 @@
1
+ # typed: true
2
+ module Parlour
3
+ # A generic superclass of all objects which form part of type definitions in,
4
+ # specific formats, such as RbiObject and RbsObject.
5
+ class TypedObject
6
+ extend T::Sig
7
+ extend T::Helpers
8
+ abstract!
9
+
10
+ sig { params(name: String).void }
11
+ # Create a new typed object.
12
+ def initialize(name)
13
+ @name = name
14
+ @comments = []
15
+ end
16
+
17
+ sig { returns(T.nilable(Plugin)) }
18
+ # The {Plugin} which was controlling the {generator} when this object was
19
+ # created.
20
+ # @return [Plugin, nil]
21
+ attr_reader :generated_by
22
+
23
+ sig { returns(String) }
24
+ # The name of this object.
25
+ # @return [String]
26
+ attr_reader :name
27
+
28
+ sig { returns(T::Array[String]) }
29
+ # An array of comments which will be placed above the object in the RBS
30
+ # file.
31
+ # @return [Array<String>]
32
+ attr_reader :comments
33
+
34
+ sig { params(comment: T.any(String, T::Array[String])).void }
35
+ # Adds one or more comments to this RBS object. Comments always go above
36
+ # the definition for this object, not in the definition's body.
37
+ #
38
+ # @example Creating a module with a comment.
39
+ # namespace.create_module('M') do |m|
40
+ # m.add_comment('This is a module')
41
+ # end
42
+ #
43
+ # @example Creating a class with a multi-line comment.
44
+ # namespace.create_class('C') do |c|
45
+ # c.add_comment(['This is a multi-line comment!', 'It can be as long as you want!'])
46
+ # end
47
+ #
48
+ # @param comment [String, Array<String>] The new comment(s).
49
+ # @return [void]
50
+ def add_comment(comment)
51
+ if comment.is_a?(String)
52
+ comments << comment
53
+ elsif comment.is_a?(Array)
54
+ comments.concat(comment)
55
+ end
56
+ end
57
+
58
+ alias_method :add_comments, :add_comment
59
+
60
+ sig { abstract.returns(String) }
61
+ # Returns a human-readable brief string description of this object. This
62
+ # is displayed during manual conflict resolution with the +parlour+ CLI.
63
+ #
64
+ # @abstract
65
+ # @return [String]
66
+ def describe; end
67
+
68
+ protected
69
+
70
+ sig do
71
+ params(
72
+ indent_level: Integer,
73
+ options: Options
74
+ ).returns(T::Array[String])
75
+ end
76
+ # Generates the RBS lines for this object's comments.
77
+ #
78
+ # @param indent_level [Integer] The indentation level to generate the lines at.
79
+ # @param options [Options] The formatting options to use.
80
+ # @return [Array<String>] The RBS lines for each comment, formatted as specified.
81
+ def generate_comments(indent_level, options)
82
+ comments.any? \
83
+ ? comments.map { |c| options.indented(indent_level, "# #{c}") }
84
+ : []
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,445 @@
1
+ # typed: true
2
+
3
+ module Parlour
4
+ # Contains structured types which can be used in type signatures.
5
+ module Types
6
+ TypeLike = T.type_alias { T.any(String, Type) }
7
+
8
+ # The top-level, abstract class for a generalised type. All of the other
9
+ # types inherit from this. Do not instantiate.
10
+ class Type
11
+ extend T::Sig
12
+ extend T::Helpers
13
+
14
+ abstract!
15
+
16
+ sig { abstract.returns(String) }
17
+ def generate_rbi; end
18
+
19
+ sig { abstract.returns(String) }
20
+ def generate_rbs; end
21
+
22
+ sig { params(type_like: TypeLike).returns(Type) }
23
+ def self.to_type(type_like)
24
+ if type_like.is_a?(String)
25
+ Raw.new(type_like)
26
+ else
27
+ type_like
28
+ end
29
+ end
30
+
31
+ sig { params(type_like: TypeLike).returns(Type) }
32
+ def to_type(type_like)
33
+ Type.to_type(type_like)
34
+ end
35
+ end
36
+
37
+ # A basic type as a raw string.
38
+ class Raw < Type
39
+ sig { params(str: String).void }
40
+ def initialize(str)
41
+ @str = str
42
+ end
43
+
44
+ sig { returns(String) }
45
+ attr_reader :str
46
+
47
+ sig { params(other: Object).returns(T::Boolean) }
48
+ def ==(other)
49
+ Raw === other && str == other.str
50
+ end
51
+
52
+ sig { override.returns(String) }
53
+ def generate_rbi
54
+ str
55
+ end
56
+
57
+ sig { override.returns(String) }
58
+ def generate_rbs
59
+ str
60
+ end
61
+ end
62
+
63
+ # A type which can be either the wrapped type, or nil.
64
+ class Nilable < Type
65
+ sig { params(type: TypeLike).void }
66
+ def initialize(type)
67
+ @type = to_type(type)
68
+ end
69
+
70
+ sig { params(other: Object).returns(T::Boolean) }
71
+ def ==(other)
72
+ Nilable === other && type == other.type
73
+ end
74
+
75
+ sig { returns(Type) }
76
+ attr_reader :type
77
+
78
+ sig { override.returns(String) }
79
+ def generate_rbi
80
+ "T.nilable(#{type.generate_rbi})"
81
+ end
82
+
83
+ sig { override.returns(String) }
84
+ def generate_rbs
85
+ "#{type.generate_rbs}?"
86
+ end
87
+ end
88
+
89
+ # A type which is (at least) one of the wrapped types.
90
+ class Union < Type
91
+ sig { params(types: T::Array[TypeLike]).void }
92
+ def initialize(types)
93
+ @types = types.map(&method(:to_type))
94
+ end
95
+
96
+ sig { params(other: Object).returns(T::Boolean) }
97
+ def ==(other)
98
+ Union === other && types == other.types
99
+ end
100
+
101
+ sig { returns(T::Array[Type]) }
102
+ attr_reader :types
103
+
104
+ sig { override.returns(String) }
105
+ def generate_rbi
106
+ "T.any(#{types.map(&:generate_rbi).join(', ')})"
107
+ end
108
+
109
+ sig { override.returns(String) }
110
+ def generate_rbs
111
+ "(#{types.map(&:generate_rbs).join(' | ')})"
112
+ end
113
+ end
114
+
115
+ # A type which matches all of the wrapped types.
116
+ class Intersection < Type
117
+ sig { params(types: T::Array[TypeLike]).void }
118
+ def initialize(types)
119
+ @types = types.map(&method(:to_type))
120
+ end
121
+
122
+ sig { params(other: Object).returns(T::Boolean) }
123
+ def ==(other)
124
+ Intersection === other && types == other.types
125
+ end
126
+
127
+ sig { returns(T::Array[Type]) }
128
+ attr_reader :types
129
+
130
+ sig { override.returns(String) }
131
+ def generate_rbi
132
+ "T.all(#{types.map(&:generate_rbi).join(', ')})"
133
+ end
134
+
135
+ sig { override.returns(String) }
136
+ def generate_rbs
137
+ "(#{types.map(&:generate_rbs).join(' & ')})"
138
+ end
139
+ end
140
+
141
+ # A fixed-length array of items, each with a known type.
142
+ class Tuple < Type
143
+ sig { params(types: T::Array[TypeLike]).void }
144
+ def initialize(types)
145
+ @types = types.map(&method(:to_type))
146
+ end
147
+
148
+ sig { params(other: Object).returns(T::Boolean) }
149
+ def ==(other)
150
+ Tuple === other && types == other.types
151
+ end
152
+
153
+ sig { returns(T::Array[Type]) }
154
+ attr_reader :types
155
+
156
+ sig { override.returns(String) }
157
+ def generate_rbi
158
+ "[#{types.map(&:generate_rbi).join(', ')}]"
159
+ end
160
+
161
+ sig { override.returns(String) }
162
+ def generate_rbs
163
+ "[#{types.map(&:generate_rbs).join(', ')}]"
164
+ end
165
+ end
166
+
167
+ class SingleElementCollection < Type
168
+ abstract!
169
+
170
+ sig { params(element: TypeLike).void }
171
+ def initialize(element)
172
+ @element = to_type(element)
173
+ end
174
+
175
+ sig { returns(Type) }
176
+ attr_reader :element
177
+
178
+ sig { abstract.returns(String) }
179
+ def collection_name; end
180
+
181
+ sig { override.returns(String) }
182
+ def generate_rbi
183
+ "T::#{collection_name}[#{element.generate_rbi}]"
184
+ end
185
+
186
+ sig { override.returns(String) }
187
+ def generate_rbs
188
+ "#{collection_name}[#{element.generate_rbs}]"
189
+ end
190
+ end
191
+
192
+ # An array with known element types.
193
+ class Array < SingleElementCollection
194
+ sig { override.returns(String) }
195
+ def collection_name
196
+ 'Array'
197
+ end
198
+
199
+ sig { params(other: Object).returns(T::Boolean) }
200
+ def ==(other)
201
+ Array === other && element == other.element
202
+ end
203
+ end
204
+
205
+ # A set with known element types.
206
+ class Set < SingleElementCollection
207
+ sig { override.returns(String) }
208
+ def collection_name
209
+ 'Set'
210
+ end
211
+
212
+ sig { params(other: Object).returns(T::Boolean) }
213
+ def ==(other)
214
+ Set === other && element == other.element
215
+ end
216
+ end
217
+
218
+ # A range with known element types.
219
+ class Range < SingleElementCollection
220
+ sig { override.returns(String) }
221
+ def collection_name
222
+ 'Range'
223
+ end
224
+
225
+ sig { params(other: Object).returns(T::Boolean) }
226
+ def ==(other)
227
+ Range === other && element == other.element
228
+ end
229
+ end
230
+
231
+ # An enumerable with known element types.
232
+ class Enumerable < SingleElementCollection
233
+ sig { override.returns(String) }
234
+ def collection_name
235
+ 'Enumerable'
236
+ end
237
+
238
+ sig { params(other: Object).returns(T::Boolean) }
239
+ def ==(other)
240
+ Enumerable === other && element == other.element
241
+ end
242
+ end
243
+
244
+ # An enumerator with known element types.
245
+ class Enumerator < SingleElementCollection
246
+ sig { override.returns(String) }
247
+ def collection_name
248
+ 'Enumerator'
249
+ end
250
+
251
+ sig { params(other: Object).returns(T::Boolean) }
252
+ def ==(other)
253
+ Enumerator === other && element == other.element
254
+ end
255
+ end
256
+
257
+ # A hash with known key and value types.
258
+ class Hash < Type
259
+ sig { params(key: TypeLike, value: TypeLike).void }
260
+ def initialize(key, value)
261
+ @key = to_type(key)
262
+ @value = to_type(value)
263
+ end
264
+
265
+ sig { params(other: Object).returns(T::Boolean) }
266
+ def ==(other)
267
+ Hash === other && key == other.key && value == other.value
268
+ end
269
+
270
+ sig { returns(Type) }
271
+ attr_reader :key
272
+
273
+ sig { returns(Type) }
274
+ attr_reader :value
275
+
276
+ sig { override.returns(String) }
277
+ def generate_rbi
278
+ "T::Hash[#{key.generate_rbi}, #{value.generate_rbi}]"
279
+ end
280
+
281
+ sig { override.returns(String) }
282
+ def generate_rbs
283
+ "Hash[#{key.generate_rbs}, #{value.generate_rbs}]"
284
+ end
285
+ end
286
+
287
+ # A record/shape; a hash with a fixed set of keys with given types.
288
+ class Record < Type
289
+ sig { params(keys_to_types: T::Hash[Symbol, TypeLike]).void }
290
+ def initialize(keys_to_types)
291
+ @keys_to_types = keys_to_types.map do |k, v|
292
+ [k, to_type(v)]
293
+ end.to_h
294
+ end
295
+
296
+ sig { params(other: Object).returns(T::Boolean) }
297
+ def ==(other)
298
+ Record === other && keys_to_types == other.keys_to_types
299
+ end
300
+
301
+ sig { returns(T::Hash[Symbol, Type]) }
302
+ attr_reader :keys_to_types
303
+
304
+ sig { override.returns(String) }
305
+ def generate_rbi
306
+ "{ #{keys_to_types.map { |k, v| "#{k}: #{v.generate_rbi}" }.join(', ')} }"
307
+ end
308
+
309
+ sig { override.returns(String) }
310
+ def generate_rbs
311
+ "{ #{keys_to_types.map { |k, v| "#{k}: #{v.generate_rbs}" }.join(', ')} }"
312
+ end
313
+ end
314
+
315
+ # A type which represents the class of a type, rather than an instance.
316
+ # For example, "String" means an instance of String, but "Class(String)"
317
+ # means the actual String class.
318
+ class Class < Type
319
+ sig { params(type: TypeLike).void }
320
+ def initialize(type)
321
+ @type = to_type(type)
322
+ end
323
+
324
+ sig { params(other: Object).returns(T::Boolean) }
325
+ def ==(other)
326
+ Class === other && type == other.type
327
+ end
328
+
329
+ sig { returns(Type) }
330
+ attr_reader :type
331
+
332
+ sig { override.returns(String) }
333
+ def generate_rbi
334
+ "T.class_of(#{type.generate_rbi})"
335
+ end
336
+
337
+ sig { override.returns(String) }
338
+ def generate_rbs
339
+ "singleton(#{type.generate_rbs})"
340
+ end
341
+ end
342
+
343
+ # Generic type for a boolean.
344
+ class Boolean < Type
345
+ sig { params(other: Object).returns(T::Boolean) }
346
+ def ==(other)
347
+ Boolean === other
348
+ end
349
+
350
+ sig { override.returns(String) }
351
+ def generate_rbi
352
+ "T::Boolean"
353
+ end
354
+
355
+ sig { override.returns(String) }
356
+ def generate_rbs
357
+ "bool"
358
+ end
359
+ end
360
+
361
+ # The explicit lack of a type.
362
+ class Untyped < Type
363
+ sig { params(other: Object).returns(T::Boolean) }
364
+ def ==(other)
365
+ Untyped === other
366
+ end
367
+
368
+ sig { override.returns(String) }
369
+ def generate_rbi
370
+ "T.untyped"
371
+ end
372
+
373
+ sig { override.returns(String) }
374
+ def generate_rbs
375
+ "untyped"
376
+ end
377
+ end
378
+
379
+ # A type which can be called as a function.
380
+ class Proc < Type
381
+ # A parameter to a proc.
382
+ class Parameter
383
+ extend T::Sig
384
+
385
+ sig { params(name: String, type: TypeLike, default: T.nilable(String)).void }
386
+ def initialize(name, type, default = nil)
387
+ @name = name
388
+ @type = Type.to_type(type)
389
+ @default = default
390
+ end
391
+
392
+ sig { returns(String) }
393
+ attr_reader :name
394
+
395
+ sig { returns(Type) }
396
+ attr_reader :type
397
+
398
+ sig { returns(T.nilable(String)) }
399
+ attr_reader :default
400
+
401
+ sig { params(other: Object).returns(T::Boolean) }
402
+ def ==(other)
403
+ Parameter === other && name == other.name && type == other.type &&
404
+ default == other.default
405
+ end
406
+ end
407
+
408
+ sig { params(parameters: T::Array[Parameter], return_type: T.nilable(TypeLike)).void }
409
+ def initialize(parameters, return_type)
410
+ @parameters = parameters
411
+ @return_type = return_type && to_type(return_type)
412
+ end
413
+
414
+ sig { params(other: Object).returns(T::Boolean) }
415
+ def ==(other)
416
+ Proc === other && parameters == other.parameters && return_type == other.return_type
417
+ end
418
+
419
+ sig { returns(T::Array[Parameter]) }
420
+ attr_reader :parameters
421
+
422
+ sig { returns(T.nilable(Type)) }
423
+ attr_reader :return_type
424
+
425
+ sig { override.returns(String) }
426
+ def generate_rbi
427
+ rbi_params = parameters.map do |param|
428
+ RbiGenerator::Parameter.new(param.name, type: param.type, default: param.default)
429
+ end
430
+ "T.proc.params(#{rbi_params.map(&:to_sig_param).join(', ')}).#{
431
+ @return_type ? "returns(#{@return_type.generate_rbi})" : 'void'
432
+ }"
433
+ end
434
+
435
+ sig { override.returns(String) }
436
+ def generate_rbs
437
+ rbs_params = parameters.map do |param|
438
+ RbsGenerator::Parameter.new(param.name, type: param.type, required: param.default.nil?)
439
+ end
440
+ "(#{rbs_params.map(&:to_rbs_param).join(', ')}) -> #{return_type&.generate_rbs || 'void'}"
441
+ end
442
+ end
443
+ end
444
+ end
445
+