parlour 3.0.0 → 5.0.0.beta.3

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 +0 -0
  8. data/CHANGELOG.md +57 -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 +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 +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 +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 +68 -18
  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 +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 +25 -12
  60. data/lib/parlour/type_parser.rb +174 -17
  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 +1856 -0
  67. metadata +35 -10
  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,539 @@
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
+
36
+ def hash
37
+ [self.class, *instance_variables.map { |x| instance_variable_get(x).hash }].hash
38
+ end
39
+
40
+ sig { abstract.returns(String) }
41
+ def describe; end
42
+ end
43
+
44
+ # A basic type as a raw string.
45
+ class Raw < Type
46
+ sig { params(str: String).void }
47
+ def initialize(str)
48
+ @str = str
49
+ end
50
+
51
+ sig { returns(String) }
52
+ attr_reader :str
53
+
54
+ sig { params(other: Object).returns(T::Boolean) }
55
+ def ==(other)
56
+ Raw === other && str == other.str
57
+ end
58
+
59
+ sig { override.returns(String) }
60
+ def generate_rbi
61
+ str
62
+ end
63
+
64
+ sig { override.returns(String) }
65
+ def generate_rbs
66
+ str
67
+ end
68
+
69
+ sig { override.returns(String) }
70
+ def describe
71
+ str
72
+ end
73
+ end
74
+
75
+ # A type which can be either the wrapped type, or nil.
76
+ class Nilable < Type
77
+ sig { params(type: TypeLike).void }
78
+ def initialize(type)
79
+ @type = to_type(type)
80
+ end
81
+
82
+ sig { params(other: Object).returns(T::Boolean) }
83
+ def ==(other)
84
+ Nilable === other && type == other.type
85
+ end
86
+
87
+ sig { returns(Type) }
88
+ attr_reader :type
89
+
90
+ sig { override.returns(String) }
91
+ def generate_rbi
92
+ "T.nilable(#{type.generate_rbi})"
93
+ end
94
+
95
+ sig { override.returns(String) }
96
+ def generate_rbs
97
+ "#{type.generate_rbs}?"
98
+ end
99
+
100
+ sig { override.returns(String) }
101
+ def describe
102
+ "Nilable<#{type.describe}>"
103
+ end
104
+ end
105
+
106
+ # A type which is (at least) one of the wrapped types.
107
+ class Union < Type
108
+ sig { params(types: T::Array[TypeLike]).void }
109
+ def initialize(types)
110
+ @types = types.map(&method(:to_type))
111
+ end
112
+
113
+ sig { params(other: Object).returns(T::Boolean) }
114
+ def ==(other)
115
+ Union === other && types == other.types
116
+ end
117
+
118
+ sig { returns(T::Array[Type]) }
119
+ attr_reader :types
120
+
121
+ sig { override.returns(String) }
122
+ def generate_rbi
123
+ "T.any(#{types.map(&:generate_rbi).join(', ')})"
124
+ end
125
+
126
+ sig { override.returns(String) }
127
+ def generate_rbs
128
+ "(#{types.map(&:generate_rbs).join(' | ')})"
129
+ end
130
+
131
+ sig { override.returns(String) }
132
+ def describe
133
+ "Union<#{types.map(&:describe).join(', ')}>"
134
+ end
135
+ end
136
+
137
+ # A type which matches all of the wrapped types.
138
+ class Intersection < Type
139
+ sig { params(types: T::Array[TypeLike]).void }
140
+ def initialize(types)
141
+ @types = types.map(&method(:to_type))
142
+ end
143
+
144
+ sig { params(other: Object).returns(T::Boolean) }
145
+ def ==(other)
146
+ Intersection === other && types == other.types
147
+ end
148
+
149
+ sig { returns(T::Array[Type]) }
150
+ attr_reader :types
151
+
152
+ sig { override.returns(String) }
153
+ def generate_rbi
154
+ "T.all(#{types.map(&:generate_rbi).join(', ')})"
155
+ end
156
+
157
+ sig { override.returns(String) }
158
+ def generate_rbs
159
+ "(#{types.map(&:generate_rbs).join(' & ')})"
160
+ end
161
+
162
+ sig { override.returns(String) }
163
+ def describe
164
+ "Intersection<#{types.map(&:describe).join(', ')}>"
165
+ end
166
+ end
167
+
168
+ # A fixed-length array of items, each with a known type.
169
+ class Tuple < Type
170
+ sig { params(types: T::Array[TypeLike]).void }
171
+ def initialize(types)
172
+ @types = types.map(&method(:to_type))
173
+ end
174
+
175
+ sig { params(other: Object).returns(T::Boolean) }
176
+ def ==(other)
177
+ Tuple === other && types == other.types
178
+ end
179
+
180
+ sig { returns(T::Array[Type]) }
181
+ attr_reader :types
182
+
183
+ sig { override.returns(String) }
184
+ def generate_rbi
185
+ "[#{types.map(&:generate_rbi).join(', ')}]"
186
+ end
187
+
188
+ sig { override.returns(String) }
189
+ def generate_rbs
190
+ "[#{types.map(&:generate_rbs).join(', ')}]"
191
+ end
192
+
193
+ sig { override.returns(String) }
194
+ def describe
195
+ "[#{types.map(&:describe).join(', ')}]"
196
+ end
197
+ end
198
+
199
+ class SingleElementCollection < Type
200
+ abstract!
201
+
202
+ sig { params(element: TypeLike).void }
203
+ def initialize(element)
204
+ @element = to_type(element)
205
+ end
206
+
207
+ sig { returns(Type) }
208
+ attr_reader :element
209
+
210
+ sig { abstract.returns(String) }
211
+ def collection_name; end
212
+
213
+ sig { override.returns(String) }
214
+ def generate_rbi
215
+ "T::#{collection_name}[#{element.generate_rbi}]"
216
+ end
217
+
218
+ sig { override.returns(String) }
219
+ def generate_rbs
220
+ "#{collection_name}[#{element.generate_rbs}]"
221
+ end
222
+
223
+ sig { override.returns(String) }
224
+ def describe
225
+ "#{collection_name}<#{element.describe}>"
226
+ end
227
+ end
228
+
229
+ # An array with known element types.
230
+ class Array < SingleElementCollection
231
+ sig { override.returns(String) }
232
+ def collection_name
233
+ 'Array'
234
+ end
235
+
236
+ sig { params(other: Object).returns(T::Boolean) }
237
+ def ==(other)
238
+ Array === other && element == other.element
239
+ end
240
+ end
241
+
242
+ # A set with known element types.
243
+ class Set < SingleElementCollection
244
+ sig { override.returns(String) }
245
+ def collection_name
246
+ 'Set'
247
+ end
248
+
249
+ sig { params(other: Object).returns(T::Boolean) }
250
+ def ==(other)
251
+ Set === other && element == other.element
252
+ end
253
+ end
254
+
255
+ # A range with known element types.
256
+ class Range < SingleElementCollection
257
+ sig { override.returns(String) }
258
+ def collection_name
259
+ 'Range'
260
+ end
261
+
262
+ sig { params(other: Object).returns(T::Boolean) }
263
+ def ==(other)
264
+ Range === other && element == other.element
265
+ end
266
+ end
267
+
268
+ # An enumerable with known element types.
269
+ class Enumerable < SingleElementCollection
270
+ sig { override.returns(String) }
271
+ def collection_name
272
+ 'Enumerable'
273
+ end
274
+
275
+ sig { params(other: Object).returns(T::Boolean) }
276
+ def ==(other)
277
+ Enumerable === other && element == other.element
278
+ end
279
+ end
280
+
281
+ # An enumerator with known element types.
282
+ class Enumerator < SingleElementCollection
283
+ sig { override.returns(String) }
284
+ def collection_name
285
+ 'Enumerator'
286
+ end
287
+
288
+ sig { params(other: Object).returns(T::Boolean) }
289
+ def ==(other)
290
+ Enumerator === other && element == other.element
291
+ end
292
+ end
293
+
294
+ # A hash with known key and value types.
295
+ class Hash < Type
296
+ sig { params(key: TypeLike, value: TypeLike).void }
297
+ def initialize(key, value)
298
+ @key = to_type(key)
299
+ @value = to_type(value)
300
+ end
301
+
302
+ sig { params(other: Object).returns(T::Boolean) }
303
+ def ==(other)
304
+ Hash === other && key == other.key && value == other.value
305
+ end
306
+
307
+ sig { returns(Type) }
308
+ attr_reader :key
309
+
310
+ sig { returns(Type) }
311
+ attr_reader :value
312
+
313
+ sig { override.returns(String) }
314
+ def generate_rbi
315
+ "T::Hash[#{key.generate_rbi}, #{value.generate_rbi}]"
316
+ end
317
+
318
+ sig { override.returns(String) }
319
+ def generate_rbs
320
+ "Hash[#{key.generate_rbs}, #{value.generate_rbs}]"
321
+ end
322
+
323
+ sig { override.returns(String) }
324
+ def describe
325
+ "Hash<#{key.describe}, #{value.describe}>"
326
+ end
327
+ end
328
+
329
+ # A record/shape; a hash with a fixed set of keys with given types.
330
+ class Record < Type
331
+ sig { params(keys_to_types: T::Hash[Symbol, TypeLike]).void }
332
+ def initialize(keys_to_types)
333
+ @keys_to_types = keys_to_types.map do |k, v|
334
+ [k, to_type(v)]
335
+ end.to_h
336
+ end
337
+
338
+ sig { params(other: Object).returns(T::Boolean) }
339
+ def ==(other)
340
+ Record === other && keys_to_types == other.keys_to_types
341
+ end
342
+
343
+ sig { returns(T::Hash[Symbol, Type]) }
344
+ attr_reader :keys_to_types
345
+
346
+ sig { override.returns(String) }
347
+ def generate_rbi
348
+ "{ #{keys_to_types.map { |k, v| "#{k}: #{v.generate_rbi}" }.join(', ')} }"
349
+ end
350
+
351
+ sig { override.returns(String) }
352
+ def generate_rbs
353
+ "{ #{keys_to_types.map { |k, v| "#{k}: #{v.generate_rbs}" }.join(', ')} }"
354
+ end
355
+
356
+ sig { override.returns(String) }
357
+ def describe
358
+ "{ #{keys_to_types.map { |k, v| "#{k}: #{v.describe}" }.join(', ')} }"
359
+ end
360
+ end
361
+
362
+ # A type which represents the class of a type, rather than an instance.
363
+ # For example, "String" means an instance of String, but "Class(String)"
364
+ # means the actual String class.
365
+ class Class < Type
366
+ sig { params(type: TypeLike).void }
367
+ def initialize(type)
368
+ @type = to_type(type)
369
+ end
370
+
371
+ sig { params(other: Object).returns(T::Boolean) }
372
+ def ==(other)
373
+ Class === other && type == other.type
374
+ end
375
+
376
+ sig { returns(Type) }
377
+ attr_reader :type
378
+
379
+ sig { override.returns(String) }
380
+ def generate_rbi
381
+ "T.class_of(#{type.generate_rbi})"
382
+ end
383
+
384
+ sig { override.returns(String) }
385
+ def generate_rbs
386
+ "singleton(#{type.generate_rbs})"
387
+ end
388
+
389
+ sig { override.returns(String) }
390
+ def describe
391
+ "Class<#{type.describe}>"
392
+ end
393
+ end
394
+
395
+ # Type for a boolean.
396
+ class Boolean < Type
397
+ sig { params(other: Object).returns(T::Boolean) }
398
+ def ==(other)
399
+ Boolean === other
400
+ end
401
+
402
+ sig { override.returns(String) }
403
+ def generate_rbi
404
+ "T::Boolean"
405
+ end
406
+
407
+ sig { override.returns(String) }
408
+ def generate_rbs
409
+ "bool"
410
+ end
411
+
412
+ sig { override.returns(String) }
413
+ def describe
414
+ "bool"
415
+ end
416
+ end
417
+
418
+ # Type equivalent to the receiver.
419
+ class Self < Type
420
+ sig { params(other: Object).returns(T::Boolean) }
421
+ def ==(other)
422
+ Self === other
423
+ end
424
+
425
+ sig { override.returns(String) }
426
+ def generate_rbi
427
+ "T.self_type"
428
+ end
429
+
430
+ sig { override.returns(String) }
431
+ def generate_rbs
432
+ "self"
433
+ end
434
+
435
+ sig { override.returns(String) }
436
+ def describe
437
+ "self"
438
+ end
439
+ end
440
+
441
+ # The explicit lack of a type.
442
+ class Untyped < Type
443
+ sig { params(other: Object).returns(T::Boolean) }
444
+ def ==(other)
445
+ Untyped === other
446
+ end
447
+
448
+ sig { override.returns(String) }
449
+ def generate_rbi
450
+ "T.untyped"
451
+ end
452
+
453
+ sig { override.returns(String) }
454
+ def generate_rbs
455
+ "untyped"
456
+ end
457
+
458
+ sig { override.returns(String) }
459
+ def describe
460
+ "untyped"
461
+ end
462
+ end
463
+
464
+ # A type which can be called as a function.
465
+ class Proc < Type
466
+ # A parameter to a proc.
467
+ class Parameter
468
+ extend T::Sig
469
+
470
+ sig { params(name: String, type: TypeLike, default: T.nilable(String)).void }
471
+ def initialize(name, type, default = nil)
472
+ @name = name
473
+ @type = Type.to_type(type)
474
+ @default = default
475
+ end
476
+
477
+ sig { returns(String) }
478
+ attr_reader :name
479
+
480
+ sig { returns(Type) }
481
+ attr_reader :type
482
+
483
+ sig { returns(T.nilable(String)) }
484
+ attr_reader :default
485
+
486
+ sig { params(other: Object).returns(T::Boolean) }
487
+ def ==(other)
488
+ Parameter === other && name == other.name && type == other.type &&
489
+ default == other.default
490
+ end
491
+ end
492
+
493
+ sig { params(parameters: T::Array[Parameter], return_type: T.nilable(TypeLike)).void }
494
+ def initialize(parameters, return_type)
495
+ @parameters = parameters
496
+ @return_type = return_type && to_type(return_type)
497
+ end
498
+
499
+ sig { params(other: Object).returns(T::Boolean) }
500
+ def ==(other)
501
+ Proc === other && parameters == other.parameters && return_type == other.return_type
502
+ end
503
+
504
+ sig { returns(T::Array[Parameter]) }
505
+ attr_reader :parameters
506
+
507
+ sig { returns(T.nilable(Type)) }
508
+ attr_reader :return_type
509
+
510
+ sig { override.returns(String) }
511
+ def generate_rbi
512
+ rbi_params = parameters.map do |param|
513
+ RbiGenerator::Parameter.new(param.name, type: param.type, default: param.default)
514
+ end
515
+ "T.proc.params(#{rbi_params.map(&:to_sig_param).join(', ')}).#{
516
+ @return_type ? "returns(#{@return_type.generate_rbi})" : 'void'
517
+ }"
518
+ end
519
+
520
+ sig { override.returns(String) }
521
+ def generate_rbs
522
+ rbs_params = parameters.map do |param|
523
+ RbsGenerator::Parameter.new(param.name, type: param.type, required: param.default.nil?)
524
+ end
525
+ "(#{rbs_params.map(&:to_rbs_param).join(', ')}) -> #{return_type&.generate_rbs || 'void'}"
526
+ end
527
+
528
+ sig { override.returns(String) }
529
+ def describe
530
+ # For simplicity, use RBS with pre-described parameter types
531
+ rbs_params = parameters.map do |param|
532
+ RbsGenerator::Parameter.new(param.name, type: param.type.describe, required: param.default.nil?)
533
+ end
534
+ "(#{rbs_params.map(&:to_rbs_param).join(', ')}) -> #{return_type&.describe || 'void'}"
535
+ end
536
+ end
537
+ end
538
+ end
539
+