rbi 0.3.9 → 0.3.11
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.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/lib/rbi/model.rb +226 -180
- data/lib/rbi/parser.rb +1 -1
- data/lib/rbi/printer.rb +152 -89
- data/lib/rbi/rbs/method_type_translator.rb +1 -1
- data/lib/rbi/rbs/type_translator.rb +13 -5
- data/lib/rbi/rbs_printer.rb +9 -4
- data/lib/rbi/rewriters/group_nodes.rb +12 -10
- data/lib/rbi/rewriters/merge_trees.rb +24 -5
- data/lib/rbi/rewriters/nest_non_public_members.rb +22 -13
- data/lib/rbi/rewriters/nest_singleton_methods.rb +15 -7
- data/lib/rbi/rewriters/sort_nodes.rb +18 -21
- data/lib/rbi/rewriters/translate_rbs_sigs.rb +2 -2
- data/lib/rbi/type.rb +4 -4
- data/lib/rbi/version.rb +1 -1
- data/rbi/rbi.rbi +98 -87
- metadata +6 -10
|
@@ -13,19 +13,21 @@ module RBI
|
|
|
13
13
|
|
|
14
14
|
case node
|
|
15
15
|
when Tree
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
node.nodes.dup.each do |child|
|
|
16
|
+
# Single-pass: visit each child, compute its group_kind once, and classify.
|
|
17
|
+
# We avoid calling `child.detach` in a loop (which is O(n) per call due to
|
|
18
|
+
# Array#delete), and instead clear the parent's nodes array in O(1) after
|
|
19
|
+
# all children have been classified.
|
|
20
|
+
groups = {} #: Hash[Group::Kind, Group]
|
|
21
|
+
node.nodes.each do |child|
|
|
23
22
|
visit(child)
|
|
24
|
-
child
|
|
25
|
-
groups[
|
|
23
|
+
kind = group_kind(child)
|
|
24
|
+
group = groups[kind] ||= Group.new(kind)
|
|
25
|
+
child.parent_tree = nil
|
|
26
|
+
group << child
|
|
26
27
|
end
|
|
28
|
+
node.nodes.clear
|
|
27
29
|
|
|
28
|
-
groups.
|
|
30
|
+
groups.each_value { |group| node << group }
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
@@ -464,11 +464,11 @@ module RBI
|
|
|
464
464
|
# @override
|
|
465
465
|
#: (Node other) -> bool
|
|
466
466
|
def compatible_with?(other)
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
467
|
+
other.is_a?(Method) &&
|
|
468
|
+
name == other.name &&
|
|
469
|
+
params == other.params &&
|
|
470
|
+
at_most_one_side_anonymous?(other) &&
|
|
471
|
+
(sigs.empty? || other.sigs.empty? || sigs == other.sigs)
|
|
472
472
|
end
|
|
473
473
|
|
|
474
474
|
# @override
|
|
@@ -477,10 +477,29 @@ module RBI
|
|
|
477
477
|
return unless other.is_a?(Method)
|
|
478
478
|
|
|
479
479
|
super
|
|
480
|
+
|
|
481
|
+
# If self is the all-anonymous side (since compatible_with? ensures
|
|
482
|
+
# at most one side is), or if self has no sigs but other does, adopt
|
|
483
|
+
# other's non-anonymous param names and sigs.
|
|
484
|
+
if params.all?(&:anonymous?) || (sigs.empty? && !other.sigs.empty?)
|
|
485
|
+
@params = other.params.dup
|
|
486
|
+
@sigs = other.sigs.dup unless other.sigs.empty?
|
|
487
|
+
return
|
|
488
|
+
end
|
|
489
|
+
|
|
480
490
|
other.sigs.each do |sig|
|
|
481
491
|
sigs << sig unless sigs.include?(sig)
|
|
482
492
|
end
|
|
483
493
|
end
|
|
494
|
+
|
|
495
|
+
private
|
|
496
|
+
|
|
497
|
+
#: (Method other) -> bool
|
|
498
|
+
def at_most_one_side_anonymous?(other)
|
|
499
|
+
(params.all?(&:anonymous?) && other.params.none?(&:anonymous?)) ||
|
|
500
|
+
(params.none?(&:anonymous?) && other.params.all?(&:anonymous?)) ||
|
|
501
|
+
(params.none?(&:anonymous?) && other.params.none?(&:anonymous?))
|
|
502
|
+
end
|
|
484
503
|
end
|
|
485
504
|
|
|
486
505
|
class Mixin
|
|
@@ -15,24 +15,33 @@ module RBI
|
|
|
15
15
|
protected_group = VisibilityGroup.new(Protected.new)
|
|
16
16
|
private_group = VisibilityGroup.new(Private.new)
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
# Classify children in a single pass, avoiding O(n) Array#delete
|
|
19
|
+
# calls from `detach` in a loop.
|
|
20
|
+
remaining = []
|
|
21
|
+
node.nodes.each do |child|
|
|
19
22
|
visit(child)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
if child.is_a?(Attr) || child.is_a?(Method)
|
|
24
|
+
child.parent_tree = nil
|
|
25
|
+
case child.visibility
|
|
26
|
+
when Protected
|
|
27
|
+
protected_group << child
|
|
28
|
+
when Private
|
|
29
|
+
private_group << child
|
|
30
|
+
else
|
|
31
|
+
public_group << child
|
|
32
|
+
end
|
|
28
33
|
else
|
|
29
|
-
|
|
34
|
+
remaining << child
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
has_groups = !public_group.empty? || !protected_group.empty? || !private_group.empty?
|
|
39
|
+
if has_groups
|
|
40
|
+
node.nodes.replace(remaining)
|
|
41
|
+
node << public_group unless public_group.empty?
|
|
42
|
+
node << protected_group unless protected_group.empty?
|
|
43
|
+
node << private_group unless private_group.empty?
|
|
44
|
+
end
|
|
36
45
|
end
|
|
37
46
|
end
|
|
38
47
|
end
|
|
@@ -13,16 +13,24 @@ module RBI
|
|
|
13
13
|
when Tree
|
|
14
14
|
singleton_class = SingletonClass.new
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# Collect singleton methods and remaining nodes in a single pass,
|
|
17
|
+
# avoiding O(n) Array#delete calls from `detach` in a loop.
|
|
18
|
+
remaining = []
|
|
19
|
+
node.nodes.each do |child|
|
|
17
20
|
visit(child)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
if child.is_a?(Method) && child.is_singleton
|
|
22
|
+
child.parent_tree = nil
|
|
23
|
+
child.is_singleton = false
|
|
24
|
+
singleton_class << child
|
|
25
|
+
else
|
|
26
|
+
remaining << child
|
|
27
|
+
end
|
|
23
28
|
end
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
unless singleton_class.empty?
|
|
31
|
+
node.nodes.replace(remaining)
|
|
32
|
+
node << singleton_class
|
|
33
|
+
end
|
|
26
34
|
end
|
|
27
35
|
end
|
|
28
36
|
end
|
|
@@ -12,32 +12,29 @@ module RBI
|
|
|
12
12
|
return unless node.is_a?(Tree)
|
|
13
13
|
|
|
14
14
|
visit_all(node.nodes)
|
|
15
|
-
original_order = node.nodes.map.with_index.to_h
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# nodes into chunks based on whether any Visibility nodes appear, and sort the chunks independently. This
|
|
20
|
-
# applies the ordering rules from the node_rank method as much as possible, while preserving visibility.
|
|
21
|
-
sorted_nodes = node.nodes.chunk do |n|
|
|
22
|
-
n.is_a?(Visibility)
|
|
23
|
-
end.flat_map do |_, nodes|
|
|
24
|
-
nodes.sort! do |a, b|
|
|
25
|
-
# First we try to compare the nodes by their node rank (based on the node type)
|
|
26
|
-
res = node_rank(a) <=> node_rank(b)
|
|
27
|
-
next res if res != 0 # we can sort the nodes by their rank, let's stop here
|
|
16
|
+
nodes = node.nodes
|
|
17
|
+
return if nodes.size <= 1
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
# Fast path: if no Visibility nodes are present (common after group_nodes!/nest_non_public_members!),
|
|
20
|
+
# skip the chunk and sort directly.
|
|
21
|
+
has_visibility = nodes.any?(Visibility)
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
if has_visibility
|
|
24
|
+
# The child nodes contain private/protected markers. Divide into chunks
|
|
25
|
+
# and sort each chunk independently to preserve visibility semantics.
|
|
26
|
+
sorted_nodes = nodes.chunk { |n| n.is_a?(Visibility) }.flat_map do |_, chunk_nodes|
|
|
27
|
+
chunk_nodes.sort_by!.with_index do |n, i|
|
|
28
|
+
[node_rank(n), node_name(n) || "", i]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
nodes.replace(sorted_nodes)
|
|
32
|
+
else
|
|
33
|
+
# No visibility nodes — sort in place with Schwartzian transform.
|
|
34
|
+
nodes.sort_by!.with_index do |n, i|
|
|
35
|
+
[node_rank(n), node_name(n) || "", i]
|
|
37
36
|
end
|
|
38
37
|
end
|
|
39
|
-
|
|
40
|
-
node.nodes.replace(sorted_nodes)
|
|
41
38
|
end
|
|
42
39
|
|
|
43
40
|
private
|
|
@@ -51,7 +51,7 @@ module RBI
|
|
|
51
51
|
|
|
52
52
|
#: (Method, RBSComment) -> Sig
|
|
53
53
|
def translate_rbs_method_type(node, comment)
|
|
54
|
-
method_type = ::RBS::Parser.parse_method_type(comment.text)
|
|
54
|
+
method_type = ::RBS::Parser.parse_method_type(comment.text, require_eof: true)
|
|
55
55
|
translator = RBS::MethodTypeTranslator.new(node)
|
|
56
56
|
translator.visit(method_type)
|
|
57
57
|
translator.result
|
|
@@ -59,7 +59,7 @@ module RBI
|
|
|
59
59
|
|
|
60
60
|
#: (Attr, RBSComment) -> Sig
|
|
61
61
|
def translate_rbs_attr_type(node, comment)
|
|
62
|
-
attr_type = ::RBS::Parser.parse_type(comment.text)
|
|
62
|
+
attr_type = ::RBS::Parser.parse_type(comment.text, require_eof: true)
|
|
63
63
|
sig = Sig.new
|
|
64
64
|
|
|
65
65
|
if node.is_a?(AttrWriter)
|
data/lib/rbi/type.rb
CHANGED
|
@@ -112,7 +112,7 @@ module RBI
|
|
|
112
112
|
# @override
|
|
113
113
|
#: -> String
|
|
114
114
|
def to_rbi
|
|
115
|
-
"T::Boolean"
|
|
115
|
+
"::T::Boolean"
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
# @override
|
|
@@ -258,7 +258,7 @@ module RBI
|
|
|
258
258
|
# @override
|
|
259
259
|
#: -> String
|
|
260
260
|
def to_rbi
|
|
261
|
-
"T::Class[#{@type}]"
|
|
261
|
+
"::T::Class[#{@type}]"
|
|
262
262
|
end
|
|
263
263
|
|
|
264
264
|
# @override
|
|
@@ -294,7 +294,7 @@ module RBI
|
|
|
294
294
|
# @override
|
|
295
295
|
#: -> String
|
|
296
296
|
def to_rbi
|
|
297
|
-
"T::Module[#{@type}]"
|
|
297
|
+
"::T::Module[#{@type}]"
|
|
298
298
|
end
|
|
299
299
|
|
|
300
300
|
# @override
|
|
@@ -498,7 +498,7 @@ module RBI
|
|
|
498
498
|
return type.simplify unless type.is_a?(Any)
|
|
499
499
|
|
|
500
500
|
types = type.types.map(&:simplify)
|
|
501
|
-
return Untyped.new if types.any?
|
|
501
|
+
return Untyped.new if types.any?(Untyped)
|
|
502
502
|
|
|
503
503
|
has_true_class = types.any? { |type| type.is_a?(Simple) && type.name == "TrueClass" }
|
|
504
504
|
has_false_class = types.any? { |type| type.is_a?(Simple) && type.name == "FalseClass" }
|
data/lib/rbi/version.rb
CHANGED