rbi 0.0.17 → 0.1.1
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 -1
- data/lib/rbi/loc.rb +20 -1
- data/lib/rbi/model.rb +2 -2
- data/lib/rbi/parser.rb +599 -545
- data/lib/rbi/version.rb +1 -1
- metadata +7 -35
data/lib/rbi/parser.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "
|
4
|
+
require "yarp"
|
5
5
|
|
6
6
|
module RBI
|
7
7
|
class ParseError < StandardError
|
@@ -53,19 +53,6 @@ module RBI
|
|
53
53
|
class Parser
|
54
54
|
extend T::Sig
|
55
55
|
|
56
|
-
# opt-in to most recent AST format
|
57
|
-
::Parser::Builders::Default.emit_lambda = true
|
58
|
-
::Parser::Builders::Default.emit_procarg0 = true
|
59
|
-
::Parser::Builders::Default.emit_encoding = true
|
60
|
-
::Parser::Builders::Default.emit_index = true
|
61
|
-
::Parser::Builders::Default.emit_arg_inside_procarg0 = true
|
62
|
-
|
63
|
-
sig { void }
|
64
|
-
def initialize
|
65
|
-
# Delay load unparser and only if it has not been loaded already.
|
66
|
-
require "unparser" unless defined?(::Unparser)
|
67
|
-
end
|
68
|
-
|
69
56
|
class << self
|
70
57
|
extend T::Sig
|
71
58
|
|
@@ -104,22 +91,27 @@ module RBI
|
|
104
91
|
|
105
92
|
private
|
106
93
|
|
107
|
-
sig { params(
|
108
|
-
def parse(
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
94
|
+
sig { params(source: String, file: String).returns(Tree) }
|
95
|
+
def parse(source, file:)
|
96
|
+
result = YARP.parse(source)
|
97
|
+
unless result.success?
|
98
|
+
message = result.errors.map { |e| "#{e.message}." }.join(" ")
|
99
|
+
error = result.errors.first
|
100
|
+
location = Loc.new(file: file, begin_line: error.location.start_line, begin_column: error.location.start_column)
|
101
|
+
raise ParseError.new(message, location)
|
102
|
+
end
|
103
|
+
|
104
|
+
visitor = TreeBuilder.new(source, comments: result.comments, file: file)
|
105
|
+
visitor.visit(result.value)
|
106
|
+
visitor.tree
|
107
|
+
rescue YARP::ParseError => e
|
108
|
+
raise ParseError.new(e.message, Loc.from_yarp(file, e.location))
|
117
109
|
rescue ParseError => e
|
118
110
|
raise e
|
119
111
|
rescue => e
|
120
|
-
last_node =
|
112
|
+
last_node = visitor&.last_node
|
121
113
|
last_location = if last_node
|
122
|
-
Loc.
|
114
|
+
Loc.from_yarp(file, last_node.location)
|
123
115
|
else
|
124
116
|
Loc.new(file: file)
|
125
117
|
end
|
@@ -128,630 +120,692 @@ module RBI
|
|
128
120
|
exception.print_debug
|
129
121
|
raise exception
|
130
122
|
end
|
131
|
-
end
|
132
123
|
|
133
|
-
|
134
|
-
|
135
|
-
extend T::Sig
|
124
|
+
class Visitor < YARP::Visitor
|
125
|
+
extend T::Sig
|
136
126
|
|
137
|
-
|
127
|
+
sig { params(source: String, file: String).void }
|
128
|
+
def initialize(source, file:)
|
129
|
+
super()
|
138
130
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
131
|
+
@source = source
|
132
|
+
@file = file
|
133
|
+
end
|
143
134
|
|
144
|
-
|
145
|
-
def visit(node); end
|
135
|
+
private
|
146
136
|
|
147
|
-
|
137
|
+
sig { params(node: YARP::Node).returns(Loc) }
|
138
|
+
def node_loc(node)
|
139
|
+
Loc.from_yarp(@file, node.location)
|
140
|
+
end
|
148
141
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
142
|
+
sig { params(node: T.nilable(YARP::Node)).returns(T.nilable(String)) }
|
143
|
+
def node_string(node)
|
144
|
+
return unless node
|
153
145
|
|
154
|
-
|
155
|
-
|
156
|
-
|
146
|
+
node.slice
|
147
|
+
end
|
148
|
+
|
149
|
+
sig { params(node: YARP::Node).returns(String) }
|
150
|
+
def node_string!(node)
|
151
|
+
T.must(node_string(node))
|
152
|
+
end
|
157
153
|
end
|
158
|
-
end
|
159
154
|
|
160
|
-
|
161
|
-
|
155
|
+
class TreeBuilder < Visitor
|
156
|
+
extend T::Sig
|
162
157
|
|
163
|
-
|
164
|
-
|
158
|
+
sig { returns(Tree) }
|
159
|
+
attr_reader :tree
|
165
160
|
|
166
|
-
|
167
|
-
|
161
|
+
sig { returns(T.nilable(YARP::Node)) }
|
162
|
+
attr_reader :last_node
|
168
163
|
|
169
|
-
|
170
|
-
|
171
|
-
file:
|
172
|
-
comments: T::Array[::Parser::Source::Comment],
|
173
|
-
nodes_comments_assoc: T::Hash[::Parser::Source::Map, T::Array[::Parser::Source::Comment]],
|
174
|
-
).void
|
175
|
-
end
|
176
|
-
def initialize(file:, comments: [], nodes_comments_assoc: {})
|
177
|
-
super()
|
178
|
-
@file = file
|
179
|
-
@comments = comments
|
180
|
-
@nodes_comments_assoc = nodes_comments_assoc
|
181
|
-
@tree = T.let(Tree.new, Tree)
|
182
|
-
@scopes_stack = T.let([@tree], T::Array[Tree])
|
183
|
-
@last_node = T.let(nil, T.nilable(::AST::Node))
|
184
|
-
@last_sigs = T.let([], T::Array[RBI::Sig])
|
185
|
-
@last_sigs_comments = T.let([], T::Array[Comment])
|
186
|
-
|
187
|
-
separate_header_comments
|
188
|
-
end
|
164
|
+
sig { params(source: String, comments: T::Array[YARP::Comment], file: String).void }
|
165
|
+
def initialize(source, comments:, file:)
|
166
|
+
super(source, file: file)
|
189
167
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
168
|
+
@comments_by_line = T.let(comments.to_h { |c| [c.location.start_line, c] }, T::Hash[Integer, YARP::Comment])
|
169
|
+
@tree = T.let(Tree.new, Tree)
|
170
|
+
|
171
|
+
@scopes_stack = T.let([@tree], T::Array[Tree])
|
172
|
+
@last_node = T.let(nil, T.nilable(YARP::Node))
|
173
|
+
@last_sigs = T.let([], T::Array[RBI::Sig])
|
174
|
+
@last_sigs_comments = T.let([], T::Array[Comment])
|
175
|
+
end
|
176
|
+
|
177
|
+
sig { override.params(node: T.nilable(YARP::Node)).void }
|
178
|
+
def visit(node)
|
179
|
+
return unless node
|
195
180
|
|
196
|
-
|
197
|
-
|
198
|
-
|
181
|
+
@last_node = node
|
182
|
+
super
|
183
|
+
end
|
199
184
|
|
200
|
-
|
185
|
+
sig { override.params(node: YARP::ClassNode).void }
|
186
|
+
def visit_class_node(node)
|
187
|
+
scope = Class.new(
|
188
|
+
node_string!(node.constant_path),
|
189
|
+
superclass_name: node_string(node.superclass),
|
190
|
+
loc: node_loc(node),
|
191
|
+
comments: node_comments(node),
|
192
|
+
)
|
201
193
|
|
202
|
-
case node.type
|
203
|
-
when :module, :class, :sclass
|
204
|
-
scope = parse_scope(node)
|
205
194
|
current_scope << scope
|
206
195
|
@scopes_stack << scope
|
207
|
-
|
196
|
+
visit(node.body)
|
197
|
+
collect_dangling_comments(node)
|
208
198
|
@scopes_stack.pop
|
209
|
-
when :casgn
|
210
|
-
current_scope << parse_const_assign(node)
|
211
|
-
when :def, :defs
|
212
|
-
current_scope << parse_def(node)
|
213
|
-
when :send
|
214
|
-
node = parse_send(node)
|
215
|
-
current_scope << node if node
|
216
|
-
when :block
|
217
|
-
rbi_node = parse_block(node)
|
218
|
-
if rbi_node.is_a?(Sig)
|
219
|
-
@last_sigs << rbi_node
|
220
|
-
@last_sigs_comments.concat(node_comments(node))
|
221
|
-
elsif rbi_node
|
222
|
-
current_scope << rbi_node
|
223
|
-
end
|
224
|
-
else
|
225
|
-
visit_all(node.children)
|
226
199
|
end
|
227
200
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
private
|
232
|
-
|
233
|
-
sig { params(node: AST::Node).returns(Scope) }
|
234
|
-
def parse_scope(node)
|
235
|
-
loc = node_loc(node)
|
236
|
-
comments = node_comments(node)
|
237
|
-
|
238
|
-
case node.type
|
239
|
-
when :module
|
240
|
-
name = parse_name(node.children[0])
|
241
|
-
Module.new(name, loc: loc, comments: comments)
|
242
|
-
when :class
|
243
|
-
name = parse_name(node.children[0])
|
244
|
-
superclass_name = ConstBuilder.visit(node.children[1])
|
245
|
-
Class.new(name, superclass_name: superclass_name, loc: loc, comments: comments)
|
246
|
-
when :sclass
|
247
|
-
SingletonClass.new(loc: loc, comments: comments)
|
248
|
-
else
|
249
|
-
raise ParseError.new("Unsupported scope node type `#{node.type}`", loc)
|
201
|
+
sig { override.params(node: YARP::ConstantWriteNode).void }
|
202
|
+
def visit_constant_write_node(node)
|
203
|
+
visit_constant_assign(node)
|
250
204
|
end
|
251
|
-
end
|
252
205
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
if struct_definition?(node_value)
|
257
|
-
parse_struct(node)
|
258
|
-
elsif type_variable_definition?(node_value)
|
259
|
-
parse_type_variable(node)
|
260
|
-
else
|
261
|
-
name = parse_name(node)
|
262
|
-
value = parse_expr(node_value)
|
263
|
-
loc = node_loc(node)
|
264
|
-
comments = node_comments(node)
|
265
|
-
Const.new(name, value, loc: loc, comments: comments)
|
206
|
+
sig { override.params(node: YARP::ConstantPathWriteNode).void }
|
207
|
+
def visit_constant_path_write_node(node)
|
208
|
+
visit_constant_assign(node)
|
266
209
|
end
|
267
|
-
end
|
268
210
|
|
269
|
-
|
270
|
-
|
271
|
-
|
211
|
+
sig { params(node: T.any(YARP::ConstantWriteNode, YARP::ConstantPathWriteNode)).void }
|
212
|
+
def visit_constant_assign(node)
|
213
|
+
struct = parse_struct(node)
|
214
|
+
|
215
|
+
current_scope << if struct
|
216
|
+
struct
|
217
|
+
elsif type_variable_definition?(node.value)
|
218
|
+
TypeMember.new(
|
219
|
+
case node
|
220
|
+
when YARP::ConstantWriteNode
|
221
|
+
node.name.to_s
|
222
|
+
when YARP::ConstantPathWriteNode
|
223
|
+
node_string!(node.target)
|
224
|
+
end,
|
225
|
+
node_string!(node.value),
|
226
|
+
loc: node_loc(node),
|
227
|
+
comments: node_comments(node),
|
228
|
+
)
|
229
|
+
else
|
230
|
+
Const.new(
|
231
|
+
case node
|
232
|
+
when YARP::ConstantWriteNode
|
233
|
+
node.name.to_s
|
234
|
+
when YARP::ConstantPathWriteNode
|
235
|
+
node_string!(node.target)
|
236
|
+
end,
|
237
|
+
node_string!(node.value),
|
238
|
+
loc: node_loc(node),
|
239
|
+
comments: node_comments(node),
|
240
|
+
)
|
241
|
+
end
|
242
|
+
end
|
272
243
|
|
273
|
-
|
274
|
-
|
275
|
-
Method.new(
|
276
|
-
node.
|
277
|
-
params: node.
|
244
|
+
sig { override.params(node: YARP::DefNode).void }
|
245
|
+
def visit_def_node(node)
|
246
|
+
current_scope << Method.new(
|
247
|
+
node.name.to_s,
|
248
|
+
params: parse_params(node.parameters),
|
278
249
|
sigs: current_sigs,
|
279
|
-
loc:
|
250
|
+
loc: node_loc(node),
|
280
251
|
comments: current_sigs_comments + node_comments(node),
|
252
|
+
is_singleton: !!node.receiver,
|
281
253
|
)
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
loc:
|
289
|
-
comments:
|
254
|
+
end
|
255
|
+
|
256
|
+
sig { override.params(node: YARP::ModuleNode).void }
|
257
|
+
def visit_module_node(node)
|
258
|
+
scope = Module.new(
|
259
|
+
node_string!(node.constant_path),
|
260
|
+
loc: node_loc(node),
|
261
|
+
comments: node_comments(node),
|
290
262
|
)
|
291
|
-
|
292
|
-
|
263
|
+
|
264
|
+
current_scope << scope
|
265
|
+
@scopes_stack << scope
|
266
|
+
visit(node.body)
|
267
|
+
collect_dangling_comments(node)
|
268
|
+
@scopes_stack.pop
|
293
269
|
end
|
294
|
-
end
|
295
270
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
when :arg
|
304
|
-
ReqParam.new(name, loc: loc, comments: comments)
|
305
|
-
when :optarg
|
306
|
-
value = parse_expr(node.children[1])
|
307
|
-
OptParam.new(name, value, loc: loc, comments: comments)
|
308
|
-
when :restarg
|
309
|
-
RestParam.new(name, loc: loc, comments: comments)
|
310
|
-
when :kwarg
|
311
|
-
KwParam.new(name, loc: loc, comments: comments)
|
312
|
-
when :kwoptarg
|
313
|
-
value = parse_expr(node.children[1])
|
314
|
-
KwOptParam.new(name, value, loc: loc, comments: comments)
|
315
|
-
when :kwrestarg
|
316
|
-
KwRestParam.new(name, loc: loc, comments: comments)
|
317
|
-
when :blockarg
|
318
|
-
BlockParam.new(name, loc: loc, comments: comments)
|
319
|
-
else
|
320
|
-
raise ParseError.new("Unsupported param node type `#{node.type}`", loc)
|
271
|
+
sig { override.params(node: YARP::ProgramNode).void }
|
272
|
+
def visit_program_node(node)
|
273
|
+
super
|
274
|
+
|
275
|
+
collect_orphan_comments
|
276
|
+
separate_header_comments
|
277
|
+
set_root_tree_loc
|
321
278
|
end
|
322
|
-
end
|
323
279
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
AttrReader.new(*symbols, sigs: current_sigs, loc: loc, comments: current_sigs_comments + comments)
|
337
|
-
when :attr_writer
|
338
|
-
symbols = node.children[2..-1].map { |child| child.children[0] }
|
339
|
-
AttrWriter.new(*symbols, sigs: current_sigs, loc: loc, comments: current_sigs_comments + comments)
|
340
|
-
when :attr_accessor
|
341
|
-
symbols = node.children[2..-1].map { |child| child.children[0] }
|
342
|
-
AttrAccessor.new(*symbols, sigs: current_sigs, loc: loc, comments: current_sigs_comments + comments)
|
343
|
-
when :include
|
344
|
-
names = node.children[2..-1].map { |child| parse_expr(child) }
|
345
|
-
Include.new(*names, loc: loc, comments: comments)
|
346
|
-
when :extend
|
347
|
-
names = node.children[2..-1].map { |child| parse_expr(child) }
|
348
|
-
Extend.new(*names, loc: loc, comments: comments)
|
349
|
-
when :abstract!, :sealed!, :interface!
|
350
|
-
Helper.new(method_name.to_s.delete_suffix("!"), loc: loc, comments: comments)
|
351
|
-
when :mixes_in_class_methods
|
352
|
-
names = node.children[2..-1].map { |child| parse_name(child) }
|
353
|
-
MixesInClassMethods.new(*names, loc: loc, comments: comments)
|
354
|
-
when :public, :protected, :private
|
355
|
-
visibility = case method_name
|
356
|
-
when :protected
|
357
|
-
Protected.new(loc: loc)
|
358
|
-
when :private
|
359
|
-
Private.new(loc: loc)
|
360
|
-
else
|
361
|
-
Public.new(loc: loc)
|
362
|
-
end
|
363
|
-
nested_node = node.children[2]
|
364
|
-
case nested_node&.type
|
365
|
-
when :def, :defs
|
366
|
-
method = parse_def(nested_node)
|
367
|
-
method.visibility = visibility
|
368
|
-
method
|
369
|
-
when :send
|
370
|
-
snode = parse_send(nested_node)
|
371
|
-
raise ParseError.new("Unexpected token `private` before `#{nested_node.type}`", loc) unless snode.is_a?(Attr)
|
372
|
-
|
373
|
-
snode.visibility = visibility
|
374
|
-
snode
|
375
|
-
when nil
|
376
|
-
visibility
|
377
|
-
else
|
378
|
-
raise ParseError.new("Unexpected token `private` before `#{nested_node.type}`", loc)
|
379
|
-
end
|
380
|
-
when :prop
|
381
|
-
name, type, default_value = parse_tstruct_prop(node)
|
382
|
-
TStructProp.new(name, type, default: default_value, loc: loc, comments: comments)
|
383
|
-
when :const
|
384
|
-
name, type, default_value = parse_tstruct_prop(node)
|
385
|
-
TStructConst.new(name, type, default: default_value, loc: loc, comments: comments)
|
386
|
-
else
|
387
|
-
args = parse_send_args(node)
|
388
|
-
Send.new(method_name.to_s, args, loc: loc, comments: comments)
|
280
|
+
sig { override.params(node: YARP::SingletonClassNode).void }
|
281
|
+
def visit_singleton_class_node(node)
|
282
|
+
scope = SingletonClass.new(
|
283
|
+
loc: node_loc(node),
|
284
|
+
comments: node_comments(node),
|
285
|
+
)
|
286
|
+
|
287
|
+
current_scope << scope
|
288
|
+
@scopes_stack << scope
|
289
|
+
visit(node.body)
|
290
|
+
collect_dangling_comments(node)
|
291
|
+
@scopes_stack.pop
|
389
292
|
end
|
390
|
-
end
|
391
293
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
294
|
+
sig { params(node: YARP::CallNode).void }
|
295
|
+
def visit_call_node(node)
|
296
|
+
message = node.name
|
297
|
+
case message
|
298
|
+
when "abstract!", "sealed!", "interface!"
|
299
|
+
current_scope << Helper.new(
|
300
|
+
message.delete_suffix("!"),
|
301
|
+
loc: node_loc(node),
|
302
|
+
comments: node_comments(node),
|
303
|
+
)
|
304
|
+
when "attr_reader"
|
305
|
+
args = node.arguments
|
306
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
307
|
+
|
308
|
+
current_scope << AttrReader.new(
|
309
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
|
310
|
+
sigs: current_sigs,
|
311
|
+
loc: node_loc(node),
|
312
|
+
comments: current_sigs_comments + node_comments(node),
|
313
|
+
)
|
314
|
+
when "attr_writer"
|
315
|
+
args = node.arguments
|
316
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
317
|
+
|
318
|
+
current_scope << AttrWriter.new(
|
319
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
|
320
|
+
sigs: current_sigs,
|
321
|
+
loc: node_loc(node),
|
322
|
+
comments: current_sigs_comments + node_comments(node),
|
323
|
+
)
|
324
|
+
when "attr_accessor"
|
325
|
+
args = node.arguments
|
326
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
327
|
+
|
328
|
+
current_scope << AttrAccessor.new(
|
329
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
|
330
|
+
sigs: current_sigs,
|
331
|
+
loc: node_loc(node),
|
332
|
+
comments: current_sigs_comments + node_comments(node),
|
333
|
+
)
|
334
|
+
when "enums"
|
335
|
+
block = node.block
|
336
|
+
return unless block.is_a?(YARP::BlockNode)
|
337
|
+
|
338
|
+
body = block.body
|
339
|
+
return unless body.is_a?(YARP::StatementsNode)
|
340
|
+
|
341
|
+
current_scope << TEnumBlock.new(
|
342
|
+
body.body.map { |stmt| T.cast(stmt, YARP::ConstantWriteNode).name.to_s },
|
343
|
+
loc: node_loc(node),
|
344
|
+
comments: node_comments(node),
|
345
|
+
)
|
346
|
+
when "extend"
|
347
|
+
args = node.arguments
|
348
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
349
|
+
|
350
|
+
current_scope << Extend.new(
|
351
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg) }),
|
352
|
+
loc: node_loc(node),
|
353
|
+
comments: node_comments(node),
|
354
|
+
)
|
355
|
+
when "include"
|
356
|
+
args = node.arguments
|
357
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
358
|
+
|
359
|
+
current_scope << Include.new(
|
360
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg) }),
|
361
|
+
loc: node_loc(node),
|
362
|
+
comments: node_comments(node),
|
363
|
+
)
|
364
|
+
when "mixes_in_class_methods"
|
365
|
+
args = node.arguments
|
366
|
+
return unless args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
367
|
+
|
368
|
+
current_scope << MixesInClassMethods.new(
|
369
|
+
*T.unsafe(args.arguments.map { |arg| node_string!(arg) }),
|
370
|
+
loc: node_loc(node),
|
371
|
+
comments: node_comments(node),
|
372
|
+
)
|
373
|
+
when "private", "protected", "public"
|
374
|
+
args = node.arguments
|
375
|
+
if args.is_a?(YARP::ArgumentsNode) && args.arguments.any?
|
376
|
+
visit(node.arguments)
|
377
|
+
last_node = @scopes_stack.last&.nodes&.last
|
378
|
+
case last_node
|
379
|
+
when Method, Attr
|
380
|
+
last_node.visibility = parse_visibility(node.name, node)
|
381
|
+
else
|
382
|
+
raise ParseError.new(
|
383
|
+
"Unexpected token `#{node.message}` before `#{last_node&.string&.strip}`",
|
384
|
+
node_loc(node),
|
385
|
+
)
|
386
|
+
end
|
387
|
+
else
|
388
|
+
current_scope << parse_visibility(node.name, node)
|
401
389
|
end
|
390
|
+
when "prop", "const"
|
391
|
+
parse_tstruct_field(node)
|
392
|
+
when "requires_ancestor"
|
393
|
+
block = node.block
|
394
|
+
return unless block.is_a?(YARP::BlockNode)
|
395
|
+
|
396
|
+
body = block.body
|
397
|
+
return unless body.is_a?(YARP::StatementsNode)
|
398
|
+
|
399
|
+
current_scope << RequiresAncestor.new(
|
400
|
+
node_string!(body),
|
401
|
+
loc: node_loc(node),
|
402
|
+
comments: node_comments(node),
|
403
|
+
)
|
404
|
+
when "sig"
|
405
|
+
@last_sigs << parse_sig(node)
|
402
406
|
else
|
403
|
-
|
407
|
+
current_scope << Send.new(
|
408
|
+
message,
|
409
|
+
parse_send_args(node.arguments),
|
410
|
+
loc: node_loc(node),
|
411
|
+
comments: node_comments(node),
|
412
|
+
)
|
404
413
|
end
|
405
414
|
end
|
406
|
-
args
|
407
|
-
end
|
408
415
|
|
409
|
-
|
410
|
-
def parse_block(node)
|
411
|
-
name = node.children[0].children[1]
|
412
|
-
|
413
|
-
case name
|
414
|
-
when :sig
|
415
|
-
parse_sig(node)
|
416
|
-
when :enums
|
417
|
-
parse_enum(node)
|
418
|
-
when :requires_ancestor
|
419
|
-
parse_requires_ancestor(node)
|
420
|
-
else
|
421
|
-
raise ParseError.new("Unsupported block node type `#{name}`", node_loc(node))
|
422
|
-
end
|
423
|
-
end
|
416
|
+
private
|
424
417
|
|
425
|
-
|
426
|
-
|
427
|
-
(node
|
428
|
-
|
429
|
-
|
418
|
+
# Collect all the remaining comments within a node
|
419
|
+
sig { params(node: YARP::Node).void }
|
420
|
+
def collect_dangling_comments(node)
|
421
|
+
first_line = node.location.start_line
|
422
|
+
last_line = node.location.end_line
|
430
423
|
|
431
|
-
|
432
|
-
def parse_struct(node)
|
433
|
-
name = parse_name(node)
|
434
|
-
loc = node_loc(node)
|
435
|
-
comments = node_comments(node)
|
424
|
+
last_node_last_line = node.child_nodes.last&.location&.end_line
|
436
425
|
|
437
|
-
|
438
|
-
|
426
|
+
last_line.downto(first_line) do |line|
|
427
|
+
comment = @comments_by_line[line]
|
428
|
+
next unless comment
|
429
|
+
break if last_node_last_line && line <= last_node_last_line
|
439
430
|
|
440
|
-
|
441
|
-
|
442
|
-
body = send.children[2].children
|
443
|
-
else
|
444
|
-
body << send.children[2]
|
431
|
+
current_scope << parse_comment(comment)
|
432
|
+
@comments_by_line.delete(line)
|
445
433
|
end
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
if
|
457
|
-
|
434
|
+
end
|
435
|
+
|
436
|
+
# Collect all the remaining comments after visiting the tree
|
437
|
+
sig { void }
|
438
|
+
def collect_orphan_comments
|
439
|
+
last_line = T.let(nil, T.nilable(Integer))
|
440
|
+
last_node_end = @tree.nodes.last&.loc&.end_line
|
441
|
+
|
442
|
+
@comments_by_line.each do |line, comment|
|
443
|
+
# Associate the comment either with the header or the file or as a dangling comment at the end
|
444
|
+
recv = if last_node_end && line >= last_node_end
|
445
|
+
@tree
|
446
|
+
else
|
447
|
+
@tree.comments
|
458
448
|
end
|
449
|
+
|
450
|
+
# Preserve blank lines in comments
|
451
|
+
if last_line && line > last_line + 1
|
452
|
+
recv << BlankLine.new(loc: Loc.from_yarp(@file, comment.location))
|
453
|
+
end
|
454
|
+
|
455
|
+
recv << parse_comment(comment)
|
456
|
+
last_line = line
|
459
457
|
end
|
460
458
|
end
|
461
459
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
struct
|
468
|
-
end
|
460
|
+
sig { returns(Tree) }
|
461
|
+
def current_scope
|
462
|
+
T.must(@scopes_stack.last) # Should never be nil since we create a Tree as the root
|
463
|
+
end
|
469
464
|
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
465
|
+
sig { returns(T::Array[Sig]) }
|
466
|
+
def current_sigs
|
467
|
+
sigs = @last_sigs.dup
|
468
|
+
@last_sigs.clear
|
469
|
+
sigs
|
470
|
+
end
|
476
471
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
472
|
+
sig { returns(T::Array[Comment]) }
|
473
|
+
def current_sigs_comments
|
474
|
+
comments = @last_sigs_comments.dup
|
475
|
+
@last_sigs_comments.clear
|
476
|
+
comments
|
477
|
+
end
|
482
478
|
|
483
|
-
|
479
|
+
sig { params(node: YARP::Node).returns(T::Array[Comment]) }
|
480
|
+
def node_comments(node)
|
481
|
+
comments = []
|
484
482
|
|
485
|
-
|
486
|
-
|
483
|
+
start_line = node.location.start_line
|
484
|
+
start_line -= 1 unless @comments_by_line.key?(start_line)
|
487
485
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
type = parse_expr(node.children[3])
|
492
|
-
has_default = node.children[4]
|
493
|
-
&.children&.fetch(0, nil)
|
494
|
-
&.children&.fetch(0, nil)
|
495
|
-
&.children&.fetch(0, nil) == :default
|
496
|
-
default_value = if has_default
|
497
|
-
parse_expr(node.children.fetch(4, nil)
|
498
|
-
&.children&.fetch(0, nil)
|
499
|
-
&.children&.fetch(1, nil))
|
500
|
-
end
|
501
|
-
[name, type, default_value]
|
502
|
-
end
|
486
|
+
start_line.downto(1) do |line|
|
487
|
+
comment = @comments_by_line[line]
|
488
|
+
break unless comment
|
503
489
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
sig.loc = node_loc(node)
|
508
|
-
sig
|
509
|
-
end
|
490
|
+
comments.unshift(parse_comment(comment))
|
491
|
+
@comments_by_line.delete(line)
|
492
|
+
end
|
510
493
|
|
511
|
-
|
512
|
-
|
513
|
-
enum = TEnumBlock.new
|
494
|
+
comments
|
495
|
+
end
|
514
496
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
[node.children[2]]
|
497
|
+
sig { params(node: YARP::Comment).returns(Comment) }
|
498
|
+
def parse_comment(node)
|
499
|
+
Comment.new(node.location.slice.gsub(/^# ?/, "").rstrip, loc: Loc.from_yarp(@file, node.location))
|
519
500
|
end
|
520
501
|
|
521
|
-
|
522
|
-
|
502
|
+
sig { params(node: T.nilable(YARP::Node)).returns(T::Array[Arg]) }
|
503
|
+
def parse_send_args(node)
|
504
|
+
args = T.let([], T::Array[Arg])
|
505
|
+
return args unless node.is_a?(YARP::ArgumentsNode)
|
506
|
+
|
507
|
+
node.arguments.each do |arg|
|
508
|
+
case arg
|
509
|
+
when YARP::KeywordHashNode
|
510
|
+
arg.elements.each do |assoc|
|
511
|
+
next unless assoc.is_a?(YARP::AssocNode)
|
512
|
+
|
513
|
+
args << KwArg.new(
|
514
|
+
node_string!(assoc.key).delete_suffix(":"),
|
515
|
+
T.must(node_string(assoc.value)),
|
516
|
+
)
|
517
|
+
end
|
518
|
+
else
|
519
|
+
args << Arg.new(T.must(node_string(arg)))
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
args
|
523
524
|
end
|
524
|
-
enum.loc = node_loc(node)
|
525
|
-
enum
|
526
|
-
end
|
527
525
|
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
ra.loc = node_loc(node)
|
533
|
-
ra
|
534
|
-
end
|
526
|
+
sig { params(node: T.nilable(YARP::Node)).returns(T::Array[Param]) }
|
527
|
+
def parse_params(node)
|
528
|
+
params = []
|
529
|
+
return params unless node.is_a?(YARP::ParametersNode)
|
535
530
|
|
536
|
-
|
537
|
-
|
538
|
-
Loc.from_ast_loc(@file, node.location)
|
539
|
-
end
|
531
|
+
node.requireds.each do |param|
|
532
|
+
next unless param.is_a?(YARP::RequiredParameterNode)
|
540
533
|
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
534
|
+
params << ReqParam.new(
|
535
|
+
param.name.to_s,
|
536
|
+
loc: node_loc(param),
|
537
|
+
comments: node_comments(param),
|
538
|
+
)
|
539
|
+
end
|
545
540
|
|
546
|
-
|
547
|
-
|
548
|
-
loc = Loc.from_ast_loc(@file, comment.location)
|
549
|
-
Comment.new(text, loc: loc)
|
550
|
-
end
|
551
|
-
end
|
541
|
+
node.optionals.each do |param|
|
542
|
+
next unless param.is_a?(YARP::OptionalParameterNode)
|
552
543
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
544
|
+
params << OptParam.new(
|
545
|
+
param.name.to_s,
|
546
|
+
node_string!(param.value),
|
547
|
+
loc: node_loc(param),
|
548
|
+
comments: node_comments(param),
|
549
|
+
)
|
550
|
+
end
|
557
551
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
552
|
+
rest = node.rest
|
553
|
+
if rest.is_a?(YARP::RestParameterNode)
|
554
|
+
params << RestParam.new(
|
555
|
+
rest.name&.to_s || "*args",
|
556
|
+
loc: node_loc(rest),
|
557
|
+
comments: node_comments(rest),
|
558
|
+
)
|
559
|
+
end
|
564
560
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
561
|
+
node.keywords.each do |param|
|
562
|
+
next unless param.is_a?(YARP::KeywordParameterNode)
|
563
|
+
|
564
|
+
value = param.value
|
565
|
+
params << if value
|
566
|
+
KwOptParam.new(
|
567
|
+
param.name.to_s.delete_suffix(":"),
|
568
|
+
node_string!(value),
|
569
|
+
loc: node_loc(param),
|
570
|
+
comments: node_comments(param),
|
571
|
+
)
|
572
|
+
else
|
573
|
+
KwParam.new(
|
574
|
+
param.name.to_s.delete_suffix(":"),
|
575
|
+
loc: node_loc(param),
|
576
|
+
comments: node_comments(param),
|
577
|
+
)
|
578
|
+
end
|
579
|
+
end
|
571
580
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
if last_line && comment_line > last_line + 1
|
581
|
-
# Preserve empty lines in file headers
|
582
|
-
tree.comments << BlankLine.new(loc: loc)
|
581
|
+
rest_kw = node.keyword_rest
|
582
|
+
if rest_kw.is_a?(YARP::KeywordRestParameterNode)
|
583
|
+
params << KwRestParam.new(
|
584
|
+
rest_kw.name&.to_s || "**kwargs",
|
585
|
+
loc: node_loc(rest_kw),
|
586
|
+
comments: node_comments(rest_kw),
|
587
|
+
)
|
583
588
|
end
|
584
589
|
|
585
|
-
|
586
|
-
|
590
|
+
block = node.block
|
591
|
+
if block.is_a?(YARP::BlockParameterNode)
|
592
|
+
params << BlockParam.new(
|
593
|
+
block.name&.to_s || "&block",
|
594
|
+
loc: node_loc(block),
|
595
|
+
comments: node_comments(block),
|
596
|
+
)
|
597
|
+
end
|
598
|
+
|
599
|
+
params
|
587
600
|
end
|
588
|
-
end
|
589
601
|
|
590
|
-
|
591
|
-
|
592
|
-
|
602
|
+
sig { params(node: YARP::CallNode).returns(Sig) }
|
603
|
+
def parse_sig(node)
|
604
|
+
@last_sigs_comments = node_comments(node)
|
593
605
|
|
594
|
-
|
595
|
-
|
596
|
-
|
606
|
+
builder = SigBuilder.new(@source, file: @file)
|
607
|
+
builder.current.loc = node_loc(node)
|
608
|
+
builder.visit_call_node(node)
|
609
|
+
builder.current
|
610
|
+
end
|
597
611
|
|
598
|
-
|
599
|
-
|
600
|
-
|
612
|
+
sig { params(node: T.any(YARP::ConstantWriteNode, YARP::ConstantPathWriteNode)).returns(T.nilable(Struct)) }
|
613
|
+
def parse_struct(node)
|
614
|
+
send = node.value
|
615
|
+
return unless send.is_a?(YARP::CallNode)
|
616
|
+
return unless send.message == "new"
|
617
|
+
|
618
|
+
recv = send.receiver
|
619
|
+
return unless recv
|
620
|
+
return unless node_string(recv) =~ /(::)?Struct/
|
621
|
+
|
622
|
+
members = []
|
623
|
+
keyword_init = T.let(false, T::Boolean)
|
624
|
+
|
625
|
+
args = send.arguments
|
626
|
+
if args.is_a?(YARP::ArgumentsNode)
|
627
|
+
args.arguments.each do |arg|
|
628
|
+
case arg
|
629
|
+
when YARP::SymbolNode
|
630
|
+
members << arg.value
|
631
|
+
when YARP::KeywordHashNode
|
632
|
+
arg.elements.each do |assoc|
|
633
|
+
next unless assoc.is_a?(YARP::AssocNode)
|
634
|
+
|
635
|
+
key = node_string!(assoc.key)
|
636
|
+
val = node_string(assoc.value)
|
637
|
+
|
638
|
+
keyword_init = val == "true" if key == "keyword_init:"
|
639
|
+
end
|
640
|
+
else
|
641
|
+
raise ParseError.new("Unexpected node type `#{arg.class}`", node_loc(arg))
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end
|
601
645
|
|
602
|
-
|
603
|
-
|
646
|
+
name = case node
|
647
|
+
when YARP::ConstantWriteNode
|
648
|
+
node.name.to_s
|
649
|
+
when YARP::ConstantPathWriteNode
|
650
|
+
node_string!(node.target)
|
651
|
+
end
|
604
652
|
|
605
|
-
|
606
|
-
|
653
|
+
loc = node_loc(node)
|
654
|
+
comments = node_comments(node)
|
655
|
+
struct = Struct.new(name, members: members, keyword_init: keyword_init, loc: loc, comments: comments)
|
656
|
+
@scopes_stack << struct
|
657
|
+
visit(send.block)
|
658
|
+
@scopes_stack.pop
|
659
|
+
struct
|
607
660
|
end
|
608
661
|
|
609
|
-
|
610
|
-
|
662
|
+
sig { params(send: YARP::CallNode).void }
|
663
|
+
def parse_tstruct_field(send)
|
664
|
+
args = send.arguments
|
665
|
+
return unless args.is_a?(YARP::ArgumentsNode)
|
611
666
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
last_loc = tree.nodes.last&.loc
|
616
|
-
|
617
|
-
@tree.loc = Loc.new(
|
618
|
-
file: @file,
|
619
|
-
begin_line: first_loc&.begin_line || 0,
|
620
|
-
begin_column: first_loc&.begin_column || 0,
|
621
|
-
end_line: last_loc&.end_line || 0,
|
622
|
-
end_column: last_loc&.end_column || 0,
|
623
|
-
)
|
624
|
-
end
|
625
|
-
end
|
667
|
+
name_arg, type_arg, *rest = args.arguments
|
668
|
+
return unless name_arg
|
669
|
+
return unless type_arg
|
626
670
|
|
627
|
-
|
628
|
-
|
671
|
+
name = node_string!(name_arg).delete_prefix(":")
|
672
|
+
type = node_string!(type_arg)
|
673
|
+
loc = node_loc(send)
|
674
|
+
comments = node_comments(send)
|
675
|
+
default_value = T.let(nil, T.nilable(String))
|
629
676
|
|
630
|
-
|
631
|
-
|
677
|
+
rest&.each do |arg|
|
678
|
+
next unless arg.is_a?(YARP::KeywordHashNode)
|
632
679
|
|
633
|
-
|
634
|
-
|
635
|
-
super
|
636
|
-
@names = T.let([], T::Array[String])
|
637
|
-
end
|
680
|
+
arg.elements.each do |assoc|
|
681
|
+
next unless assoc.is_a?(YARP::AssocNode)
|
638
682
|
|
639
|
-
|
640
|
-
|
683
|
+
if node_string(assoc.key) == "default:"
|
684
|
+
default_value = node_string(assoc.value)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
641
688
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
689
|
+
current_scope << case send.message
|
690
|
+
when "const"
|
691
|
+
TStructConst.new(name, type, default: default_value, loc: loc, comments: comments)
|
692
|
+
when "prop"
|
693
|
+
TStructProp.new(name, type, default: default_value, loc: loc, comments: comments)
|
694
|
+
else
|
695
|
+
raise ParseError.new("Unexpected message `#{send.message}`", loc)
|
696
|
+
end
|
697
|
+
end
|
647
698
|
|
648
|
-
|
699
|
+
sig { params(name: String, node: YARP::Node).returns(Visibility) }
|
700
|
+
def parse_visibility(name, node)
|
701
|
+
case name
|
702
|
+
when "public"
|
703
|
+
Public.new(loc: node_loc(node))
|
704
|
+
when "protected"
|
705
|
+
Protected.new(loc: node_loc(node))
|
706
|
+
when "private"
|
707
|
+
Private.new(loc: node_loc(node))
|
708
|
+
else
|
709
|
+
raise ParseError.new("Unexpected visibility `#{name}`", node_loc(node))
|
710
|
+
end
|
649
711
|
end
|
650
|
-
end
|
651
712
|
|
652
|
-
|
653
|
-
|
654
|
-
|
713
|
+
sig { void }
|
714
|
+
def separate_header_comments
|
715
|
+
current_scope.nodes.dup.each do |child_node|
|
716
|
+
break unless child_node.is_a?(Comment) || child_node.is_a?(BlankLine)
|
655
717
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
@names << node.children[1].to_s
|
660
|
-
when :cbase
|
661
|
-
@names << ""
|
662
|
-
when :sym
|
663
|
-
@names << ":#{node.children[0]}"
|
718
|
+
current_scope.comments << child_node
|
719
|
+
child_node.detach
|
720
|
+
end
|
664
721
|
end
|
665
|
-
end
|
666
|
-
end
|
667
722
|
|
668
|
-
|
669
|
-
|
723
|
+
sig { void }
|
724
|
+
def set_root_tree_loc
|
725
|
+
first_loc = tree.nodes.first&.loc
|
726
|
+
last_loc = tree.nodes.last&.loc
|
727
|
+
|
728
|
+
@tree.loc = Loc.new(
|
729
|
+
file: @file,
|
730
|
+
begin_line: first_loc&.begin_line || 0,
|
731
|
+
begin_column: first_loc&.begin_column || 0,
|
732
|
+
end_line: last_loc&.end_line || 0,
|
733
|
+
end_column: last_loc&.end_column || 0,
|
734
|
+
)
|
735
|
+
end
|
670
736
|
|
671
|
-
|
672
|
-
|
737
|
+
sig { params(node: T.nilable(YARP::Node)).returns(T::Boolean) }
|
738
|
+
def type_variable_definition?(node)
|
739
|
+
return false unless node.is_a?(YARP::CallNode)
|
740
|
+
return false unless node.block
|
673
741
|
|
674
|
-
|
675
|
-
|
676
|
-
super
|
677
|
-
@current = T.let(Sig.new, Sig)
|
742
|
+
node.message == "type_member" || node.message == "type_template"
|
743
|
+
end
|
678
744
|
end
|
679
745
|
|
680
|
-
class
|
746
|
+
class SigBuilder < Visitor
|
681
747
|
extend T::Sig
|
682
748
|
|
683
|
-
sig {
|
684
|
-
|
685
|
-
v = SigBuilder.new
|
686
|
-
v.visit_all(node.children)
|
687
|
-
v.current
|
688
|
-
end
|
689
|
-
end
|
749
|
+
sig { returns(Sig) }
|
750
|
+
attr_reader :current
|
690
751
|
|
691
|
-
|
692
|
-
|
693
|
-
|
752
|
+
sig { params(content: String, file: String).void }
|
753
|
+
def initialize(content, file:)
|
754
|
+
super
|
694
755
|
|
695
|
-
|
696
|
-
when :send
|
697
|
-
visit_send(node)
|
756
|
+
@current = T.let(Sig.new, Sig)
|
698
757
|
end
|
699
|
-
end
|
700
758
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
@current.is_abstract = true
|
711
|
-
when :override
|
712
|
-
@current.is_override = true
|
713
|
-
when :overridable
|
714
|
-
@current.is_overridable = true
|
715
|
-
when :checked
|
716
|
-
if node.children.length >= 3
|
717
|
-
@current.checked = node.children[2].children[0]
|
718
|
-
end
|
719
|
-
when :type_parameters
|
720
|
-
node.children[2..-1].each do |child|
|
721
|
-
@current.type_params << child.children[0].to_s
|
722
|
-
end
|
723
|
-
when :params
|
724
|
-
if node.children.length >= 3
|
725
|
-
node.children[2].children.each do |child|
|
726
|
-
name = child.children[0].children[0].to_s
|
727
|
-
type = parse_expr(child.children[1])
|
728
|
-
@current << SigParam.new(name, type)
|
759
|
+
sig { override.params(node: YARP::CallNode).void }
|
760
|
+
def visit_call_node(node)
|
761
|
+
case node.message
|
762
|
+
when "sig"
|
763
|
+
args = node.arguments
|
764
|
+
if args.is_a?(YARP::ArgumentsNode)
|
765
|
+
args.arguments.each do |arg|
|
766
|
+
@current.is_final = node_string(arg) == ":final"
|
767
|
+
end
|
729
768
|
end
|
769
|
+
when "abstract"
|
770
|
+
@current.is_abstract = true
|
771
|
+
when "checked"
|
772
|
+
args = node.arguments
|
773
|
+
if args.is_a?(YARP::ArgumentsNode)
|
774
|
+
arg = node_string(args.arguments.first)
|
775
|
+
@current.checked = arg&.delete_prefix(":")&.to_sym
|
776
|
+
end
|
777
|
+
when "override"
|
778
|
+
@current.is_override = true
|
779
|
+
when "overridable"
|
780
|
+
@current.is_overridable = true
|
781
|
+
when "params"
|
782
|
+
visit(node.arguments)
|
783
|
+
when "returns"
|
784
|
+
args = node.arguments
|
785
|
+
if args.is_a?(YARP::ArgumentsNode)
|
786
|
+
first = args.arguments.first
|
787
|
+
@current.return_type = node_string!(first) if first
|
788
|
+
end
|
789
|
+
when "type_parameters"
|
790
|
+
args = node.arguments
|
791
|
+
if args.is_a?(YARP::ArgumentsNode)
|
792
|
+
args.arguments.each do |arg|
|
793
|
+
@current.type_params << node_string!(arg).delete_prefix(":")
|
794
|
+
end
|
795
|
+
end
|
796
|
+
when "void"
|
797
|
+
@current.return_type = nil
|
730
798
|
end
|
731
|
-
when :returns
|
732
|
-
if node.children.length >= 3
|
733
|
-
@current.return_type = parse_expr(node.children[2])
|
734
|
-
end
|
735
|
-
when :void
|
736
|
-
@current.return_type = nil
|
737
|
-
else
|
738
|
-
raise "#{node.location.line}: Unhandled #{name}"
|
739
|
-
end
|
740
|
-
end
|
741
|
-
end
|
742
799
|
|
743
|
-
|
744
|
-
|
745
|
-
|
800
|
+
visit(node.receiver)
|
801
|
+
visit(node.block)
|
802
|
+
end
|
746
803
|
|
747
|
-
sig { params(
|
748
|
-
def
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
begin_column: ast_loc.column,
|
753
|
-
end_line: ast_loc.last_line,
|
754
|
-
end_column: ast_loc.last_column,
|
804
|
+
sig { override.params(node: YARP::AssocNode).void }
|
805
|
+
def visit_assoc_node(node)
|
806
|
+
@current.params << SigParam.new(
|
807
|
+
node_string!(node.key).delete_suffix(":"),
|
808
|
+
node_string!(T.must(node.value)),
|
755
809
|
)
|
756
810
|
end
|
757
811
|
end
|