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,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
+