rbi 0.3.9 → 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/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 +22 -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
|
|
|
@@ -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,27 @@ 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), 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
|
+
|
|
480
488
|
other.sigs.each do |sig|
|
|
481
489
|
sigs << sig unless sigs.include?(sig)
|
|
482
490
|
end
|
|
483
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
|
|
484
501
|
end
|
|
485
502
|
|
|
486
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