typeprof 0.31.1 → 0.32.0
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 +2 -1
- data/doc/report_guide.md +88 -0
- data/lib/typeprof/cli/cli.rb +9 -3
- data/lib/typeprof/code_range.rb +7 -5
- data/lib/typeprof/core/ast/base.rb +18 -6
- data/lib/typeprof/core/ast/call.rb +96 -32
- data/lib/typeprof/core/ast/const.rb +12 -9
- data/lib/typeprof/core/ast/control.rb +60 -30
- data/lib/typeprof/core/ast/meta.rb +194 -2
- data/lib/typeprof/core/ast/method.rb +74 -20
- data/lib/typeprof/core/ast/misc.rb +27 -7
- data/lib/typeprof/core/ast/module.rb +33 -3
- data/lib/typeprof/core/ast/sig_decl.rb +85 -24
- data/lib/typeprof/core/ast/sig_type.rb +77 -31
- data/lib/typeprof/core/ast/value.rb +14 -6
- data/lib/typeprof/core/ast/variable.rb +11 -4
- data/lib/typeprof/core/ast.rb +95 -14
- data/lib/typeprof/core/builtin.rb +184 -12
- data/lib/typeprof/core/env/method.rb +171 -6
- data/lib/typeprof/core/env/method_entity.rb +18 -15
- data/lib/typeprof/core/env/module_entity.rb +56 -18
- data/lib/typeprof/core/env/static_read.rb +4 -4
- data/lib/typeprof/core/env/type_alias_entity.rb +1 -1
- data/lib/typeprof/core/env/value_entity.rb +25 -3
- data/lib/typeprof/core/env.rb +79 -17
- data/lib/typeprof/core/graph/box.rb +379 -52
- data/lib/typeprof/core/graph/change_set.rb +59 -46
- data/lib/typeprof/core/graph/filter.rb +8 -5
- data/lib/typeprof/core/graph/vertex.rb +20 -19
- data/lib/typeprof/core/service.rb +317 -23
- data/lib/typeprof/core/type.rb +41 -7
- data/lib/typeprof/core/util.rb +6 -0
- data/lib/typeprof/lsp/messages.rb +5 -0
- data/lib/typeprof/lsp/server.rb +35 -4
- data/lib/typeprof/version.rb +1 -1
- metadata +3 -2
|
@@ -203,7 +203,7 @@ module TypeProf::Core
|
|
|
203
203
|
|
|
204
204
|
def install0(genv)
|
|
205
205
|
arg = @arg.install(genv)
|
|
206
|
-
@changes.add_edge(genv, arg, @lenv.get_break_vtx)
|
|
206
|
+
@changes.add_edge(genv, arg.new_vertex(genv, self), @lenv.get_break_vtx)
|
|
207
207
|
Source.new()
|
|
208
208
|
end
|
|
209
209
|
end
|
|
@@ -236,7 +236,7 @@ module TypeProf::Core
|
|
|
236
236
|
if @lenv.exist_var?(:"*expected_block_ret")
|
|
237
237
|
@lenv.add_next_box(@changes.add_escape_box(genv, @arg.ret))
|
|
238
238
|
end
|
|
239
|
-
Source.new(
|
|
239
|
+
Source.new(genv.bot_type)
|
|
240
240
|
end
|
|
241
241
|
end
|
|
242
242
|
|
|
@@ -322,44 +322,74 @@ module TypeProf::Core
|
|
|
322
322
|
ret = Vertex.new(self)
|
|
323
323
|
@pivot&.install(genv)
|
|
324
324
|
|
|
325
|
-
#
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
# Collect modified variables across all branches
|
|
326
|
+
vars = []
|
|
327
|
+
@when_nodes.each {|wn| wn.body.modified_vars(@lenv.locals.keys, vars) }
|
|
328
|
+
@else_clause.modified_vars(@lenv.locals.keys, vars) if @else_clause
|
|
329
|
+
vars.uniq!
|
|
329
330
|
|
|
330
|
-
|
|
331
|
-
|
|
331
|
+
# Save original variable vertices
|
|
332
|
+
saved_vtxs = {}
|
|
333
|
+
vars.each do |var|
|
|
334
|
+
saved_vtxs[var] = @lenv.get_var(var)
|
|
335
|
+
end
|
|
332
336
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
337
|
+
# Prepare per-branch result vertices
|
|
338
|
+
branch_vtxs = []
|
|
339
|
+
|
|
340
|
+
# Setup pivot narrowing if applicable
|
|
341
|
+
pivot_var = @pivot.is_a?(LocalVariableReadNode) ? @pivot.var : nil
|
|
342
|
+
if pivot_var
|
|
343
|
+
original_pivot = @lenv.get_var(pivot_var)
|
|
344
|
+
@lenv.set_var(:"*pivot", original_pivot)
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Install each when branch
|
|
348
|
+
@when_nodes.each do |when_node|
|
|
349
|
+
# Reset variables to original for each branch
|
|
350
|
+
saved_vtxs.each {|var, vtx| @lenv.set_var(var, vtx.new_vertex(genv, self)) }
|
|
351
|
+
@lenv.set_var(pivot_var, original_pivot) if pivot_var
|
|
352
|
+
|
|
353
|
+
clause_val = when_node.install(genv)
|
|
354
|
+
@changes.add_edge(genv, clause_val, ret)
|
|
340
355
|
|
|
341
|
-
|
|
342
|
-
|
|
356
|
+
modified = {}
|
|
357
|
+
vars.each {|var| modified[var] = @lenv.get_var(var) }
|
|
358
|
+
branch_vtxs << [clause_val, modified]
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Install else branch
|
|
362
|
+
saved_vtxs.each {|var, vtx| @lenv.set_var(var, vtx.new_vertex(genv, self)) }
|
|
363
|
+
if pivot_var
|
|
364
|
+
# Apply exclusion filters for else
|
|
365
|
+
filtered_else_vtx = original_pivot.new_vertex(genv, self)
|
|
343
366
|
@when_nodes.each do |when_node|
|
|
344
367
|
when_node.get_exclusion_conditions.each do |static_ret|
|
|
345
|
-
# 各when節の型を除外(negation)
|
|
346
368
|
filtered_else_vtx = IsAFilter.new(genv, self, filtered_else_vtx, true, static_ret).next_vtx
|
|
347
369
|
end
|
|
348
370
|
end
|
|
349
|
-
@lenv.set_var(
|
|
350
|
-
|
|
351
|
-
|
|
371
|
+
@lenv.set_var(pivot_var, filtered_else_vtx)
|
|
372
|
+
end
|
|
373
|
+
else_val = @else_clause.install(genv)
|
|
374
|
+
@changes.add_edge(genv, else_val, ret)
|
|
352
375
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
376
|
+
else_modified = {}
|
|
377
|
+
vars.each {|var| else_modified[var] = @lenv.get_var(var) }
|
|
378
|
+
branch_vtxs << [else_val, else_modified]
|
|
379
|
+
|
|
380
|
+
# Join all branches
|
|
381
|
+
vars.each do |var|
|
|
382
|
+
joined = Vertex.new(self)
|
|
383
|
+
branch_vtxs.each do |branch_val, modified|
|
|
384
|
+
vtx = BotFilter.new(genv, self, modified[var], branch_val).next_vtx
|
|
385
|
+
@changes.add_edge(genv, vtx, joined)
|
|
359
386
|
end
|
|
360
|
-
@
|
|
387
|
+
@lenv.set_var(var, joined)
|
|
361
388
|
end
|
|
362
389
|
|
|
390
|
+
# Cleanup
|
|
391
|
+
@lenv.locals.delete(:"*pivot") if pivot_var
|
|
392
|
+
|
|
363
393
|
ret
|
|
364
394
|
end
|
|
365
395
|
end
|
|
@@ -496,7 +526,7 @@ module TypeProf::Core
|
|
|
496
526
|
@arg.install(genv)
|
|
497
527
|
e_ret = @lenv.locals[:"*expected_method_ret"]
|
|
498
528
|
@lenv.add_return_box(@changes.add_escape_box(genv, @arg.ret)) if e_ret
|
|
499
|
-
Source.new(
|
|
529
|
+
Source.new(genv.bot_type)
|
|
500
530
|
end
|
|
501
531
|
end
|
|
502
532
|
|
|
@@ -681,7 +711,7 @@ module TypeProf::Core
|
|
|
681
711
|
end
|
|
682
712
|
|
|
683
713
|
def install0(genv)
|
|
684
|
-
Source.new(
|
|
714
|
+
Source.new(genv.bot_type)
|
|
685
715
|
end
|
|
686
716
|
end
|
|
687
717
|
|
|
@@ -72,7 +72,7 @@ module TypeProf::Core
|
|
|
72
72
|
def mname_code_range(name)
|
|
73
73
|
idx = @args.index(name.to_sym) # TODO: support string args
|
|
74
74
|
node = @raw_node.arguments.arguments[idx].location
|
|
75
|
-
|
|
75
|
+
@lenv.code_range_from_node(node)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def install0(genv)
|
|
@@ -86,6 +86,62 @@ module TypeProf::Core
|
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
class AttrWriterMetaNode < Node
|
|
90
|
+
def initialize(raw_node, lenv)
|
|
91
|
+
super(raw_node, lenv)
|
|
92
|
+
@args = []
|
|
93
|
+
raw_node.arguments.arguments.each do |raw_arg|
|
|
94
|
+
@args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
attr_reader :args
|
|
99
|
+
|
|
100
|
+
def attrs = { args: }
|
|
101
|
+
|
|
102
|
+
def mname_code_range(name)
|
|
103
|
+
idx = @args.index(name.to_sym)
|
|
104
|
+
node = @raw_node.arguments.arguments[idx].location
|
|
105
|
+
@lenv.code_range_from_node(node)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def define0(genv)
|
|
109
|
+
@args.map do |arg|
|
|
110
|
+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
|
|
111
|
+
mod.add_def(self)
|
|
112
|
+
mod
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def define_copy(genv)
|
|
117
|
+
@args.map do |arg|
|
|
118
|
+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
|
|
119
|
+
mod.add_def(self)
|
|
120
|
+
mod.remove_def(@prev_node)
|
|
121
|
+
mod
|
|
122
|
+
end
|
|
123
|
+
super(genv)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def undefine0(genv)
|
|
127
|
+
@args.each do |arg|
|
|
128
|
+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
|
|
129
|
+
mod.remove_def(self)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def install0(genv)
|
|
134
|
+
@args.zip(@static_ret) do |arg, ive|
|
|
135
|
+
vtx = Vertex.new(self)
|
|
136
|
+
@changes.add_edge(genv, vtx, ive.vtx)
|
|
137
|
+
ret_box = @changes.add_escape_box(genv, vtx)
|
|
138
|
+
f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
|
|
139
|
+
@changes.add_method_def_box(genv, @lenv.cref.cpath, false, :"#{ arg }=", f_args, [ret_box])
|
|
140
|
+
end
|
|
141
|
+
Source.new
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
89
145
|
class AttrAccessorMetaNode < Node
|
|
90
146
|
def initialize(raw_node, lenv)
|
|
91
147
|
super(raw_node, lenv)
|
|
@@ -104,7 +160,7 @@ module TypeProf::Core
|
|
|
104
160
|
def mname_code_range(name)
|
|
105
161
|
idx = @args.index(name.to_sym) # TODO: support string args
|
|
106
162
|
node = @raw_node.arguments.arguments[idx].location
|
|
107
|
-
|
|
163
|
+
@lenv.code_range_from_node(node)
|
|
108
164
|
end
|
|
109
165
|
|
|
110
166
|
def define0(genv)
|
|
@@ -146,5 +202,141 @@ module TypeProf::Core
|
|
|
146
202
|
Source.new
|
|
147
203
|
end
|
|
148
204
|
end
|
|
205
|
+
class ModuleFunctionMetaNode < Node
|
|
206
|
+
def install0(genv)
|
|
207
|
+
@lenv.module_function = true
|
|
208
|
+
Source.new
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
class StructNewNode < Node
|
|
213
|
+
def initialize(raw_node, members, kind, lenv)
|
|
214
|
+
super(raw_node, lenv)
|
|
215
|
+
case raw_node.type
|
|
216
|
+
when :constant_write_node
|
|
217
|
+
@static_cpath = lenv.cref.cpath + [raw_node.name]
|
|
218
|
+
when :constant_path_write_node
|
|
219
|
+
@static_cpath = AST.parse_cpath(raw_node.target, lenv.cref)
|
|
220
|
+
else
|
|
221
|
+
raise
|
|
222
|
+
end
|
|
223
|
+
@members = members
|
|
224
|
+
@kind = kind # :struct or :data
|
|
225
|
+
|
|
226
|
+
# Parse block body if present (Struct.new(:foo) do ... end)
|
|
227
|
+
raw_value = raw_node.value
|
|
228
|
+
if raw_value.block && raw_value.block.type == :block_node && raw_value.block.body
|
|
229
|
+
ncref = CRef.new(@static_cpath, :instance, nil, lenv.cref)
|
|
230
|
+
nlenv = LocalEnv.new(lenv.file_context, ncref, {}, [])
|
|
231
|
+
@block_body = AST.create_node(raw_value.block.body, nlenv)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
attr_reader :static_cpath, :members, :kind, :block_body
|
|
236
|
+
|
|
237
|
+
def subnodes = { block_body: }
|
|
238
|
+
def attrs = { static_cpath:, members:, kind: }
|
|
239
|
+
|
|
240
|
+
# Interface expected by MethodDefBox
|
|
241
|
+
def req_positionals = @kind == :struct ? @members : []
|
|
242
|
+
def opt_positionals = []
|
|
243
|
+
def rest_positionals = nil
|
|
244
|
+
def post_positionals = []
|
|
245
|
+
def req_keywords = @kind == :data ? @members : []
|
|
246
|
+
def opt_keywords = []
|
|
247
|
+
def rest_keywords = nil
|
|
248
|
+
def no_keywords = @kind == :struct
|
|
249
|
+
|
|
250
|
+
def define0(genv)
|
|
251
|
+
mod = genv.resolve_cpath(@static_cpath)
|
|
252
|
+
# add_module_def internally calls get_const(name).add_def(self)
|
|
253
|
+
cdef = mod.add_module_def(genv, self)
|
|
254
|
+
@members.each do |member|
|
|
255
|
+
ive = genv.resolve_ivar(@static_cpath, false, member)
|
|
256
|
+
ive.add_def(self)
|
|
257
|
+
end
|
|
258
|
+
@block_body.define(genv) if @block_body
|
|
259
|
+
cdef
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def define_copy(genv)
|
|
263
|
+
mod = genv.resolve_cpath(@static_cpath)
|
|
264
|
+
mod.add_module_def(genv, self)
|
|
265
|
+
mod.remove_module_def(genv, @prev_node)
|
|
266
|
+
@members.each do |member|
|
|
267
|
+
ive = genv.resolve_ivar(@static_cpath, false, member)
|
|
268
|
+
ive.add_def(self)
|
|
269
|
+
ive.remove_def(@prev_node)
|
|
270
|
+
end
|
|
271
|
+
super(genv)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def undefine0(genv)
|
|
275
|
+
mod = genv.resolve_cpath(@static_cpath)
|
|
276
|
+
mod.remove_module_def(genv, self)
|
|
277
|
+
@members.each do |member|
|
|
278
|
+
ive = genv.resolve_ivar(@static_cpath, false, member)
|
|
279
|
+
ive.remove_def(self)
|
|
280
|
+
end
|
|
281
|
+
@block_body.undefine(genv) if @block_body
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def install0(genv)
|
|
285
|
+
# Register the class singleton type as the constant value
|
|
286
|
+
mod_val = Source.new(Type::Singleton.new(genv, genv.resolve_cpath(@static_cpath)))
|
|
287
|
+
if @static_cpath
|
|
288
|
+
@changes.add_edge(genv, mod_val, @static_ret.vtx)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
cpath = @static_cpath
|
|
292
|
+
@members.each do |member|
|
|
293
|
+
# Use bare `:member` (not `:@member`) so the slot can't collide with a
|
|
294
|
+
# user-written @member ivar — Struct/Data fields are not real ivars.
|
|
295
|
+
ivar_box = @changes.add_ivar_read_box(genv, cpath, false, member)
|
|
296
|
+
ret_box = @changes.add_escape_box(genv, ivar_box.ret)
|
|
297
|
+
@changes.add_method_def_box(genv, cpath, false, member, FormalArguments::Empty, [ret_box])
|
|
298
|
+
|
|
299
|
+
if @kind == :struct
|
|
300
|
+
# attr_writer (Struct only, Data is frozen)
|
|
301
|
+
ive = genv.resolve_ivar(cpath, false, member)
|
|
302
|
+
vtx = Vertex.new(self)
|
|
303
|
+
@changes.add_edge(genv, vtx, ive.vtx)
|
|
304
|
+
writer_ret = @changes.add_escape_box(genv, vtx)
|
|
305
|
+
f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
|
|
306
|
+
@changes.add_method_def_box(genv, cpath, false, :"#{ member }=", f_args, [writer_ret])
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# initialize
|
|
311
|
+
init_vtxs = @members.map do |member|
|
|
312
|
+
ive = genv.resolve_ivar(cpath, false, member)
|
|
313
|
+
vtx = Vertex.new(self)
|
|
314
|
+
@changes.add_edge(genv, vtx, ive.vtx)
|
|
315
|
+
vtx
|
|
316
|
+
end
|
|
317
|
+
init_ret = @changes.add_escape_box(genv, Source.new(genv.nil_type))
|
|
318
|
+
if @kind == :struct
|
|
319
|
+
init_f_args = FormalArguments.new(init_vtxs, [], nil, [], [], [], nil, nil)
|
|
320
|
+
else
|
|
321
|
+
# Data.define uses keyword arguments
|
|
322
|
+
init_f_args = FormalArguments.new([], [], nil, [], init_vtxs, [], nil, nil)
|
|
323
|
+
end
|
|
324
|
+
@changes.add_method_def_box(genv, cpath, false, :initialize, init_f_args, [init_ret])
|
|
325
|
+
|
|
326
|
+
# Struct.[] is an alias for Struct.new
|
|
327
|
+
if @kind == :struct
|
|
328
|
+
self_ret = @changes.add_escape_box(genv, Source.new(Type::Instance.new(genv, genv.resolve_cpath(cpath), [])))
|
|
329
|
+
@changes.add_method_def_box(genv, cpath, true, :[], init_f_args, [self_ret])
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# Install block body (additional method definitions)
|
|
333
|
+
if @block_body
|
|
334
|
+
@block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv)
|
|
335
|
+
@block_body.install(genv)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
mod_val
|
|
339
|
+
end
|
|
340
|
+
end
|
|
149
341
|
end
|
|
150
342
|
end
|
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
module TypeProf::Core
|
|
2
2
|
class AST
|
|
3
3
|
def self.get_rbs_comment_before(raw_node, lenv)
|
|
4
|
-
comments =
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
comments = lenv.file_context.comments
|
|
5
|
+
return nil unless comments
|
|
6
|
+
node_line = raw_node.location.start_line
|
|
7
|
+
last_comment_index = comments.bsearch_index {|c| c.location.start_line >= node_line } || comments.size
|
|
7
8
|
rbs_comments = []
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
lineno -= 1
|
|
9
|
+
expected_line = node_line - 1
|
|
10
|
+
(last_comment_index - 1).downto(0) do |i|
|
|
11
11
|
comment = comments[i]
|
|
12
|
+
break unless comment.location.start_line == expected_line && comment.location.slice.start_with?("#:")
|
|
12
13
|
comment_loc = comment.location
|
|
13
14
|
comment_text = comment_loc.slice
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
else
|
|
17
|
-
break
|
|
18
|
-
end
|
|
15
|
+
rbs_comments[comment_loc.start_line - 1] = " " * (comment_loc.start_column + 2) + comment_text[2..]
|
|
16
|
+
expected_line -= 1
|
|
19
17
|
end
|
|
20
18
|
return nil if rbs_comments.empty?
|
|
21
19
|
rbs_comments = rbs_comments.map {|line| line || "" }.join("\n")
|
|
22
20
|
method_type = RBS::Parser.parse_method_type(rbs_comments)
|
|
23
21
|
if method_type
|
|
24
22
|
AST.create_rbs_func_type(method_type, method_type.type_params, method_type.block, lenv)
|
|
25
|
-
else
|
|
26
|
-
nil
|
|
27
23
|
end
|
|
28
24
|
rescue RBS::ParsingError
|
|
29
25
|
# TODO: report the error
|
|
@@ -34,23 +30,32 @@ module TypeProf::Core
|
|
|
34
30
|
unless raw_args
|
|
35
31
|
return {
|
|
36
32
|
req_positionals: [],
|
|
33
|
+
req_multi_targets: {},
|
|
37
34
|
opt_positionals: [],
|
|
38
35
|
opt_positional_defaults: [],
|
|
39
36
|
rest_positionals: nil,
|
|
40
37
|
post_positionals: [],
|
|
38
|
+
post_multi_targets: {},
|
|
41
39
|
req_keywords: [],
|
|
42
40
|
opt_keywords: [],
|
|
43
41
|
opt_keyword_defaults: [],
|
|
44
42
|
rest_keywords: nil,
|
|
43
|
+
no_keywords: false,
|
|
45
44
|
block: nil,
|
|
46
45
|
}
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
args_code_ranges = []
|
|
50
49
|
req_positionals = []
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
req_multi_targets = {}
|
|
51
|
+
raw_args.requireds.each_with_index do |n, i|
|
|
52
|
+
args_code_ranges << lenv.code_range_from_node(n.location)
|
|
53
|
+
if n.is_a?(Prism::MultiTargetNode)
|
|
54
|
+
req_positionals << nil
|
|
55
|
+
req_multi_targets[i] = n
|
|
56
|
+
else
|
|
57
|
+
req_positionals << n.name
|
|
58
|
+
end
|
|
54
59
|
end
|
|
55
60
|
|
|
56
61
|
# pre_init = args[1]
|
|
@@ -62,13 +67,22 @@ module TypeProf::Core
|
|
|
62
67
|
opt_positional_defaults << AST.create_node(n.value, lenv)
|
|
63
68
|
end
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
post_multi_targets = {}
|
|
71
|
+
post_positionals = raw_args.posts.each_with_index.map do |n, i|
|
|
72
|
+
if n.is_a?(Prism::MultiTargetNode)
|
|
73
|
+
post_multi_targets[i] = n
|
|
74
|
+
nil
|
|
75
|
+
else
|
|
76
|
+
n.name
|
|
77
|
+
end
|
|
78
|
+
end
|
|
66
79
|
|
|
67
80
|
rest_positionals = raw_args.rest ? (raw_args.rest.name || :"*anonymous_rest") : nil
|
|
68
81
|
|
|
69
82
|
req_keywords = []
|
|
70
83
|
opt_keywords = []
|
|
71
84
|
opt_keyword_defaults = []
|
|
85
|
+
no_keywords = false
|
|
72
86
|
|
|
73
87
|
raw_args.keywords.each do |kw|
|
|
74
88
|
case kw.type
|
|
@@ -88,7 +102,7 @@ module TypeProf::Core
|
|
|
88
102
|
rest_positionals = :"..."
|
|
89
103
|
rest_keywords = :"..."
|
|
90
104
|
when Prism::NoKeywordsParameterNode
|
|
91
|
-
|
|
105
|
+
no_keywords = true
|
|
92
106
|
when nil
|
|
93
107
|
# nothing to do
|
|
94
108
|
else
|
|
@@ -99,14 +113,17 @@ module TypeProf::Core
|
|
|
99
113
|
|
|
100
114
|
{
|
|
101
115
|
req_positionals:,
|
|
116
|
+
req_multi_targets:,
|
|
102
117
|
opt_positionals:,
|
|
103
118
|
opt_positional_defaults:,
|
|
104
119
|
rest_positionals:,
|
|
105
120
|
post_positionals:,
|
|
121
|
+
post_multi_targets:,
|
|
106
122
|
req_keywords:,
|
|
107
123
|
opt_keywords:,
|
|
108
124
|
opt_keyword_defaults:,
|
|
109
125
|
rest_keywords:,
|
|
126
|
+
no_keywords:,
|
|
110
127
|
block:,
|
|
111
128
|
args_code_ranges:
|
|
112
129
|
}
|
|
@@ -118,7 +135,7 @@ module TypeProf::Core
|
|
|
118
135
|
# TODO: warn "def self.foo" in a metaclass
|
|
119
136
|
singleton = !!raw_node.receiver || lenv.cref.scope_level == :metaclass
|
|
120
137
|
mid = raw_node.name
|
|
121
|
-
mid_code_range =
|
|
138
|
+
mid_code_range = lenv.code_range_from_node(raw_node.name_loc)
|
|
122
139
|
@tbl = raw_node.locals
|
|
123
140
|
raw_args = raw_node.parameters
|
|
124
141
|
raw_body = raw_node.body
|
|
@@ -130,7 +147,7 @@ module TypeProf::Core
|
|
|
130
147
|
@mid_code_range = mid_code_range
|
|
131
148
|
|
|
132
149
|
ncref = CRef.new(lenv.cref.cpath, @singleton ? :class : :instance, @mid, lenv.cref)
|
|
133
|
-
nlenv = LocalEnv.new(@lenv.
|
|
150
|
+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
|
|
134
151
|
if raw_body
|
|
135
152
|
@body = AST.create_node(raw_body, nlenv)
|
|
136
153
|
else
|
|
@@ -141,14 +158,17 @@ module TypeProf::Core
|
|
|
141
158
|
|
|
142
159
|
h = AST.parse_params(@tbl, raw_args, nlenv)
|
|
143
160
|
@req_positionals = h[:req_positionals]
|
|
161
|
+
@req_multi_targets = h[:req_multi_targets]
|
|
144
162
|
@opt_positionals = h[:opt_positionals]
|
|
145
163
|
@opt_positional_defaults = h[:opt_positional_defaults]
|
|
146
164
|
@rest_positionals = h[:rest_positionals]
|
|
147
165
|
@post_positionals = h[:post_positionals]
|
|
166
|
+
@post_multi_targets = h[:post_multi_targets]
|
|
148
167
|
@req_keywords = h[:req_keywords]
|
|
149
168
|
@opt_keywords = h[:opt_keywords]
|
|
150
169
|
@opt_keyword_defaults = h[:opt_keyword_defaults]
|
|
151
170
|
@rest_keywords = h[:rest_keywords]
|
|
171
|
+
@no_keywords = h[:no_keywords]
|
|
152
172
|
@block = h[:block]
|
|
153
173
|
@args_code_ranges = h[:args_code_ranges] || []
|
|
154
174
|
|
|
@@ -168,6 +188,7 @@ module TypeProf::Core
|
|
|
168
188
|
attr_reader :opt_keywords
|
|
169
189
|
attr_reader :opt_keyword_defaults
|
|
170
190
|
attr_reader :rest_keywords
|
|
191
|
+
attr_reader :no_keywords
|
|
171
192
|
attr_reader :block
|
|
172
193
|
attr_reader :body
|
|
173
194
|
attr_reader :rbs_method_type
|
|
@@ -191,6 +212,7 @@ module TypeProf::Core
|
|
|
191
212
|
req_keywords:,
|
|
192
213
|
opt_keywords:,
|
|
193
214
|
rest_keywords:,
|
|
215
|
+
no_keywords:,
|
|
194
216
|
block:,
|
|
195
217
|
reusable:,
|
|
196
218
|
}
|
|
@@ -219,6 +241,8 @@ module TypeProf::Core
|
|
|
219
241
|
opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
|
|
220
242
|
rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
|
|
221
243
|
post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
|
|
244
|
+
install_multi_targets(genv, @req_multi_targets, req_positionals)
|
|
245
|
+
install_multi_targets(genv, @post_multi_targets, post_positionals)
|
|
222
246
|
req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
|
|
223
247
|
opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
|
|
224
248
|
rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
|
|
@@ -247,6 +271,23 @@ module TypeProf::Core
|
|
|
247
271
|
block = @body.lenv.new_var(:"*given_block", self)
|
|
248
272
|
end
|
|
249
273
|
|
|
274
|
+
forward_opt_positionals = @opt_positionals.map do
|
|
275
|
+
elem_vtx = Vertex.new(self)
|
|
276
|
+
[Source.new(genv.gen_ary_type(elem_vtx)), elem_vtx]
|
|
277
|
+
end
|
|
278
|
+
forward_opt_keywords = @opt_keywords.map {|_name| Vertex.new(self) }
|
|
279
|
+
@body.lenv.forward_args = ForwardingArguments.new(
|
|
280
|
+
req_positionals,
|
|
281
|
+
forward_opt_positionals.map(&:first),
|
|
282
|
+
forward_opt_positionals.map(&:last),
|
|
283
|
+
rest_positionals,
|
|
284
|
+
post_positionals,
|
|
285
|
+
@req_keywords.zip(req_keywords),
|
|
286
|
+
@opt_keywords.zip(forward_opt_keywords),
|
|
287
|
+
rest_keywords,
|
|
288
|
+
block,
|
|
289
|
+
)
|
|
290
|
+
|
|
250
291
|
if @body
|
|
251
292
|
@body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
|
|
252
293
|
@body.install(genv)
|
|
@@ -265,10 +306,23 @@ module TypeProf::Core
|
|
|
265
306
|
)
|
|
266
307
|
|
|
267
308
|
@changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)
|
|
309
|
+
if @lenv.module_function && !@singleton
|
|
310
|
+
@changes.add_method_def_box(genv, @lenv.cref.cpath, true, @mid, f_args, @body.lenv.return_boxes)
|
|
311
|
+
end
|
|
268
312
|
|
|
269
313
|
Source.new(Type::Symbol.new(genv, @mid))
|
|
270
314
|
end
|
|
271
315
|
|
|
316
|
+
def install_multi_targets(genv, multi_targets, positionals)
|
|
317
|
+
multi_targets.each do |idx, raw_multi_target|
|
|
318
|
+
param_vtx = positionals[idx]
|
|
319
|
+
lefts = raw_multi_target.lefts.map do |n|
|
|
320
|
+
@body.lenv.new_var(n.is_a?(Prism::MultiTargetNode) ? nil : n.name, self)
|
|
321
|
+
end
|
|
322
|
+
@changes.add_masgn_box(genv, param_vtx, lefts, nil, nil)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
272
326
|
def last_stmt_code_range
|
|
273
327
|
if @body
|
|
274
328
|
if @body.is_a?(AST::StatementsNode)
|
|
@@ -6,7 +6,7 @@ module TypeProf::Core
|
|
|
6
6
|
stmts = raw_node.body
|
|
7
7
|
@stmts = stmts.map.with_index do |n, i|
|
|
8
8
|
if n
|
|
9
|
-
AST.create_node(n, lenv, i == stmts.length - 1 ? use_result : false)
|
|
9
|
+
AST.create_node(n, lenv, i == stmts.length - 1 ? use_result : false, true)
|
|
10
10
|
else
|
|
11
11
|
last = code_range.last
|
|
12
12
|
DummyNilNode.new(TypeProf::CodeRange.new(last, last), lenv)
|
|
@@ -256,28 +256,48 @@ module TypeProf::Core
|
|
|
256
256
|
vtx = @expr.install(genv)
|
|
257
257
|
|
|
258
258
|
a_args = ActualArguments.new([], [], nil, nil)
|
|
259
|
-
|
|
259
|
+
to_a_vtx = @changes.add_method_call_box(genv, vtx, :to_a, a_args, false, suppress_errors: true).ret
|
|
260
260
|
|
|
261
|
-
@changes.add_splat_box(genv, vtx).ret
|
|
261
|
+
@changes.add_splat_box(genv, to_a_vtx, nil, vtx).ret
|
|
262
262
|
end
|
|
263
263
|
end
|
|
264
264
|
|
|
265
265
|
class ForNode < Node
|
|
266
266
|
def initialize(raw_node, lenv)
|
|
267
267
|
super(raw_node, lenv)
|
|
268
|
-
|
|
269
|
-
# raw_node.index
|
|
268
|
+
@index = AST.create_target_node(raw_node.index, lenv)
|
|
270
269
|
@expr = AST.create_node(raw_node.collection, lenv)
|
|
271
270
|
@body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.new(code_range.last, code_range.last), lenv)
|
|
272
271
|
end
|
|
273
272
|
|
|
274
|
-
attr_reader :expr, :body
|
|
273
|
+
attr_reader :index, :expr, :body
|
|
275
274
|
|
|
276
|
-
def subnodes = { expr:, body: }
|
|
275
|
+
def subnodes = { index:, expr:, body: }
|
|
277
276
|
|
|
278
277
|
def install0(genv)
|
|
279
278
|
@expr.install(genv)
|
|
279
|
+
|
|
280
|
+
vars = []
|
|
281
|
+
@index.modified_vars(@lenv.locals.keys, vars)
|
|
282
|
+
@body.modified_vars(@lenv.locals.keys, vars)
|
|
283
|
+
vars.uniq!
|
|
284
|
+
|
|
285
|
+
old_vtxs = {}
|
|
286
|
+
vars.each do |var|
|
|
287
|
+
vtx = @lenv.get_var(var)
|
|
288
|
+
nvtx = vtx.new_vertex(genv, self)
|
|
289
|
+
old_vtxs[var] = nvtx
|
|
290
|
+
@lenv.set_var(var, nvtx)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
@index.install(genv)
|
|
280
294
|
@body.install(genv)
|
|
295
|
+
|
|
296
|
+
vars.each do |var|
|
|
297
|
+
@changes.add_edge(genv, @lenv.get_var(var), old_vtxs[var])
|
|
298
|
+
@lenv.set_var(var, old_vtxs[var])
|
|
299
|
+
end
|
|
300
|
+
|
|
281
301
|
Source.new(genv.nil_type)
|
|
282
302
|
end
|
|
283
303
|
end
|