rbi 0.1.13 → 0.2.0

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.
@@ -0,0 +1,169 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class UnexpectedMultipleSigsError < Error
6
+ sig { returns(Node) }
7
+ attr_reader :node
8
+
9
+ sig { params(node: Node).void }
10
+ def initialize(node)
11
+ super(<<~MSG)
12
+ This declaration cannot have more than one sig.
13
+
14
+ #{node.string.chomp}
15
+ MSG
16
+
17
+ @node = node
18
+ end
19
+ end
20
+
21
+ module Rewriters
22
+ class AttrToMethods < Visitor
23
+ extend T::Sig
24
+
25
+ sig { override.params(node: T.nilable(Node)).void }
26
+ def visit(node)
27
+ case node
28
+ when Tree
29
+ visit_all(node.nodes.dup)
30
+
31
+ when Attr
32
+ replace(node, with: node.convert_to_methods)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ sig { params(node: Node, with: T::Array[Node]).void }
39
+ def replace(node, with:)
40
+ tree = node.parent_tree
41
+ raise ReplaceNodeError, "Can't replace #{self} without a parent tree" unless tree
42
+
43
+ node.detach
44
+ with.each { |node| tree << node }
45
+ end
46
+ end
47
+ end
48
+
49
+ class Tree
50
+ extend T::Sig
51
+
52
+ sig { void }
53
+ def replace_attributes_with_methods!
54
+ visitor = Rewriters::AttrToMethods.new
55
+ visitor.visit(self)
56
+ end
57
+ end
58
+
59
+ class Attr
60
+ sig { abstract.returns(T::Array[Method]) }
61
+ def convert_to_methods; end
62
+
63
+ private
64
+
65
+ sig(:final) { returns([T.nilable(Sig), T.nilable(T.any(Type, String))]) }
66
+ def parse_sig
67
+ raise UnexpectedMultipleSigsError, self if 1 < sigs.count
68
+
69
+ sig = sigs.first
70
+ return [nil, nil] unless sig
71
+
72
+ attribute_type = case self
73
+ when AttrReader, AttrAccessor then sig.return_type
74
+ when AttrWriter then sig.params.first&.type
75
+ end
76
+
77
+ [sig, attribute_type]
78
+ end
79
+
80
+ sig do
81
+ params(
82
+ name: String,
83
+ sig: T.nilable(Sig),
84
+ visibility: Visibility,
85
+ loc: T.nilable(Loc),
86
+ comments: T::Array[Comment],
87
+ ).returns(Method)
88
+ end
89
+ def create_getter_method(name, sig, visibility, loc, comments)
90
+ Method.new(
91
+ name,
92
+ params: [],
93
+ visibility: visibility,
94
+ sigs: sig ? [sig] : [],
95
+ loc: loc,
96
+ comments: comments,
97
+ )
98
+ end
99
+
100
+ sig do
101
+ params(
102
+ name: String,
103
+ sig: T.nilable(Sig),
104
+ attribute_type: T.nilable(T.any(Type, String)),
105
+ visibility: Visibility,
106
+ loc: T.nilable(Loc),
107
+ comments: T::Array[Comment],
108
+ ).returns(Method)
109
+ end
110
+ def create_setter_method(name, sig, attribute_type, visibility, loc, comments) # rubocop:disable Metrics/ParameterLists
111
+ sig = if sig # Modify the original sig to correct the name, and remove the return type
112
+ params = attribute_type ? [SigParam.new(name, attribute_type)] : []
113
+
114
+ Sig.new(
115
+ params: params,
116
+ return_type: "void",
117
+ is_abstract: sig.is_abstract,
118
+ is_override: sig.is_override,
119
+ is_overridable: sig.is_overridable,
120
+ is_final: sig.is_final,
121
+ type_params: sig.type_params,
122
+ checked: sig.checked,
123
+ loc: sig.loc,
124
+ )
125
+ end
126
+
127
+ Method.new(
128
+ "#{name}=",
129
+ params: [ReqParam.new(name)],
130
+ visibility: visibility,
131
+ sigs: sig ? [sig] : [],
132
+ loc: loc,
133
+ comments: comments,
134
+ )
135
+ end
136
+ end
137
+
138
+ class AttrAccessor
139
+ sig { override.returns(T::Array[Method]) }
140
+ def convert_to_methods
141
+ sig, attribute_type = parse_sig
142
+
143
+ names.flat_map do |name|
144
+ [
145
+ create_getter_method(name.to_s, sig, visibility, loc, comments),
146
+ create_setter_method(name.to_s, sig, attribute_type, visibility, loc, comments),
147
+ ]
148
+ end
149
+ end
150
+ end
151
+
152
+ class AttrReader
153
+ sig { override.returns(T::Array[Method]) }
154
+ def convert_to_methods
155
+ sig, _ = parse_sig
156
+
157
+ names.map { |name| create_getter_method(name.to_s, sig, visibility, loc, comments) }
158
+ end
159
+ end
160
+
161
+ class AttrWriter
162
+ sig { override.returns(T::Array[Method]) }
163
+ def convert_to_methods
164
+ sig, attribute_type = parse_sig
165
+
166
+ names.map { |name| create_setter_method(name.to_s, sig, attribute_type, visibility, loc, comments) }
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,65 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ # Rewrite non-singleton methods inside singleton classes to singleton methods
7
+ #
8
+ # Example:
9
+ # ~~~rb
10
+ # class << self
11
+ # def m1; end
12
+ # def self.m2; end
13
+ #
14
+ # class << self
15
+ # def m3; end
16
+ # end
17
+ # end
18
+ # ~~~
19
+ #
20
+ # will be rewritten to:
21
+ #
22
+ # ~~~rb
23
+ # def self.m1; end
24
+ #
25
+ # class << self
26
+ # def self.m2; end
27
+ # def self.m3; end
28
+ # end
29
+ # ~~~
30
+ class FlattenSingletonMethods < Visitor
31
+ extend T::Sig
32
+
33
+ sig { override.params(node: T.nilable(Node)).void }
34
+ def visit(node)
35
+ return unless node
36
+
37
+ case node
38
+ when SingletonClass
39
+ node.nodes.dup.each do |child|
40
+ visit(child)
41
+ next unless child.is_a?(Method) && !child.is_singleton
42
+
43
+ child.detach
44
+ child.is_singleton = true
45
+ T.must(node.parent_tree) << child
46
+ end
47
+
48
+ node.detach if node.nodes.empty?
49
+ when Tree
50
+ visit_all(node.nodes)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class Tree
57
+ extend T::Sig
58
+
59
+ sig { void }
60
+ def flatten_singleton_methods!
61
+ visitor = Rewriters::FlattenSingletonMethods.new
62
+ visitor.visit(self)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ # Flattens visibility nodes into method nodes
7
+ #
8
+ # Example:
9
+ # ~~~rb
10
+ # class A
11
+ # def m1; end
12
+ # private
13
+ # def m2; end
14
+ # def m3; end
15
+ # end
16
+ # ~~~
17
+ #
18
+ # will be transformed into:
19
+ #
20
+ # ~~~rb
21
+ # class A
22
+ # def m1; end
23
+ # private def m2; end
24
+ # private def m3; end
25
+ # end
26
+ # ~~~
27
+ class FlattenVisibilities < Visitor
28
+ extend T::Sig
29
+
30
+ sig { void }
31
+ def initialize
32
+ super
33
+
34
+ @current_visibility = T.let([Public.new], T::Array[Visibility])
35
+ end
36
+
37
+ sig { override.params(node: T.nilable(Node)).void }
38
+ def visit(node)
39
+ return unless node
40
+
41
+ case node
42
+ when Public, Protected, Private
43
+ @current_visibility[-1] = node
44
+ node.detach
45
+ when Tree
46
+ @current_visibility << Public.new
47
+ visit_all(node.nodes.dup)
48
+ @current_visibility.pop
49
+ when Attr, Method
50
+ node.visibility = T.must(@current_visibility.last)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class Tree
57
+ extend T::Sig
58
+
59
+ sig { void }
60
+ def flatten_visibilities!
61
+ visitor = Rewriters::FlattenVisibilities.new
62
+ visitor.visit(self)
63
+ end
64
+ end
65
+ end
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RBI
5
+ class GroupNodesError < Error; end
6
+
5
7
  module Rewriters
6
8
  class GroupNodes < Visitor
7
9
  extend T::Sig
@@ -12,8 +14,7 @@ module RBI
12
14
 
13
15
  case node
14
16
  when Tree
15
- kinds = node.nodes.map(&:group_kind)
16
- kinds.compact!
17
+ kinds = node.nodes.map { |child| group_kind(child) }
17
18
  kinds.uniq!
18
19
 
19
20
  groups = {}
@@ -22,12 +23,54 @@ module RBI
22
23
  node.nodes.dup.each do |child|
23
24
  visit(child)
24
25
  child.detach
25
- groups[child.group_kind] << child
26
+ groups[group_kind(child)] << child
26
27
  end
27
28
 
28
29
  groups.each { |_, group| node << group }
29
30
  end
30
31
  end
32
+
33
+ private
34
+
35
+ sig { params(node: Node).returns(Group::Kind) }
36
+ def group_kind(node)
37
+ case node
38
+ when Group
39
+ node.kind
40
+ when Include, Extend
41
+ Group::Kind::Mixins
42
+ when RequiresAncestor
43
+ Group::Kind::RequiredAncestors
44
+ when Helper
45
+ Group::Kind::Helpers
46
+ when TypeMember
47
+ Group::Kind::TypeMembers
48
+ when MixesInClassMethods
49
+ Group::Kind::MixesInClassMethods
50
+ when Send
51
+ Group::Kind::Sends
52
+ when Attr
53
+ Group::Kind::Attrs
54
+ when TStructField
55
+ Group::Kind::TStructFields
56
+ when TEnumBlock
57
+ Group::Kind::TEnums
58
+ when VisibilityGroup
59
+ Group::Kind::Methods
60
+ when Method
61
+ if node.name == "initialize"
62
+ Group::Kind::Inits
63
+ else
64
+ Group::Kind::Methods
65
+ end
66
+ when SingletonClass
67
+ Group::Kind::SingletonClasses
68
+ when Scope, Const
69
+ Group::Kind::Consts
70
+ else
71
+ raise GroupNodesError, "Unknown group for #{self}"
72
+ end
73
+ end
31
74
  end
32
75
  end
33
76
 
@@ -41,50 +84,6 @@ module RBI
41
84
  end
42
85
  end
43
86
 
44
- class Node
45
- extend T::Sig
46
-
47
- sig { returns(Group::Kind) }
48
- def group_kind
49
- case self
50
- when Group
51
- kind
52
- when Include, Extend
53
- Group::Kind::Mixins
54
- when RequiresAncestor
55
- Group::Kind::RequiredAncestors
56
- when Helper
57
- Group::Kind::Helpers
58
- when TypeMember
59
- Group::Kind::TypeMembers
60
- when MixesInClassMethods
61
- Group::Kind::MixesInClassMethods
62
- when Send
63
- Group::Kind::Sends
64
- when Attr
65
- Group::Kind::Attrs
66
- when TStructField
67
- Group::Kind::TStructFields
68
- when TEnumBlock
69
- Group::Kind::TEnums
70
- when VisibilityGroup
71
- Group::Kind::Methods
72
- when Method
73
- if name == "initialize"
74
- Group::Kind::Inits
75
- else
76
- Group::Kind::Methods
77
- end
78
- when SingletonClass
79
- Group::Kind::SingletonClasses
80
- when Scope, Const
81
- Group::Kind::Consts
82
- else
83
- raise "Unknown group for #{self}"
84
- end
85
- end
86
- end
87
-
88
87
  class Group < Tree
89
88
  extend T::Sig
90
89
 
@@ -348,6 +348,8 @@ module RBI
348
348
  end
349
349
  end
350
350
 
351
+ class DuplicateNodeError < Error; end
352
+
351
353
  class Scope
352
354
  extend T::Sig
353
355
 
@@ -357,6 +359,12 @@ module RBI
357
359
  case self
358
360
  when Module
359
361
  Module.new(name, loc: loc, comments: comments)
362
+ when TEnum
363
+ TEnum.new(name, loc: loc, comments: comments)
364
+ when TEnumBlock
365
+ TEnumBlock.new(loc: loc, comments: comments)
366
+ when TStruct
367
+ TStruct.new(name, loc: loc, comments: comments)
360
368
  when Class
361
369
  Class.new(name, superclass_name: superclass_name, loc: loc, comments: comments)
362
370
  when Struct
@@ -364,7 +372,7 @@ module RBI
364
372
  when SingletonClass
365
373
  SingletonClass.new(loc: loc, comments: comments)
366
374
  else
367
- raise "Can't duplicate node #{self}"
375
+ raise DuplicateNodeError, "Can't duplicate node #{self}"
368
376
  end
369
377
  end
370
378
  end
@@ -549,20 +557,6 @@ module RBI
549
557
  end
550
558
  end
551
559
 
552
- class TEnumBlock
553
- extend T::Sig
554
-
555
- sig { override.params(other: Node).void }
556
- def merge_with(other)
557
- return unless other.is_a?(TEnumBlock)
558
-
559
- super
560
- other.names.each do |name|
561
- names << name unless names.include?(name)
562
- end
563
- end
564
- end
565
-
566
560
  class TStructProp
567
561
  extend T::Sig
568
562
 
@@ -592,6 +586,9 @@ module RBI
592
586
  sig { returns(Tree) }
593
587
  attr_reader :left, :right
594
588
 
589
+ sig { returns(String) }
590
+ attr_reader :left_name, :right_name
591
+
595
592
  sig { params(left_name: String, right_name: String).void }
596
593
  def initialize(left_name: "left", right_name: "right")
597
594
  super()
@@ -602,15 +599,6 @@ module RBI
602
599
  @right = T.let(Tree.new, Tree)
603
600
  @right.parent_tree = self
604
601
  end
605
-
606
- sig { override.params(v: Printer).void }
607
- def accept_printer(v)
608
- v.printl("<<<<<<< #{@left_name}")
609
- v.visit(left)
610
- v.printl("=======")
611
- v.visit(right)
612
- v.printl(">>>>>>> #{@right_name}")
613
- end
614
602
  end
615
603
 
616
604
  # A conflict between two scope headers
@@ -631,6 +619,9 @@ module RBI
631
619
  sig { returns(Scope) }
632
620
  attr_reader :left, :right
633
621
 
622
+ sig { returns(String) }
623
+ attr_reader :left_name, :right_name
624
+
634
625
  sig do
635
626
  params(
636
627
  left: Scope,
@@ -646,26 +637,5 @@ module RBI
646
637
  @left_name = left_name
647
638
  @right_name = right_name
648
639
  end
649
-
650
- sig { override.params(v: Printer).void }
651
- def accept_printer(v)
652
- previous_node = v.previous_node
653
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
654
-
655
- v.printl("# #{loc}") if loc && v.print_locs
656
- v.visit_all(comments)
657
-
658
- v.printl("<<<<<<< #{@left_name}")
659
- left.print_header(v)
660
- v.printl("=======")
661
- right.print_header(v)
662
- v.printl(">>>>>>> #{@right_name}")
663
- left.print_body(v)
664
- end
665
-
666
- sig { override.returns(T::Boolean) }
667
- def oneline?
668
- left.oneline?
669
- end
670
640
  end
671
641
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  module RBI
5
5
  module Rewriters
6
- class NestNonPublicMethods < Visitor
6
+ class NestNonPublicMembers < Visitor
7
7
  extend T::Sig
8
8
 
9
9
  sig { override.params(node: T.nilable(Node)).void }
@@ -18,7 +18,7 @@ module RBI
18
18
 
19
19
  node.nodes.dup.each do |child|
20
20
  visit(child)
21
- next unless child.is_a?(Method)
21
+ next unless child.is_a?(Attr) || child.is_a?(Method)
22
22
 
23
23
  child.detach
24
24
  case child.visibility
@@ -43,8 +43,8 @@ module RBI
43
43
  extend T::Sig
44
44
 
45
45
  sig { void }
46
- def nest_non_public_methods!
47
- visitor = Rewriters::NestNonPublicMethods.new
46
+ def nest_non_public_members!
47
+ visitor = Rewriters::NestNonPublicMembers.new
48
48
  visitor.visit(self)
49
49
  end
50
50
  end
@@ -0,0 +1,68 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ # This rewriter moves top-level members into a top-level Object class
7
+ #
8
+ # Example:
9
+ # ~~~rb
10
+ # def foo; end
11
+ # attr_reader :bar
12
+ # ~~~
13
+ #
14
+ # will be rewritten to:
15
+ #
16
+ # ~~~rb
17
+ # class Object
18
+ # def foo; end
19
+ # attr_reader :bar
20
+ # end
21
+ # ~~~
22
+ class NestTopLevelMembers < Visitor
23
+ extend T::Sig
24
+
25
+ sig { void }
26
+ def initialize
27
+ super
28
+
29
+ @top_level_object_class = T.let(nil, T.nilable(Class))
30
+ end
31
+
32
+ sig { override.params(node: T.nilable(Node)).void }
33
+ def visit(node)
34
+ return unless node
35
+
36
+ case node
37
+ when Tree
38
+ visit_all(node.nodes.dup)
39
+ else
40
+ scope = node.parent_scope
41
+ unless scope
42
+ parent = node.parent_tree
43
+ raise unless parent
44
+
45
+ node.detach
46
+
47
+ unless @top_level_object_class
48
+ @top_level_object_class = Class.new("Object")
49
+ parent.nodes << @top_level_object_class
50
+ end
51
+
52
+ @top_level_object_class << node
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ class Tree
60
+ extend T::Sig
61
+
62
+ sig { void }
63
+ def nest_top_level_members!
64
+ visitor = Rewriters::NestTopLevelMembers.new
65
+ visitor.visit(self)
66
+ end
67
+ end
68
+ end