rbi 0.0.2 → 0.0.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.
data/lib/rbi/printer.rb CHANGED
@@ -163,6 +163,15 @@ module RBI
163
163
  end
164
164
  end
165
165
 
166
+ class EmptyComment
167
+ extend T::Sig
168
+
169
+ sig { override.params(v: Printer).void }
170
+ def accept_printer(v)
171
+ v.printn
172
+ end
173
+ end
174
+
166
175
  class Tree
167
176
  extend T::Sig
168
177
 
@@ -238,6 +247,27 @@ module RBI
238
247
  end
239
248
  end
240
249
 
250
+ class Struct
251
+ extend T::Sig
252
+
253
+ sig { override.params(v: Printer).void }
254
+ def print_header(v)
255
+ v.printt("#{name} = ::Struct.new")
256
+ if !members.empty? || keyword_init
257
+ v.print("(")
258
+ args = members.map { |member| ":#{member}" }
259
+ args << "keyword_init: true" if keyword_init
260
+ v.print(args.join(", "))
261
+ v.print(")")
262
+ end
263
+ if empty?
264
+ v.printn
265
+ else
266
+ v.printn(" do")
267
+ end
268
+ end
269
+ end
270
+
241
271
  class SingletonClass
242
272
  extend T::Sig
243
273
 
@@ -278,7 +308,7 @@ module RBI
278
308
  sigs.each { |sig| v.visit(sig) }
279
309
  v.printl("# #{loc}") if loc && v.print_locs
280
310
  v.printt
281
- unless v.in_visibility_group || visibility == Visibility::Public
311
+ unless v.in_visibility_group || visibility.public?
282
312
  v.print(visibility.visibility.to_s)
283
313
  v.print(" ")
284
314
  end
@@ -315,7 +345,7 @@ module RBI
315
345
  v.visit_all(sigs)
316
346
  v.printl("# #{loc}") if loc && v.print_locs
317
347
  v.printt
318
- unless v.in_visibility_group || visibility == Visibility::Public
348
+ unless v.in_visibility_group || visibility.public?
319
349
  v.print(visibility.visibility.to_s)
320
350
  v.print(" ")
321
351
  end
@@ -338,7 +368,7 @@ module RBI
338
368
  v.print(",") if pindex < params.size - 1
339
369
  param.comments.each_with_index do |comment, cindex|
340
370
  if cindex > 0
341
- param.print_comment_leading_space(v)
371
+ param.print_comment_leading_space(v, last: pindex == params.size - 1)
342
372
  else
343
373
  v.print(" ")
344
374
  end
@@ -373,11 +403,12 @@ module RBI
373
403
  v.print(name.to_s)
374
404
  end
375
405
 
376
- sig { params(v: Printer).void }
377
- def print_comment_leading_space(v)
406
+ sig { params(v: Printer, last: T::Boolean).void }
407
+ def print_comment_leading_space(v, last:)
378
408
  v.printn
379
409
  v.printt
380
- v.print(" " * (name.size + 2))
410
+ v.print(" " * (name.size + 1))
411
+ v.print(" ") unless last
381
412
  end
382
413
  end
383
414
 
@@ -389,8 +420,8 @@ module RBI
389
420
  v.print("#{name} = #{value}")
390
421
  end
391
422
 
392
- sig { override.params(v: Printer).void }
393
- def print_comment_leading_space(v)
423
+ sig { override.params(v: Printer, last: T::Boolean).void }
424
+ def print_comment_leading_space(v, last:)
394
425
  super
395
426
  v.print(" " * (value.size + 3))
396
427
  end
@@ -404,8 +435,8 @@ module RBI
404
435
  v.print("*#{name}")
405
436
  end
406
437
 
407
- sig { override.params(v: Printer).void }
408
- def print_comment_leading_space(v)
438
+ sig { override.params(v: Printer, last: T::Boolean).void }
439
+ def print_comment_leading_space(v, last:)
409
440
  super
410
441
  v.print(" ")
411
442
  end
@@ -419,8 +450,8 @@ module RBI
419
450
  v.print("#{name}:")
420
451
  end
421
452
 
422
- sig { override.params(v: Printer).void }
423
- def print_comment_leading_space(v)
453
+ sig { override.params(v: Printer, last: T::Boolean).void }
454
+ def print_comment_leading_space(v, last:)
424
455
  super
425
456
  v.print(" ")
426
457
  end
@@ -434,11 +465,9 @@ module RBI
434
465
  v.print("#{name}: #{value}")
435
466
  end
436
467
 
437
- sig { override.params(v: Printer).void }
438
- def print_comment_leading_space(v)
439
- v.printn
440
- v.printt
441
- v.print(" " * (name.size + 2))
468
+ sig { override.params(v: Printer, last: T::Boolean).void }
469
+ def print_comment_leading_space(v, last:)
470
+ super
442
471
  v.print(" " * (value.size + 2))
443
472
  end
444
473
  end
@@ -451,8 +480,8 @@ module RBI
451
480
  v.print("**#{name}")
452
481
  end
453
482
 
454
- sig { override.params(v: Printer).void }
455
- def print_comment_leading_space(v)
483
+ sig { override.params(v: Printer, last: T::Boolean).void }
484
+ def print_comment_leading_space(v, last:)
456
485
  super
457
486
  v.print(" ")
458
487
  end
@@ -465,6 +494,12 @@ module RBI
465
494
  def accept_printer(v)
466
495
  v.print("&#{name}")
467
496
  end
497
+
498
+ sig { override.params(v: Printer, last: T::Boolean).void }
499
+ def print_comment_leading_space(v, last:)
500
+ super
501
+ v.print(" ")
502
+ end
468
503
  end
469
504
 
470
505
  class Mixin
@@ -494,7 +529,11 @@ module RBI
494
529
 
495
530
  sig { override.params(v: Printer).void }
496
531
  def accept_printer(v)
532
+ previous_node = v.previous_node
533
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
534
+
497
535
  v.printl("# #{loc}") if loc && v.print_locs
536
+ v.visit_all(comments)
498
537
  v.printl(visibility.to_s)
499
538
  end
500
539
  end
@@ -505,7 +544,12 @@ module RBI
505
544
  sig { override.params(v: Printer).void }
506
545
  def accept_printer(v)
507
546
  v.printl("# #{loc}") if loc && v.print_locs
508
- v.printt("sig { ")
547
+ if oneline?
548
+ v.printt("sig { ")
549
+ else
550
+ v.printl("sig do")
551
+ v.indent
552
+ end
509
553
  v.print("abstract.") if is_abstract
510
554
  v.print("override.") if is_override
511
555
  v.print("overridable.") if is_overridable
@@ -518,12 +562,33 @@ module RBI
518
562
  v.print(").")
519
563
  end
520
564
  unless params.empty?
521
- v.print("params(")
522
- params.each_with_index do |param, index|
523
- v.visit(param)
524
- v.print(", ") if index < params.length - 1
565
+ if inline_params?
566
+ v.print("params(")
567
+ params.each_with_index do |param, index|
568
+ v.print(", ") if index > 0
569
+ v.visit(param)
570
+ end
571
+ v.print(").")
572
+ else
573
+ v.printl("params(")
574
+ v.indent
575
+ params.each_with_index do |param, pindex|
576
+ v.printt
577
+ v.visit(param)
578
+ v.print(",") if pindex < params.size - 1
579
+ param.comments.each_with_index do |comment, cindex|
580
+ if cindex == 0
581
+ v.print(" ")
582
+ else
583
+ param.print_comment_leading_space(v, last: pindex == params.size - 1)
584
+ end
585
+ v.print("# #{comment.text.strip}")
586
+ end
587
+ v.printn
588
+ end
589
+ v.dedent
590
+ v.printt(").")
525
591
  end
526
- v.print(").")
527
592
  end
528
593
  if return_type && return_type != "void"
529
594
  v.print("returns(#{return_type})")
@@ -533,7 +598,23 @@ module RBI
533
598
  if checked
534
599
  v.print(".checked(:#{checked})")
535
600
  end
536
- v.printn(" }")
601
+ if oneline?
602
+ v.printn(" }")
603
+ else
604
+ v.printn
605
+ v.dedent
606
+ v.printl("end")
607
+ end
608
+ end
609
+
610
+ sig { override.returns(T::Boolean) }
611
+ def oneline?
612
+ inline_params?
613
+ end
614
+
615
+ sig { returns(T::Boolean) }
616
+ def inline_params?
617
+ params.all? { |p| p.comments.empty? }
537
618
  end
538
619
  end
539
620
 
@@ -544,6 +625,14 @@ module RBI
544
625
  def accept_printer(v)
545
626
  v.print("#{name}: #{type}")
546
627
  end
628
+
629
+ sig { params(v: Printer, last: T::Boolean).void }
630
+ def print_comment_leading_space(v, last:)
631
+ v.printn
632
+ v.printt
633
+ v.print(" " * (name.size + type.size + 3))
634
+ v.print(" ") unless last
635
+ end
547
636
  end
548
637
 
549
638
  class TStructField
@@ -630,14 +719,19 @@ module RBI
630
719
  sig { override.params(v: Printer).void }
631
720
  def accept_printer(v)
632
721
  v.in_visibility_group = true
633
- v.printn unless v.previous_node.nil?
634
- case visibility
635
- when Visibility::Protected, Visibility::Private
722
+ if visibility.public?
723
+ v.printn unless v.previous_node.nil?
724
+ else
636
725
  v.visit(visibility)
637
726
  v.printn
638
727
  end
639
728
  v.visit_all(nodes)
640
729
  v.in_visibility_group = false
641
730
  end
731
+
732
+ sig { override.returns(T::Boolean) }
733
+ def oneline?
734
+ false
735
+ end
642
736
  end
643
737
  end
@@ -0,0 +1,71 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ class AddSigTemplates < Visitor
7
+ extend T::Sig
8
+
9
+ sig { params(with_todo_comment: T::Boolean).void }
10
+ def initialize(with_todo_comment: true)
11
+ super()
12
+ @with_todo_comment = with_todo_comment
13
+ end
14
+
15
+ sig { override.params(node: T.nilable(Node)).void }
16
+ def visit(node)
17
+ case node
18
+ when Tree
19
+ visit_all(node.nodes)
20
+ when Attr
21
+ add_attr_sig(node)
22
+ when Method
23
+ add_method_sig(node)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ sig { params(attr: Attr).void }
30
+ def add_attr_sig(attr)
31
+ return unless attr.sigs.empty?
32
+ return if attr.names.size > 1
33
+
34
+ params = []
35
+ params << SigParam.new(attr.names.first.to_s, "T.untyped") if attr.is_a?(AttrWriter)
36
+
37
+ attr.sigs << Sig.new(
38
+ params: params,
39
+ return_type: "T.untyped"
40
+ )
41
+ add_todo_comment(attr)
42
+ end
43
+
44
+ sig { params(method: Method).void }
45
+ def add_method_sig(method)
46
+ return unless method.sigs.empty?
47
+
48
+ method.sigs << Sig.new(
49
+ params: method.params.map { |param| SigParam.new(param.name, "T.untyped") },
50
+ return_type: "T.untyped"
51
+ )
52
+ add_todo_comment(method)
53
+ end
54
+
55
+ sig { params(node: NodeWithComments).void }
56
+ def add_todo_comment(node)
57
+ node.comments << Comment.new("TODO: fill in signature with appropriate type information") if @with_todo_comment
58
+ end
59
+ end
60
+ end
61
+
62
+ class Tree
63
+ extend T::Sig
64
+
65
+ sig { params(with_todo_comment: T::Boolean).void }
66
+ def add_sig_templates!(with_todo_comment: true)
67
+ visitor = Rewriters::AddSigTemplates.new(with_todo_comment: with_todo_comment)
68
+ visitor.visit(self)
69
+ end
70
+ end
71
+ end
@@ -39,9 +39,17 @@ module RBI
39
39
  class Merge
40
40
  extend T::Sig
41
41
 
42
- sig { params(left: Tree, right: Tree, left_name: String, right_name: String).returns(Tree) }
43
- def self.merge_trees(left, right, left_name: "left", right_name: "right")
44
- rewriter = Rewriters::Merge.new(left_name: left_name, right_name: right_name)
42
+ class Keep < ::T::Enum
43
+ enums do
44
+ NONE = new
45
+ LEFT = new
46
+ RIGHT = new
47
+ end
48
+ end
49
+
50
+ sig { params(left: Tree, right: Tree, left_name: String, right_name: String, keep: Keep).returns(Tree) }
51
+ def self.merge_trees(left, right, left_name: "left", right_name: "right", keep: Keep::NONE)
52
+ rewriter = Rewriters::Merge.new(left_name: left_name, right_name: right_name, keep: keep)
45
53
  rewriter.merge(left)
46
54
  rewriter.merge(right)
47
55
  tree = rewriter.tree
@@ -52,17 +60,18 @@ module RBI
52
60
  sig { returns(Tree) }
53
61
  attr_reader :tree
54
62
 
55
- sig { params(left_name: String, right_name: String).void }
56
- def initialize(left_name: "left", right_name: "right")
63
+ sig { params(left_name: String, right_name: String, keep: Keep).void }
64
+ def initialize(left_name: "left", right_name: "right", keep: Keep::NONE)
57
65
  @left_name = left_name
58
66
  @right_name = right_name
67
+ @keep = keep
59
68
  @tree = T.let(Tree.new, Tree)
60
69
  @scope_stack = T.let([@tree], T::Array[Tree])
61
70
  end
62
71
 
63
72
  sig { params(tree: Tree).returns(T::Array[Conflict]) }
64
73
  def merge(tree)
65
- v = TreeMerger.new(@tree, left_name: @left_name, right_name: @right_name)
74
+ v = TreeMerger.new(@tree, left_name: @left_name, right_name: @right_name, keep: @keep)
66
75
  v.visit(tree)
67
76
  v.conflicts
68
77
  end
@@ -88,14 +97,15 @@ module RBI
88
97
  sig { returns(T::Array[Conflict]) }
89
98
  attr_reader :conflicts
90
99
 
91
- sig { params(output: Tree, left_name: String, right_name: String).void }
92
- def initialize(output, left_name: "left", right_name: "right")
100
+ sig { params(output: Tree, left_name: String, right_name: String, keep: Keep).void }
101
+ def initialize(output, left_name: "left", right_name: "right", keep: Keep::NONE)
93
102
  super()
94
103
  @tree = output
95
104
  @index = T.let(output.index, Index)
96
105
  @scope_stack = T.let([@tree], T::Array[Tree])
97
106
  @left_name = left_name
98
107
  @right_name = right_name
108
+ @keep = keep
99
109
  @conflicts = T.let([], T::Array[Conflict])
100
110
  end
101
111
 
@@ -110,6 +120,10 @@ module RBI
110
120
  if prev.is_a?(Scope)
111
121
  if node.compatible_with?(prev)
112
122
  prev.merge_with(node)
123
+ elsif @keep == Keep::LEFT
124
+ # do nothing it's already merged
125
+ elsif @keep == Keep::RIGHT
126
+ prev = replace_scope_header(prev, node)
113
127
  else
114
128
  make_conflict_scope(prev, node)
115
129
  end
@@ -129,6 +143,10 @@ module RBI
129
143
  if prev
130
144
  if node.compatible_with?(prev)
131
145
  prev.merge_with(node)
146
+ elsif @keep == Keep::LEFT
147
+ # do nothing it's already merged
148
+ elsif @keep == Keep::RIGHT
149
+ prev.replace(node)
132
150
  else
133
151
  make_conflict_tree(prev, node)
134
152
  end
@@ -175,6 +193,17 @@ module RBI
175
193
  end
176
194
  tree.right << right
177
195
  end
196
+
197
+ sig { params(left: Scope, right: Scope).returns(Scope) }
198
+ def replace_scope_header(left, right)
199
+ right_copy = right.dup_empty
200
+ left.replace(right_copy)
201
+ left.nodes.each do |node|
202
+ right_copy << node
203
+ end
204
+ @index.index(right_copy)
205
+ right_copy
206
+ end
178
207
  end
179
208
 
180
209
  # Merge adjacent conflict trees
@@ -300,6 +329,8 @@ module RBI
300
329
  Module.new(name, loc: loc, comments: comments)
301
330
  when Class
302
331
  Class.new(name, superclass_name: superclass_name, loc: loc, comments: comments)
332
+ when Struct
333
+ Struct.new(name, members: members, keyword_init: keyword_init, loc: loc, comments: comments)
303
334
  when SingletonClass
304
335
  SingletonClass.new(loc: loc, comments: comments)
305
336
  else
@@ -326,6 +357,15 @@ module RBI
326
357
  end
327
358
  end
328
359
 
360
+ class Struct
361
+ extend T::Sig
362
+
363
+ sig { override.params(other: Node).returns(T::Boolean) }
364
+ def compatible_with?(other)
365
+ other.is_a?(Struct) && members == other.members && keyword_init == other.keyword_init
366
+ end
367
+ end
368
+
329
369
  class Const
330
370
  extend T::Sig
331
371