rbi 0.0.7 → 0.0.8
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 +1 -0
- data/lib/rbi/index.rb +22 -5
- data/lib/rbi/model.rb +100 -0
- data/lib/rbi/parser.rb +100 -47
- data/lib/rbi/printer.rb +41 -0
- data/lib/rbi/rewriters/group_nodes.rb +6 -0
- data/lib/rbi/rewriters/merge_trees.rb +9 -0
- data/lib/rbi/rewriters/remove_known_definitions.rb +125 -0
- data/lib/rbi/rewriters/sort_nodes.rb +25 -15
- data/lib/rbi/version.rb +1 -1
- data/lib/rbi.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37be6daaf86810c60a865b98ac94ff089184e990e168bc405a0d167c641477ed
|
4
|
+
data.tar.gz: 95de3a3ffb035c40d9dd8da3055d808b1b0ae365add26bbc0754ae997c1c09c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b794985ed143c257080ed69ab6ac8458e0cfcad5e988bfe412566dd2146ea009a8ceabfb274759089e3a687eb42e15b27c31a884c04e78a6b413b424d97d0b1
|
7
|
+
data.tar.gz: bc41f792fd147ceb04dee6852e046a68e5f90f886ce4b2937ceaa642ef4d9d46996f1560067177acfedc52b73b60878aeb03cd64deda17be516d04516e37ed63
|
data/Gemfile
CHANGED
data/lib/rbi/index.rb
CHANGED
@@ -29,9 +29,9 @@ module RBI
|
|
29
29
|
@index[id] ||= []
|
30
30
|
end
|
31
31
|
|
32
|
-
sig { params(
|
33
|
-
def index(
|
34
|
-
|
32
|
+
sig { params(nodes: Node).void }
|
33
|
+
def index(*nodes)
|
34
|
+
nodes.each { |node| visit(node) }
|
35
35
|
end
|
36
36
|
|
37
37
|
sig { override.params(node: T.nilable(Node)).void }
|
@@ -40,14 +40,21 @@ module RBI
|
|
40
40
|
|
41
41
|
case node
|
42
42
|
when Scope
|
43
|
-
|
43
|
+
index_node(node)
|
44
44
|
visit_all(node.nodes)
|
45
45
|
when Tree
|
46
46
|
visit_all(node.nodes)
|
47
47
|
when Indexable
|
48
|
-
|
48
|
+
index_node(node)
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
sig { params(node: T.all(Indexable, Node)).void }
|
55
|
+
def index_node(node)
|
56
|
+
node.index_ids.each { |id| self[id] << node }
|
57
|
+
end
|
51
58
|
end
|
52
59
|
|
53
60
|
class Tree
|
@@ -154,6 +161,16 @@ module RBI
|
|
154
161
|
end
|
155
162
|
end
|
156
163
|
|
164
|
+
class Send
|
165
|
+
extend T::Sig
|
166
|
+
include Indexable
|
167
|
+
|
168
|
+
sig { override.returns(T::Array[String]) }
|
169
|
+
def index_ids
|
170
|
+
["#{parent_scope&.fully_qualified_name}.#{method}"]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
157
174
|
class TStructConst
|
158
175
|
extend T::Sig
|
159
176
|
include Indexable
|
data/lib/rbi/model.rb
CHANGED
@@ -914,6 +914,106 @@ module RBI
|
|
914
914
|
end
|
915
915
|
end
|
916
916
|
|
917
|
+
# Sends
|
918
|
+
|
919
|
+
class Send < NodeWithComments
|
920
|
+
extend T::Sig
|
921
|
+
|
922
|
+
sig { returns(String) }
|
923
|
+
attr_reader :method
|
924
|
+
|
925
|
+
sig { returns(T::Array[Arg]) }
|
926
|
+
attr_reader :args
|
927
|
+
|
928
|
+
sig do
|
929
|
+
params(
|
930
|
+
method: String,
|
931
|
+
args: T::Array[Arg],
|
932
|
+
loc: T.nilable(Loc),
|
933
|
+
comments: T::Array[Comment],
|
934
|
+
block: T.nilable(T.proc.params(node: Send).void)
|
935
|
+
).void
|
936
|
+
end
|
937
|
+
def initialize(method, args = [], loc: nil, comments: [], &block)
|
938
|
+
super(loc: loc, comments: comments)
|
939
|
+
@method = method
|
940
|
+
@args = args
|
941
|
+
block&.call(self)
|
942
|
+
end
|
943
|
+
|
944
|
+
sig { params(arg: Arg).void }
|
945
|
+
def <<(arg)
|
946
|
+
@args << arg
|
947
|
+
end
|
948
|
+
|
949
|
+
sig { params(other: T.nilable(Object)).returns(T::Boolean) }
|
950
|
+
def ==(other)
|
951
|
+
Send === other && method == other.method && args == other.args
|
952
|
+
end
|
953
|
+
|
954
|
+
sig { returns(String) }
|
955
|
+
def to_s
|
956
|
+
"#{parent_scope&.fully_qualified_name}.#{method}(#{args.join(", ")})"
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
class Arg < Node
|
961
|
+
extend T::Sig
|
962
|
+
|
963
|
+
sig { returns(String) }
|
964
|
+
attr_reader :value
|
965
|
+
|
966
|
+
sig do
|
967
|
+
params(
|
968
|
+
value: String,
|
969
|
+
loc: T.nilable(Loc)
|
970
|
+
).void
|
971
|
+
end
|
972
|
+
def initialize(value, loc: nil)
|
973
|
+
super(loc: loc)
|
974
|
+
@value = value
|
975
|
+
end
|
976
|
+
|
977
|
+
sig { params(other: T.nilable(Object)).returns(T::Boolean) }
|
978
|
+
def ==(other)
|
979
|
+
Arg === other && value == other.value
|
980
|
+
end
|
981
|
+
|
982
|
+
sig { returns(String) }
|
983
|
+
def to_s
|
984
|
+
value
|
985
|
+
end
|
986
|
+
end
|
987
|
+
|
988
|
+
class KwArg < Arg
|
989
|
+
extend T::Sig
|
990
|
+
|
991
|
+
sig { returns(String) }
|
992
|
+
attr_reader :keyword
|
993
|
+
|
994
|
+
sig do
|
995
|
+
params(
|
996
|
+
keyword: String,
|
997
|
+
value: String,
|
998
|
+
loc: T.nilable(Loc)
|
999
|
+
).void
|
1000
|
+
end
|
1001
|
+
def initialize(keyword, value, loc: nil)
|
1002
|
+
super(value, loc: loc)
|
1003
|
+
@keyword = keyword
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
sig { params(other: T.nilable(Object)).returns(T::Boolean) }
|
1007
|
+
def ==(other)
|
1008
|
+
KwArg === other && value == other.value && keyword == other.keyword
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
sig { returns(String) }
|
1012
|
+
def to_s
|
1013
|
+
"#{keyword}: #{value}"
|
1014
|
+
end
|
1015
|
+
end
|
1016
|
+
|
917
1017
|
# Sorbet's sigs
|
918
1018
|
|
919
1019
|
class Sig < Node
|
data/lib/rbi/parser.rb
CHANGED
@@ -43,11 +43,23 @@ module RBI
|
|
43
43
|
Parser.new.parse_file(path)
|
44
44
|
end
|
45
45
|
|
46
|
+
sig { params(paths: T::Array[String]).returns(T::Array[Tree]) }
|
47
|
+
def self.parse_files(paths)
|
48
|
+
parser = Parser.new
|
49
|
+
paths.map { |path| parser.parse_file(path) }
|
50
|
+
end
|
51
|
+
|
46
52
|
sig { params(string: String).returns(Tree) }
|
47
53
|
def parse_string(string)
|
48
54
|
parse(string, file: "-")
|
49
55
|
end
|
50
56
|
|
57
|
+
sig { params(strings: T::Array[String]).returns(T::Array[Tree]) }
|
58
|
+
def self.parse_strings(strings)
|
59
|
+
parser = Parser.new
|
60
|
+
strings.map { |string| parser.parse_string(string) }
|
61
|
+
end
|
62
|
+
|
51
63
|
sig { params(path: String).returns(Tree) }
|
52
64
|
def parse_file(path)
|
53
65
|
parse(::File.read(path), file: path)
|
@@ -59,10 +71,9 @@ module RBI
|
|
59
71
|
def parse(content, file:)
|
60
72
|
node, comments = Unparser.parse_with_comments(content)
|
61
73
|
assoc = ::Parser::Source::Comment.associate_locations(node, comments)
|
62
|
-
builder = TreeBuilder.new(file: file, comments: assoc)
|
63
|
-
builder.separate_header_comments
|
74
|
+
builder = TreeBuilder.new(file: file, comments: comments, nodes_comments_assoc: assoc)
|
64
75
|
builder.visit(node)
|
65
|
-
builder.
|
76
|
+
builder.post_process
|
66
77
|
builder.tree
|
67
78
|
rescue ::Parser::SyntaxError => e
|
68
79
|
raise ParseError.new(e.message, Loc.from_ast_loc(file, e.diagnostic.location))
|
@@ -105,16 +116,26 @@ module RBI
|
|
105
116
|
sig do
|
106
117
|
params(
|
107
118
|
file: String,
|
108
|
-
comments: T::
|
119
|
+
comments: T::Array[::Parser::Source::Comment],
|
120
|
+
nodes_comments_assoc: T::Hash[::Parser::Source::Map, T::Array[::Parser::Source::Comment]]
|
109
121
|
).void
|
110
122
|
end
|
111
|
-
def initialize(file:, comments: {})
|
123
|
+
def initialize(file:, comments: [], nodes_comments_assoc: {})
|
112
124
|
super()
|
113
125
|
@file = file
|
114
126
|
@comments = comments
|
127
|
+
@nodes_comments_assoc = nodes_comments_assoc
|
115
128
|
@tree = T.let(Tree.new, Tree)
|
116
129
|
@scopes_stack = T.let([@tree], T::Array[Tree])
|
117
130
|
@last_sigs = T.let([], T::Array[RBI::Sig])
|
131
|
+
|
132
|
+
separate_header_comments
|
133
|
+
end
|
134
|
+
|
135
|
+
sig { void }
|
136
|
+
def post_process
|
137
|
+
assoc_dangling_comments
|
138
|
+
set_root_tree_loc
|
118
139
|
end
|
119
140
|
|
120
141
|
sig { override.params(node: T.nilable(Object)).void }
|
@@ -146,46 +167,6 @@ module RBI
|
|
146
167
|
end
|
147
168
|
end
|
148
169
|
|
149
|
-
sig { void }
|
150
|
-
def separate_header_comments
|
151
|
-
return if @comments.empty?
|
152
|
-
|
153
|
-
keep = []
|
154
|
-
node = T.must(@comments.keys.first)
|
155
|
-
comments = T.must(@comments.values.first)
|
156
|
-
|
157
|
-
last_line = T.let(nil, T.nilable(Integer))
|
158
|
-
comments.reverse.each do |comment|
|
159
|
-
comment_line = comment.location.last_line
|
160
|
-
|
161
|
-
break if last_line && comment_line < last_line - 1 ||
|
162
|
-
!last_line && comment_line < node.first_line - 1
|
163
|
-
|
164
|
-
keep << comment
|
165
|
-
last_line = comment_line
|
166
|
-
end
|
167
|
-
|
168
|
-
@comments[node] = keep.reverse
|
169
|
-
end
|
170
|
-
|
171
|
-
sig { params(comments: T::Array[::Parser::Source::Comment]).void }
|
172
|
-
def assoc_dangling_comments(comments)
|
173
|
-
last_line = T.let(nil, T.nilable(Integer))
|
174
|
-
(comments - @comments.values.flatten).each do |comment|
|
175
|
-
comment_line = comment.location.last_line
|
176
|
-
text = comment.text[1..-1].strip
|
177
|
-
loc = Loc.from_ast_loc(@file, comment.location)
|
178
|
-
|
179
|
-
if last_line && comment_line > last_line + 1
|
180
|
-
# Preserve empty lines in file headers
|
181
|
-
tree.comments << BlankLine.new(loc: loc)
|
182
|
-
end
|
183
|
-
|
184
|
-
tree.comments << Comment.new(text, loc: loc)
|
185
|
-
last_line = comment_line
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
170
|
private
|
190
171
|
|
191
172
|
sig { params(node: AST::Node).returns(Scope) }
|
@@ -332,10 +313,28 @@ module RBI
|
|
332
313
|
name, type, default_value = parse_tstruct_prop(node)
|
333
314
|
TStructConst.new(name, type, default: default_value, loc: loc, comments: comments)
|
334
315
|
else
|
335
|
-
|
316
|
+
args = parse_send_args(node)
|
317
|
+
Send.new(method_name.to_s, args, loc: loc, comments: comments)
|
336
318
|
end
|
337
319
|
end
|
338
320
|
|
321
|
+
sig { params(node: AST::Node).returns(T::Array[Arg]) }
|
322
|
+
def parse_send_args(node)
|
323
|
+
args = T.let([], T::Array[Arg])
|
324
|
+
node.children[2..-1].each do |child|
|
325
|
+
if child.type == :kwargs
|
326
|
+
child.children.each do |pair|
|
327
|
+
keyword = pair.children.first.children.last.to_s
|
328
|
+
value = parse_expr(pair.children.last)
|
329
|
+
args << KwArg.new(keyword, value)
|
330
|
+
end
|
331
|
+
else
|
332
|
+
args << Arg.new(parse_expr(child))
|
333
|
+
end
|
334
|
+
end
|
335
|
+
args
|
336
|
+
end
|
337
|
+
|
339
338
|
sig { params(node: AST::Node).returns(T.nilable(RBI::Node)) }
|
340
339
|
def parse_block(node)
|
341
340
|
name = node.children[0].children[1]
|
@@ -435,7 +434,7 @@ module RBI
|
|
435
434
|
|
436
435
|
sig { params(node: AST::Node).returns(T::Array[Comment]) }
|
437
436
|
def node_comments(node)
|
438
|
-
comments = @
|
437
|
+
comments = @nodes_comments_assoc[node.location]
|
439
438
|
return [] unless comments
|
440
439
|
comments.map do |comment|
|
441
440
|
text = comment.text[1..-1].strip
|
@@ -455,6 +454,60 @@ module RBI
|
|
455
454
|
@last_sigs.clear
|
456
455
|
sigs
|
457
456
|
end
|
457
|
+
|
458
|
+
sig { void }
|
459
|
+
def assoc_dangling_comments
|
460
|
+
last_line = T.let(nil, T.nilable(Integer))
|
461
|
+
(@comments - @nodes_comments_assoc.values.flatten).each do |comment|
|
462
|
+
comment_line = comment.location.last_line
|
463
|
+
text = comment.text[1..-1].strip
|
464
|
+
loc = Loc.from_ast_loc(@file, comment.location)
|
465
|
+
|
466
|
+
if last_line && comment_line > last_line + 1
|
467
|
+
# Preserve empty lines in file headers
|
468
|
+
tree.comments << BlankLine.new(loc: loc)
|
469
|
+
end
|
470
|
+
|
471
|
+
tree.comments << Comment.new(text, loc: loc)
|
472
|
+
last_line = comment_line
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
sig { void }
|
477
|
+
def separate_header_comments
|
478
|
+
return if @nodes_comments_assoc.empty?
|
479
|
+
|
480
|
+
keep = []
|
481
|
+
node = T.must(@nodes_comments_assoc.keys.first)
|
482
|
+
comments = T.must(@nodes_comments_assoc.values.first)
|
483
|
+
|
484
|
+
last_line = T.let(nil, T.nilable(Integer))
|
485
|
+
comments.reverse.each do |comment|
|
486
|
+
comment_line = comment.location.last_line
|
487
|
+
|
488
|
+
break if last_line && comment_line < last_line - 1 ||
|
489
|
+
!last_line && comment_line < node.first_line - 1
|
490
|
+
|
491
|
+
keep << comment
|
492
|
+
last_line = comment_line
|
493
|
+
end
|
494
|
+
|
495
|
+
@nodes_comments_assoc[node] = keep.reverse
|
496
|
+
end
|
497
|
+
|
498
|
+
sig { void }
|
499
|
+
def set_root_tree_loc
|
500
|
+
first_loc = tree.nodes.first&.loc
|
501
|
+
last_loc = tree.nodes.last&.loc
|
502
|
+
|
503
|
+
@tree.loc = Loc.new(
|
504
|
+
file: @file,
|
505
|
+
begin_line: first_loc&.begin_line || 0,
|
506
|
+
begin_column: first_loc&.begin_column || 0,
|
507
|
+
end_line: last_loc&.end_line || 0,
|
508
|
+
end_column: last_loc&.end_column || 0
|
509
|
+
)
|
510
|
+
end
|
458
511
|
end
|
459
512
|
|
460
513
|
class ConstBuilder < ASTVisitor
|
data/lib/rbi/printer.rb
CHANGED
@@ -555,6 +555,47 @@ module RBI
|
|
555
555
|
end
|
556
556
|
end
|
557
557
|
|
558
|
+
class Send
|
559
|
+
extend T::Sig
|
560
|
+
|
561
|
+
sig { override.params(v: Printer).void }
|
562
|
+
def accept_printer(v)
|
563
|
+
print_blank_line_before(v)
|
564
|
+
|
565
|
+
v.printl("# #{loc}") if loc && v.print_locs
|
566
|
+
v.visit_all(comments)
|
567
|
+
v.printt(method)
|
568
|
+
unless args.empty?
|
569
|
+
v.print(" ")
|
570
|
+
args.each_with_index do |arg, index|
|
571
|
+
v.visit(arg)
|
572
|
+
v.print(", ") if index < args.size - 1
|
573
|
+
end
|
574
|
+
end
|
575
|
+
v.printn
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
class Arg
|
580
|
+
extend T::Sig
|
581
|
+
|
582
|
+
sig { override.params(v: Printer).void }
|
583
|
+
def accept_printer(v)
|
584
|
+
v.print(value)
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
class KwArg
|
589
|
+
extend T::Sig
|
590
|
+
|
591
|
+
sig { override.params(v: Printer).void }
|
592
|
+
def accept_printer(v)
|
593
|
+
v.print(keyword)
|
594
|
+
v.print(": ")
|
595
|
+
v.print(value)
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
558
599
|
class Sig
|
559
600
|
extend T::Sig
|
560
601
|
|
@@ -55,6 +55,8 @@ module RBI
|
|
55
55
|
Group::Kind::TypeMembers
|
56
56
|
when MixesInClassMethods
|
57
57
|
Group::Kind::MixesInClassMethods
|
58
|
+
when Send
|
59
|
+
Group::Kind::Sends
|
58
60
|
when TStructField
|
59
61
|
Group::Kind::TStructFields
|
60
62
|
when TEnumBlock
|
@@ -67,6 +69,8 @@ module RBI
|
|
67
69
|
else
|
68
70
|
Group::Kind::Methods
|
69
71
|
end
|
72
|
+
when SingletonClass
|
73
|
+
Group::Kind::SingletonClasses
|
70
74
|
when Scope, Const
|
71
75
|
Group::Kind::Consts
|
72
76
|
else
|
@@ -93,10 +97,12 @@ module RBI
|
|
93
97
|
Helpers = new
|
94
98
|
TypeMembers = new
|
95
99
|
MixesInClassMethods = new
|
100
|
+
Sends = new
|
96
101
|
TStructFields = new
|
97
102
|
TEnums = new
|
98
103
|
Inits = new
|
99
104
|
Methods = new
|
105
|
+
SingletonClasses = new
|
100
106
|
Consts = new
|
101
107
|
end
|
102
108
|
end
|
@@ -512,6 +512,15 @@ module RBI
|
|
512
512
|
end
|
513
513
|
end
|
514
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
|
+
|
515
524
|
class TStructField
|
516
525
|
extend T::Sig
|
517
526
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RBI
|
5
|
+
module Rewriters
|
6
|
+
# Remove all definitions existing in the index from the current tree
|
7
|
+
#
|
8
|
+
# Let's create an `Index` from two different `Tree`s:
|
9
|
+
# ~~~rb
|
10
|
+
# tree1 = Parse.parse_string(<<~RBI)
|
11
|
+
# class Foo
|
12
|
+
# def foo; end
|
13
|
+
# end
|
14
|
+
# RBI
|
15
|
+
#
|
16
|
+
# tree2 = Parse.parse_string(<<~RBI)
|
17
|
+
# FOO = 10
|
18
|
+
# RBI
|
19
|
+
#
|
20
|
+
# index = Index.index(tree1, tree2)
|
21
|
+
# ~~~
|
22
|
+
#
|
23
|
+
# We can use `RemoveKnownDefinitions` to remove the definitions found in the `index` from the `Tree` to clean:
|
24
|
+
# ~~~rb
|
25
|
+
# tree_to_clean = Parser.parse_string(<<~RBI)
|
26
|
+
# class Foo
|
27
|
+
# def foo; end
|
28
|
+
# def bar; end
|
29
|
+
# end
|
30
|
+
# FOO = 10
|
31
|
+
# BAR = 42
|
32
|
+
# RBI
|
33
|
+
#
|
34
|
+
# cleaned_tree, operations = RemoveKnownDefinitions.remove(tree_to_clean, index)
|
35
|
+
#
|
36
|
+
# assert_equal(<<~RBI, cleaned_tree)
|
37
|
+
# class Foo
|
38
|
+
# def bar; end
|
39
|
+
# end
|
40
|
+
# BAR = 42
|
41
|
+
# RBI
|
42
|
+
#
|
43
|
+
# assert_equal(<<~OPERATIONS, operations.join("\n"))
|
44
|
+
# Deleted ::Foo#foo at -:2:2-2-16 (duplicate from -:2:2-2:16)
|
45
|
+
# Deleted ::FOO at -:5:0-5:8 (duplicate from -:1:0-1:8)
|
46
|
+
# OPERATIONS
|
47
|
+
# ~~~
|
48
|
+
class RemoveKnownDefinitions < Visitor
|
49
|
+
extend T::Sig
|
50
|
+
|
51
|
+
sig do
|
52
|
+
params(
|
53
|
+
tree: RBI::Tree,
|
54
|
+
index: RBI::Index
|
55
|
+
).returns([RBI::Tree, T::Array[Operation]])
|
56
|
+
end
|
57
|
+
def self.remove(tree, index)
|
58
|
+
v = RemoveKnownDefinitions.new(index)
|
59
|
+
v.visit(tree)
|
60
|
+
[tree, v.operations]
|
61
|
+
end
|
62
|
+
|
63
|
+
sig { returns(T::Array[Operation]) }
|
64
|
+
attr_reader :operations
|
65
|
+
|
66
|
+
sig { params(index: RBI::Index).void }
|
67
|
+
def initialize(index)
|
68
|
+
super()
|
69
|
+
@index = index
|
70
|
+
@operations = T.let([], T::Array[Operation])
|
71
|
+
end
|
72
|
+
|
73
|
+
sig { params(nodes: T::Array[RBI::Node]).void }
|
74
|
+
def visit_all(nodes)
|
75
|
+
nodes.dup.each { |node| visit(node) }
|
76
|
+
end
|
77
|
+
|
78
|
+
sig { override.params(node: T.nilable(RBI::Node)).void }
|
79
|
+
def visit(node)
|
80
|
+
return unless node
|
81
|
+
|
82
|
+
case node
|
83
|
+
when RBI::Scope
|
84
|
+
visit_all(node.nodes)
|
85
|
+
previous = previous_definition_for(node)
|
86
|
+
delete_node(node, previous) if previous && node.empty?
|
87
|
+
when RBI::Tree
|
88
|
+
visit_all(node.nodes)
|
89
|
+
when RBI::Indexable
|
90
|
+
previous = previous_definition_for(node)
|
91
|
+
delete_node(node, previous) if previous
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
sig { params(node: RBI::Indexable).returns(T.nilable(RBI::Node)) }
|
98
|
+
def previous_definition_for(node)
|
99
|
+
node.index_ids.each do |id|
|
100
|
+
previous = @index[id].first
|
101
|
+
return previous if previous
|
102
|
+
end
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
sig { params(node: RBI::Node, previous: RBI::Node).void }
|
107
|
+
def delete_node(node, previous)
|
108
|
+
node.detach
|
109
|
+
@operations << Operation.new(deleted_node: node, duplicate_of: previous)
|
110
|
+
end
|
111
|
+
|
112
|
+
class Operation < T::Struct
|
113
|
+
extend T::Sig
|
114
|
+
|
115
|
+
const :deleted_node, RBI::Node
|
116
|
+
const :duplicate_of, RBI::Node
|
117
|
+
|
118
|
+
sig { returns(String) }
|
119
|
+
def to_s
|
120
|
+
"Deleted #{duplicate_of} at #{deleted_node.loc} (duplicate from #{duplicate_of.loc})"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -12,10 +12,16 @@ module RBI
|
|
12
12
|
visit_all(node.nodes)
|
13
13
|
original_order = node.nodes.map.with_index.to_h
|
14
14
|
node.nodes.sort! do |a, b|
|
15
|
+
# First we try to compare the nodes by their node rank (based on the node type)
|
15
16
|
res = node_rank(a) <=> node_rank(b)
|
16
|
-
res
|
17
|
-
|
18
|
-
res
|
17
|
+
next res if res != 0 # we can sort the nodes by their rank, let's stop here
|
18
|
+
|
19
|
+
# Then, if the nodes ranks are the same (res == 0), we try to compare the nodes by their name
|
20
|
+
res = node_name(a) <=> node_name(b)
|
21
|
+
next res if res && res != 0 # we can sort the nodes by their name, let's stop here
|
22
|
+
|
23
|
+
# Finally, if the two nodes have the same rank and the same name or at least one node is anonymous then,
|
24
|
+
T.must(original_order[a]) <=> T.must(original_order[b]) # we keep the original order
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
@@ -29,19 +35,21 @@ module RBI
|
|
29
35
|
when Helper then 20
|
30
36
|
when TypeMember then 30
|
31
37
|
when MixesInClassMethods then 40
|
32
|
-
when
|
33
|
-
when
|
38
|
+
when Send then 50
|
39
|
+
when TStructField then 60
|
40
|
+
when TEnumBlock then 70
|
34
41
|
when Method
|
35
42
|
if node.name == "initialize"
|
36
|
-
|
43
|
+
81
|
37
44
|
elsif !node.is_singleton
|
38
|
-
|
45
|
+
82
|
39
46
|
else
|
40
|
-
|
47
|
+
83
|
41
48
|
end
|
42
|
-
when
|
49
|
+
when SingletonClass then 90
|
50
|
+
when Scope, Const then 100
|
43
51
|
else
|
44
|
-
|
52
|
+
110
|
45
53
|
end
|
46
54
|
end
|
47
55
|
|
@@ -52,11 +60,13 @@ module RBI
|
|
52
60
|
when Group::Kind::Helpers then 1
|
53
61
|
when Group::Kind::TypeMembers then 2
|
54
62
|
when Group::Kind::MixesInClassMethods then 3
|
55
|
-
when Group::Kind::
|
56
|
-
when Group::Kind::
|
57
|
-
when Group::Kind::
|
58
|
-
when Group::Kind::
|
59
|
-
when Group::Kind::
|
63
|
+
when Group::Kind::Sends then 5
|
64
|
+
when Group::Kind::TStructFields then 6
|
65
|
+
when Group::Kind::TEnums then 7
|
66
|
+
when Group::Kind::Inits then 8
|
67
|
+
when Group::Kind::Methods then 9
|
68
|
+
when Group::Kind::SingletonClasses then 10
|
69
|
+
when Group::Kind::Consts then 11
|
60
70
|
else
|
61
71
|
T.absurd(kind)
|
62
72
|
end
|
data/lib/rbi/version.rb
CHANGED
data/lib/rbi.rb
CHANGED
@@ -19,6 +19,7 @@ require "rbi/rewriters/merge_trees"
|
|
19
19
|
require "rbi/rewriters/nest_singleton_methods"
|
20
20
|
require "rbi/rewriters/nest_non_public_methods"
|
21
21
|
require "rbi/rewriters/group_nodes"
|
22
|
+
require "rbi/rewriters/remove_known_definitions"
|
22
23
|
require "rbi/rewriters/sort_nodes"
|
23
24
|
require "rbi/parser"
|
24
25
|
require "rbi/printer"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandre Terrasa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/rbi/rewriters/merge_trees.rb
|
90
90
|
- lib/rbi/rewriters/nest_non_public_methods.rb
|
91
91
|
- lib/rbi/rewriters/nest_singleton_methods.rb
|
92
|
+
- lib/rbi/rewriters/remove_known_definitions.rb
|
92
93
|
- lib/rbi/rewriters/sort_nodes.rb
|
93
94
|
- lib/rbi/version.rb
|
94
95
|
- lib/rbi/visitor.rb
|