rbi 0.0.6 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rbi/printer.rb CHANGED
@@ -11,14 +11,28 @@ module RBI
11
11
  sig { returns(T.nilable(Node)) }
12
12
  attr_reader :previous_node
13
13
 
14
- sig { params(out: T.any(IO, StringIO), indent: Integer, print_locs: T::Boolean).void }
15
- def initialize(out: $stdout, indent: 0, print_locs: false)
14
+ sig { returns(Integer) }
15
+ attr_reader :current_indent
16
+
17
+ sig { returns(T.nilable(Integer)) }
18
+ attr_reader :max_line_length
19
+
20
+ sig do
21
+ params(
22
+ out: T.any(IO, StringIO),
23
+ indent: Integer,
24
+ print_locs: T::Boolean,
25
+ max_line_length: T.nilable(Integer)
26
+ ).void
27
+ end
28
+ def initialize(out: $stdout, indent: 0, print_locs: false, max_line_length: nil)
16
29
  super()
17
30
  @out = out
18
31
  @current_indent = indent
19
32
  @print_locs = print_locs
20
33
  @in_visibility_group = T.let(false, T::Boolean)
21
34
  @previous_node = T.let(nil, T.nilable(Node))
35
+ @max_line_length = max_line_length
22
36
  end
23
37
 
24
38
  # Printing
@@ -123,19 +137,35 @@ module RBI
123
137
  sig { abstract.params(v: Printer).void }
124
138
  def accept_printer(v); end
125
139
 
126
- sig { params(out: T.any(IO, StringIO), indent: Integer, print_locs: T::Boolean).void }
127
- def print(out: $stdout, indent: 0, print_locs: false)
128
- p = Printer.new(out: out, indent: indent, print_locs: print_locs)
140
+ sig do
141
+ params(
142
+ out: T.any(IO, StringIO),
143
+ indent: Integer,
144
+ print_locs: T::Boolean,
145
+ max_line_length: T.nilable(Integer)
146
+ ).void
147
+ end
148
+ def print(out: $stdout, indent: 0, print_locs: false, max_line_length: nil)
149
+ p = Printer.new(out: out, indent: indent, print_locs: print_locs, max_line_length: max_line_length)
129
150
  p.visit(self)
130
151
  end
131
152
 
132
- sig { params(indent: Integer, print_locs: T::Boolean).returns(String) }
133
- def string(indent: 0, print_locs: false)
153
+ sig { params(indent: Integer, print_locs: T::Boolean, max_line_length: T.nilable(Integer)).returns(String) }
154
+ def string(indent: 0, print_locs: false, max_line_length: nil)
134
155
  out = StringIO.new
135
- print(out: out, indent: indent, print_locs: print_locs)
156
+ print(out: out, indent: indent, print_locs: print_locs, max_line_length: max_line_length)
136
157
  out.string
137
158
  end
138
159
 
160
+ sig { params(v: Printer).void }
161
+ def print_blank_line_before(v)
162
+ previous_node = v.previous_node
163
+ return unless previous_node
164
+ return if previous_node.is_a?(BlankLine)
165
+ return if previous_node.oneline? && oneline?
166
+ v.printn
167
+ end
168
+
139
169
  sig { returns(T::Boolean) }
140
170
  def oneline?
141
171
  true
@@ -171,7 +201,7 @@ module RBI
171
201
  end
172
202
  end
173
203
 
174
- class EmptyComment
204
+ class BlankLine
175
205
  extend T::Sig
176
206
 
177
207
  sig { override.params(v: Printer).void }
@@ -201,8 +231,7 @@ module RBI
201
231
 
202
232
  sig { override.params(v: Printer).void }
203
233
  def accept_printer(v)
204
- previous_node = v.previous_node
205
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
234
+ print_blank_line_before(v)
206
235
 
207
236
  v.printl("# #{loc}") if loc && v.print_locs
208
237
  v.visit_all(comments)
@@ -295,8 +324,7 @@ module RBI
295
324
 
296
325
  sig { override.params(v: Printer).void }
297
326
  def accept_printer(v)
298
- previous_node = v.previous_node
299
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
327
+ print_blank_line_before(v)
300
328
 
301
329
  v.printl("# #{loc}") if loc && v.print_locs
302
330
  v.visit_all(comments)
@@ -309,8 +337,7 @@ module RBI
309
337
 
310
338
  sig { override.params(v: Printer).void }
311
339
  def accept_printer(v)
312
- previous_node = v.previous_node
313
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
340
+ print_blank_line_before(v)
314
341
 
315
342
  v.visit_all(comments)
316
343
  sigs.each { |sig| v.visit(sig) }
@@ -346,8 +373,7 @@ module RBI
346
373
 
347
374
  sig { override.params(v: Printer).void }
348
375
  def accept_printer(v)
349
- previous_node = v.previous_node
350
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
376
+ print_blank_line_before(v)
351
377
 
352
378
  v.visit_all(comments)
353
379
  v.visit_all(sigs)
@@ -521,8 +547,7 @@ module RBI
521
547
 
522
548
  sig { override.params(v: Printer).void }
523
549
  def accept_printer(v)
524
- previous_node = v.previous_node
525
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
550
+ print_blank_line_before(v)
526
551
 
527
552
  v.printl("# #{loc}") if loc && v.print_locs
528
553
  v.visit_all(comments)
@@ -543,8 +568,7 @@ module RBI
543
568
 
544
569
  sig { override.params(v: Printer).void }
545
570
  def accept_printer(v)
546
- previous_node = v.previous_node
547
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
571
+ print_blank_line_before(v)
548
572
 
549
573
  v.printl("# #{loc}") if loc && v.print_locs
550
574
  v.visit_all(comments)
@@ -552,72 +576,65 @@ module RBI
552
576
  end
553
577
  end
554
578
 
555
- class Sig
579
+ class Send
556
580
  extend T::Sig
557
581
 
558
582
  sig { override.params(v: Printer).void }
559
583
  def accept_printer(v)
584
+ print_blank_line_before(v)
585
+
560
586
  v.printl("# #{loc}") if loc && v.print_locs
561
- if oneline?
562
- v.printt("sig { ")
563
- else
564
- v.printl("sig do")
565
- v.indent
566
- end
567
- v.print("abstract.") if is_abstract
568
- v.print("override.") if is_override
569
- v.print("overridable.") if is_overridable
570
- unless type_params.empty?
571
- v.print("type_parameters(")
572
- type_params.each_with_index do |param, index|
573
- v.print(":#{param}")
574
- v.print(", ") if index < type_params.length - 1
587
+ v.visit_all(comments)
588
+ v.printt(method)
589
+ unless args.empty?
590
+ v.print(" ")
591
+ args.each_with_index do |arg, index|
592
+ v.visit(arg)
593
+ v.print(", ") if index < args.size - 1
575
594
  end
576
- v.print(").")
577
595
  end
578
- unless params.empty?
579
- if inline_params?
580
- v.print("params(")
581
- params.each_with_index do |param, index|
582
- v.print(", ") if index > 0
583
- v.visit(param)
584
- end
585
- v.print(").")
596
+ v.printn
597
+ end
598
+ end
599
+
600
+ class Arg
601
+ extend T::Sig
602
+
603
+ sig { override.params(v: Printer).void }
604
+ def accept_printer(v)
605
+ v.print(value)
606
+ end
607
+ end
608
+
609
+ class KwArg
610
+ extend T::Sig
611
+
612
+ sig { override.params(v: Printer).void }
613
+ def accept_printer(v)
614
+ v.print(keyword)
615
+ v.print(": ")
616
+ v.print(value)
617
+ end
618
+ end
619
+
620
+ class Sig
621
+ extend T::Sig
622
+
623
+ sig { override.params(v: Printer).void }
624
+ def accept_printer(v)
625
+ v.printl("# #{loc}") if loc && v.print_locs
626
+ max_line_length = v.max_line_length
627
+ if oneline? && max_line_length.nil?
628
+ print_as_line(v)
629
+ elsif max_line_length
630
+ line = string(indent: v.current_indent)
631
+ if line.length <= max_line_length
632
+ v.print(line)
586
633
  else
587
- v.printl("params(")
588
- v.indent
589
- params.each_with_index do |param, pindex|
590
- v.printt
591
- v.visit(param)
592
- v.print(",") if pindex < params.size - 1
593
- param.comments_lines.each_with_index do |comment, cindex|
594
- if cindex == 0
595
- v.print(" ")
596
- else
597
- param.print_comment_leading_space(v, last: pindex == params.size - 1)
598
- end
599
- v.print("# #{comment}")
600
- end
601
- v.printn
602
- end
603
- v.dedent
604
- v.printt(").")
634
+ print_as_block(v)
605
635
  end
606
- end
607
- if return_type && return_type != "void"
608
- v.print("returns(#{return_type})")
609
- else
610
- v.print("void")
611
- end
612
- if checked
613
- v.print(".checked(:#{checked})")
614
- end
615
- if oneline?
616
- v.printn(" }")
617
636
  else
618
- v.printn
619
- v.dedent
620
- v.printl("end")
637
+ print_as_block(v)
621
638
  end
622
639
  end
623
640
 
@@ -630,6 +647,90 @@ module RBI
630
647
  def inline_params?
631
648
  params.all? { |p| p.comments.empty? }
632
649
  end
650
+
651
+ private
652
+
653
+ sig { returns(T::Array[String]) }
654
+ def sig_modifiers
655
+ modifiers = T.let([], T::Array[String])
656
+ modifiers << "abstract" if is_abstract
657
+ modifiers << "override" if is_override
658
+ modifiers << "overridable" if is_overridable
659
+ modifiers << "type_parameters(#{type_params.map { |type| ":#{type}" }.join(", ")})" if type_params.any?
660
+ modifiers << "checked(:#{checked})" if checked
661
+ modifiers
662
+ end
663
+
664
+ sig { params(v: Printer).void }
665
+ def print_as_line(v)
666
+ v.printt("sig { ")
667
+ sig_modifiers.each do |modifier|
668
+ v.print("#{modifier}.")
669
+ end
670
+ unless params.empty?
671
+ v.print("params(")
672
+ params.each_with_index do |param, index|
673
+ v.print(", ") if index > 0
674
+ v.visit(param)
675
+ end
676
+ v.print(").")
677
+ end
678
+ if return_type && return_type != "void"
679
+ v.print("returns(#{return_type})")
680
+ else
681
+ v.print("void")
682
+ end
683
+ v.printn(" }")
684
+ end
685
+
686
+ sig { params(v: Printer).void }
687
+ def print_as_block(v)
688
+ modifiers = sig_modifiers
689
+
690
+ v.printl("sig do")
691
+ v.indent
692
+ if modifiers.any?
693
+ v.printl(T.must(modifiers.first))
694
+ v.indent
695
+ modifiers[1..]&.each do |modifier|
696
+ v.printl(".#{modifier}")
697
+ end
698
+ end
699
+
700
+ if params.any?
701
+ v.printt
702
+ v.print(".") if modifiers.any?
703
+ v.printn("params(")
704
+ v.indent
705
+ params.each_with_index do |param, pindex|
706
+ v.printt
707
+ v.visit(param)
708
+ v.print(",") if pindex < params.size - 1
709
+ param.comments_lines.each_with_index do |comment, cindex|
710
+ if cindex == 0
711
+ v.print(" ")
712
+ else
713
+ param.print_comment_leading_space(v, last: pindex == params.size - 1)
714
+ end
715
+ v.print("# #{comment}")
716
+ end
717
+ v.printn
718
+ end
719
+ v.dedent
720
+ v.printt(")")
721
+ end
722
+ v.printt if params.empty?
723
+ v.print(".") if modifiers.any? || params.any?
724
+ if return_type && return_type != "void"
725
+ v.print("returns(#{return_type})")
726
+ else
727
+ v.print("void")
728
+ end
729
+ v.printn
730
+ v.dedent
731
+ v.dedent if modifiers.any?
732
+ v.printl("end")
733
+ end
633
734
  end
634
735
 
635
736
  class SigParam
@@ -659,8 +760,7 @@ module RBI
659
760
 
660
761
  sig { override.params(v: Printer).void }
661
762
  def accept_printer(v)
662
- previous_node = v.previous_node
663
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
763
+ print_blank_line_before(v)
664
764
 
665
765
  v.printl("# #{loc}") if loc && v.print_locs
666
766
  v.visit_all(comments)
@@ -699,8 +799,7 @@ module RBI
699
799
 
700
800
  sig { override.params(v: Printer).void }
701
801
  def accept_printer(v)
702
- previous_node = v.previous_node
703
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
802
+ print_blank_line_before(v)
704
803
 
705
804
  v.printl("# #{loc}") if loc && v.print_locs
706
805
  v.visit_all(comments)
@@ -713,8 +812,7 @@ module RBI
713
812
 
714
813
  sig { override.params(v: Printer).void }
715
814
  def accept_printer(v)
716
- previous_node = v.previous_node
717
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
815
+ print_blank_line_before(v)
718
816
 
719
817
  v.printl("# #{loc}") if loc && v.print_locs
720
818
  v.visit_all(comments)
@@ -753,4 +851,17 @@ module RBI
753
851
  false
754
852
  end
755
853
  end
854
+
855
+ class RequiresAncestor
856
+ extend T::Sig
857
+
858
+ sig { override.params(v: Printer).void }
859
+ def accept_printer(v)
860
+ print_blank_line_before(v)
861
+
862
+ v.printl("# #{loc}") if loc && v.print_locs
863
+ v.visit_all(comments)
864
+ v.printl("requires_ancestor { #{name} }")
865
+ end
866
+ end
756
867
  end
@@ -0,0 +1,57 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ class Annotate < Visitor
7
+ extend T::Sig
8
+
9
+ sig { params(annotation: String, annotate_scopes: T::Boolean, annotate_properties: T::Boolean).void }
10
+ def initialize(annotation, annotate_scopes: false, annotate_properties: false)
11
+ super()
12
+ @annotation = annotation
13
+ @annotate_scopes = annotate_scopes
14
+ @annotate_properties = annotate_properties
15
+ end
16
+
17
+ sig { override.params(node: T.nilable(Node)).void }
18
+ def visit(node)
19
+ case node
20
+ when Scope
21
+ annotate_node(node) if @annotate_scopes || root?(node)
22
+ when Const, Attr, Method, TStructField, TypeMember
23
+ annotate_node(node) if @annotate_properties
24
+ end
25
+ visit_all(node.nodes) if node.is_a?(Tree)
26
+ end
27
+
28
+ private
29
+
30
+ sig { params(node: NodeWithComments).void }
31
+ def annotate_node(node)
32
+ return if node.annotations.one?(@annotation)
33
+ node.comments << Comment.new("@#{@annotation}")
34
+ end
35
+
36
+ sig { params(node: Node).returns(T::Boolean) }
37
+ def root?(node)
38
+ parent = node.parent_tree
39
+ parent.is_a?(Tree) && parent.parent_tree.nil?
40
+ end
41
+ end
42
+ end
43
+
44
+ class Tree
45
+ extend T::Sig
46
+
47
+ sig { params(annotation: String, annotate_scopes: T::Boolean, annotate_properties: T::Boolean).void }
48
+ def annotate!(annotation, annotate_scopes: false, annotate_properties: false)
49
+ visitor = Rewriters::Annotate.new(
50
+ annotation,
51
+ annotate_scopes: annotate_scopes,
52
+ annotate_properties: annotate_properties
53
+ )
54
+ visitor.visit(self)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,45 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ class Deannotate < Visitor
7
+ extend T::Sig
8
+
9
+ sig { params(annotation: String).void }
10
+ def initialize(annotation)
11
+ super()
12
+ @annotation = annotation
13
+ end
14
+
15
+ sig { override.params(node: T.nilable(Node)).void }
16
+ def visit(node)
17
+ case node
18
+ when Scope, Const, Attr, Method, TStructField, TypeMember
19
+ deannotate_node(node)
20
+ end
21
+ visit_all(node.nodes) if node.is_a?(Tree)
22
+ end
23
+
24
+ private
25
+
26
+ sig { params(node: NodeWithComments).void }
27
+ def deannotate_node(node)
28
+ return unless node.annotations.one?(@annotation)
29
+ node.comments.reject! do |comment|
30
+ comment.text == "@#{@annotation}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ class Tree
37
+ extend T::Sig
38
+
39
+ sig { params(annotation: String).void }
40
+ def deannotate!(annotation)
41
+ visitor = Rewriters::Deannotate.new(annotation)
42
+ visitor.visit(self)
43
+ end
44
+ end
45
+ end
@@ -49,12 +49,18 @@ module RBI
49
49
  case self
50
50
  when Include, Extend
51
51
  Group::Kind::Mixins
52
+ when RequiresAncestor
53
+ Group::Kind::RequiredAncestors
52
54
  when Helper
53
55
  Group::Kind::Helpers
54
56
  when TypeMember
55
57
  Group::Kind::TypeMembers
56
58
  when MixesInClassMethods
57
59
  Group::Kind::MixesInClassMethods
60
+ when Send
61
+ Group::Kind::Sends
62
+ when Attr
63
+ Group::Kind::Attrs
58
64
  when TStructField
59
65
  Group::Kind::TStructFields
60
66
  when TEnumBlock
@@ -67,6 +73,8 @@ module RBI
67
73
  else
68
74
  Group::Kind::Methods
69
75
  end
76
+ when SingletonClass
77
+ Group::Kind::SingletonClasses
70
78
  when Scope, Const
71
79
  Group::Kind::Consts
72
80
  else
@@ -90,13 +98,17 @@ module RBI
90
98
  class Kind < T::Enum
91
99
  enums do
92
100
  Mixins = new
101
+ RequiredAncestors = new
93
102
  Helpers = new
94
103
  TypeMembers = new
95
104
  MixesInClassMethods = new
105
+ Sends = new
106
+ Attrs = new
96
107
  TStructFields = new
97
108
  TEnums = new
98
109
  Inits = new
99
110
  Methods = new
111
+ SingletonClasses = new
100
112
  Consts = new
101
113
  end
102
114
  end
@@ -47,7 +47,7 @@ module RBI
47
47
  end
48
48
  end
49
49
 
50
- sig { params(left: Tree, right: Tree, left_name: String, right_name: String, keep: Keep).returns(Tree) }
50
+ sig { params(left: Tree, right: Tree, left_name: String, right_name: String, keep: Keep).returns(MergeTree) }
51
51
  def self.merge_trees(left, right, left_name: "left", right_name: "right", keep: Keep::NONE)
52
52
  left.nest_singleton_methods!
53
53
  right.nest_singleton_methods!
@@ -59,7 +59,7 @@ module RBI
59
59
  tree
60
60
  end
61
61
 
62
- sig { returns(Tree) }
62
+ sig { returns(MergeTree) }
63
63
  attr_reader :tree
64
64
 
65
65
  sig { params(left_name: String, right_name: String, keep: Keep).void }
@@ -67,15 +67,15 @@ module RBI
67
67
  @left_name = left_name
68
68
  @right_name = right_name
69
69
  @keep = keep
70
- @tree = T.let(Tree.new, Tree)
70
+ @tree = T.let(MergeTree.new, MergeTree)
71
71
  @scope_stack = T.let([@tree], T::Array[Tree])
72
72
  end
73
73
 
74
- sig { params(tree: Tree).returns(T::Array[Conflict]) }
74
+ sig { params(tree: Tree).void }
75
75
  def merge(tree)
76
76
  v = TreeMerger.new(@tree, left_name: @left_name, right_name: @right_name, keep: @keep)
77
77
  v.visit(tree)
78
- v.conflicts
78
+ @tree.conflicts.concat(v.conflicts)
79
79
  end
80
80
 
81
81
  # Used for logging / error displaying purpose
@@ -314,9 +314,31 @@ module RBI
314
314
  class Tree
315
315
  extend T::Sig
316
316
 
317
- sig { params(other: Tree).returns(Tree) }
318
- def merge(other)
319
- Rewriters::Merge.merge_trees(self, other)
317
+ sig { params(other: Tree, left_name: String, right_name: String, keep: Rewriters::Merge::Keep).returns(MergeTree) }
318
+ def merge(other, left_name: "left", right_name: "right", keep: Rewriters::Merge::Keep::NONE)
319
+ Rewriters::Merge.merge_trees(self, other, left_name: left_name, right_name: right_name, keep: keep)
320
+ end
321
+ end
322
+
323
+ # A tree that _might_ contain conflicts
324
+ class MergeTree < Tree
325
+ extend T::Sig
326
+
327
+ sig { returns(T::Array[Rewriters::Merge::Conflict]) }
328
+ attr_reader :conflicts
329
+
330
+ sig do
331
+ params(
332
+ loc: T.nilable(Loc),
333
+ comments: T::Array[Comment],
334
+ conflicts: T::Array[Rewriters::Merge::Conflict],
335
+ block: T.nilable(T.proc.params(node: Tree).void)
336
+ ).void
337
+ end
338
+ def initialize(loc: nil, comments: [], conflicts: [], &block)
339
+ super(loc: loc, comments: comments)
340
+ @conflicts = conflicts
341
+ block&.call(self)
320
342
  end
321
343
  end
322
344
 
@@ -490,6 +512,15 @@ module RBI
490
512
  end
491
513
  end
492
514
 
515
+ class Send
516
+ extend T::Sig
517
+
518
+ sig { override.params(other: Node).returns(T::Boolean) }
519
+ def compatible_with?(other)
520
+ other.is_a?(Send) && method == other.method && args == other.args
521
+ end
522
+ end
523
+
493
524
  class TStructField
494
525
  extend T::Sig
495
526