rbi 0.3.8 → 0.3.10
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/README.md +18 -2
- data/lib/rbi/model.rb +208 -162
- 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 +8 -3
- data/lib/rbi/rewriters/group_nodes.rb +12 -10
- data/lib/rbi/rewriters/merge_trees.rb +35 -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/version.rb +1 -1
- data/rbi/rbi.rbi +98 -77
- 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
|
|
|
@@ -136,6 +136,17 @@ module RBI
|
|
|
136
136
|
make_conflict_scope(prev, node)
|
|
137
137
|
end
|
|
138
138
|
@scope_stack << prev
|
|
139
|
+
elsif prev
|
|
140
|
+
# prev exists but is not a Scope (e.g., a Const)
|
|
141
|
+
# This is a conflict between different node types
|
|
142
|
+
if @keep == Keep::LEFT
|
|
143
|
+
# do nothing, keep the existing non-scope
|
|
144
|
+
elsif @keep == Keep::RIGHT
|
|
145
|
+
prev.replace(node.dup)
|
|
146
|
+
else
|
|
147
|
+
make_conflict_tree(prev, node)
|
|
148
|
+
end
|
|
149
|
+
return # Don't visit children, the whole scope is in conflict
|
|
139
150
|
else
|
|
140
151
|
copy = node.dup_empty
|
|
141
152
|
current_scope << copy
|
|
@@ -265,6 +276,8 @@ module RBI
|
|
|
265
276
|
else
|
|
266
277
|
last_conflict_tree = node
|
|
267
278
|
end
|
|
279
|
+
else
|
|
280
|
+
last_conflict_tree = nil
|
|
268
281
|
end
|
|
269
282
|
|
|
270
283
|
visit(node)
|
|
@@ -451,11 +464,11 @@ module RBI
|
|
|
451
464
|
# @override
|
|
452
465
|
#: (Node other) -> bool
|
|
453
466
|
def compatible_with?(other)
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
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)
|
|
459
472
|
end
|
|
460
473
|
|
|
461
474
|
# @override
|
|
@@ -464,10 +477,27 @@ module RBI
|
|
|
464
477
|
return unless other.is_a?(Method)
|
|
465
478
|
|
|
466
479
|
super
|
|
480
|
+
|
|
481
|
+
# If self is the all-anonymous side (since compatible_with? ensures
|
|
482
|
+
# at most one side is), adopt other's non-anonymous param names and sigs.
|
|
483
|
+
if params.all?(&:anonymous?)
|
|
484
|
+
@params = other.params.dup
|
|
485
|
+
@sigs = other.sigs.dup unless other.sigs.empty?
|
|
486
|
+
end
|
|
487
|
+
|
|
467
488
|
other.sigs.each do |sig|
|
|
468
489
|
sigs << sig unless sigs.include?(sig)
|
|
469
490
|
end
|
|
470
491
|
end
|
|
492
|
+
|
|
493
|
+
private
|
|
494
|
+
|
|
495
|
+
#: (Method other) -> bool
|
|
496
|
+
def at_most_one_side_anonymous?(other)
|
|
497
|
+
(params.all?(&:anonymous?) && other.params.none?(&:anonymous?)) ||
|
|
498
|
+
(params.none?(&:anonymous?) && other.params.all?(&:anonymous?)) ||
|
|
499
|
+
(params.none?(&:anonymous?) && other.params.none?(&:anonymous?))
|
|
500
|
+
end
|
|
471
501
|
end
|
|
472
502
|
|
|
473
503
|
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? { |n| n.is_a?(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/version.rb
CHANGED