typeprof 0.31.1 → 0.33.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 +31 -6
- data/lib/typeprof/core/ast/call.rb +120 -39
- data/lib/typeprof/core/ast/const.rb +22 -11
- data/lib/typeprof/core/ast/control.rb +62 -32
- data/lib/typeprof/core/ast/meta.rb +279 -14
- data/lib/typeprof/core/ast/method.rb +82 -24
- data/lib/typeprof/core/ast/misc.rb +41 -12
- data/lib/typeprof/core/ast/module.rb +38 -4
- data/lib/typeprof/core/ast/pattern.rb +51 -23
- data/lib/typeprof/core/ast/sig_decl.rb +141 -27
- data/lib/typeprof/core/ast/sig_type.rb +113 -32
- data/lib/typeprof/core/ast/value.rb +14 -6
- data/lib/typeprof/core/ast/variable.rb +17 -4
- data/lib/typeprof/core/ast.rb +98 -14
- data/lib/typeprof/core/builtin.rb +184 -12
- data/lib/typeprof/core/env/method.rb +343 -6
- data/lib/typeprof/core/env/method_entity.rb +18 -15
- data/lib/typeprof/core/env/module_entity.rb +116 -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 +113 -23
- data/lib/typeprof/core/graph/box.rb +508 -63
- data/lib/typeprof/core/graph/change_set.rb +64 -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 +340 -24
- 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
|
@@ -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
|
-
|
|
138
|
+
mid_code_range_loc = raw_node.name_loc
|
|
122
139
|
@tbl = raw_node.locals
|
|
123
140
|
raw_args = raw_node.parameters
|
|
124
141
|
raw_body = raw_node.body
|
|
@@ -127,10 +144,10 @@ module TypeProf::Core
|
|
|
127
144
|
|
|
128
145
|
@singleton = singleton
|
|
129
146
|
@mid = mid
|
|
130
|
-
@
|
|
147
|
+
@mid_code_range_loc = mid_code_range_loc
|
|
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
|
|
|
@@ -157,7 +177,11 @@ module TypeProf::Core
|
|
|
157
177
|
@reusable = !use_result
|
|
158
178
|
end
|
|
159
179
|
|
|
160
|
-
attr_reader :singleton, :mid
|
|
180
|
+
attr_reader :singleton, :mid
|
|
181
|
+
|
|
182
|
+
def mid_code_range
|
|
183
|
+
@mid_code_range ||= @lenv.code_range_from_node(@mid_code_range_loc) if @mid_code_range_loc
|
|
184
|
+
end
|
|
161
185
|
attr_reader :tbl
|
|
162
186
|
attr_reader :req_positionals
|
|
163
187
|
attr_reader :opt_positionals
|
|
@@ -168,6 +192,7 @@ module TypeProf::Core
|
|
|
168
192
|
attr_reader :opt_keywords
|
|
169
193
|
attr_reader :opt_keyword_defaults
|
|
170
194
|
attr_reader :rest_keywords
|
|
195
|
+
attr_reader :no_keywords
|
|
171
196
|
attr_reader :block
|
|
172
197
|
attr_reader :body
|
|
173
198
|
attr_reader :rbs_method_type
|
|
@@ -182,7 +207,6 @@ module TypeProf::Core
|
|
|
182
207
|
def attrs = {
|
|
183
208
|
singleton:,
|
|
184
209
|
mid:,
|
|
185
|
-
mid_code_range:,
|
|
186
210
|
tbl:,
|
|
187
211
|
req_positionals:,
|
|
188
212
|
opt_positionals:,
|
|
@@ -191,11 +215,12 @@ module TypeProf::Core
|
|
|
191
215
|
req_keywords:,
|
|
192
216
|
opt_keywords:,
|
|
193
217
|
rest_keywords:,
|
|
218
|
+
no_keywords:,
|
|
194
219
|
block:,
|
|
195
220
|
reusable:,
|
|
196
221
|
}
|
|
197
222
|
|
|
198
|
-
def mname_code_range(_name) =
|
|
223
|
+
def mname_code_range(_name) = mid_code_range
|
|
199
224
|
|
|
200
225
|
def define(genv) # NOT define0
|
|
201
226
|
return define_copy(genv) if @prev_node && @reusable
|
|
@@ -219,6 +244,8 @@ module TypeProf::Core
|
|
|
219
244
|
opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
|
|
220
245
|
rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
|
|
221
246
|
post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
|
|
247
|
+
install_multi_targets(genv, @req_multi_targets, req_positionals)
|
|
248
|
+
install_multi_targets(genv, @post_multi_targets, post_positionals)
|
|
222
249
|
req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
|
|
223
250
|
opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
|
|
224
251
|
rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
|
|
@@ -247,6 +274,24 @@ module TypeProf::Core
|
|
|
247
274
|
block = @body.lenv.new_var(:"*given_block", self)
|
|
248
275
|
end
|
|
249
276
|
|
|
277
|
+
forward_opt_positionals = @opt_positionals.map { Vertex.new(self) }
|
|
278
|
+
forward_rest_positionals = @rest_positionals ? Vertex.new(self) : nil
|
|
279
|
+
forward_opt_keywords = @opt_keywords.map {|_name| Vertex.new(self) }
|
|
280
|
+
forward_rest_keywords = @rest_keywords ? Vertex.new(self) : nil
|
|
281
|
+
forward_block = Vertex.new(self)
|
|
282
|
+
forward_activation = Vertex.new(self)
|
|
283
|
+
@body.lenv.forward_args = ForwardingArguments.new(
|
|
284
|
+
req_positionals,
|
|
285
|
+
forward_opt_positionals,
|
|
286
|
+
forward_rest_positionals,
|
|
287
|
+
post_positionals,
|
|
288
|
+
@req_keywords.zip(req_keywords),
|
|
289
|
+
@opt_keywords.zip(forward_opt_keywords),
|
|
290
|
+
forward_rest_keywords,
|
|
291
|
+
forward_block,
|
|
292
|
+
forward_activation,
|
|
293
|
+
)
|
|
294
|
+
|
|
250
295
|
if @body
|
|
251
296
|
@body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
|
|
252
297
|
@body.install(genv)
|
|
@@ -265,10 +310,23 @@ module TypeProf::Core
|
|
|
265
310
|
)
|
|
266
311
|
|
|
267
312
|
@changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)
|
|
313
|
+
if @lenv.module_function && !@singleton
|
|
314
|
+
@changes.add_method_def_box(genv, @lenv.cref.cpath, true, @mid, f_args, @body.lenv.return_boxes)
|
|
315
|
+
end
|
|
268
316
|
|
|
269
317
|
Source.new(Type::Symbol.new(genv, @mid))
|
|
270
318
|
end
|
|
271
319
|
|
|
320
|
+
def install_multi_targets(genv, multi_targets, positionals)
|
|
321
|
+
multi_targets.each do |idx, raw_multi_target|
|
|
322
|
+
param_vtx = positionals[idx]
|
|
323
|
+
lefts = raw_multi_target.lefts.map do |n|
|
|
324
|
+
@body.lenv.new_var(n.is_a?(Prism::MultiTargetNode) ? nil : n.name, self)
|
|
325
|
+
end
|
|
326
|
+
@changes.add_masgn_box(genv, param_vtx, lefts, nil, nil)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
272
330
|
def last_stmt_code_range
|
|
273
331
|
if @body
|
|
274
332
|
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,59 @@ module TypeProf::Core
|
|
|
256
256
|
vtx = @expr.install(genv)
|
|
257
257
|
|
|
258
258
|
a_args = ActualArguments.new([], [], nil, nil)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
# Receiver types with no `to_a` are collected here, so that each union
|
|
260
|
+
# member can independently fall back to wrapping itself as `[x]`.
|
|
261
|
+
unresolved_recv = Vertex.new(self)
|
|
262
|
+
to_a_box = @changes.add_method_call_box(
|
|
263
|
+
genv,
|
|
264
|
+
vtx,
|
|
265
|
+
:to_a,
|
|
266
|
+
a_args,
|
|
267
|
+
false,
|
|
268
|
+
suppress_errors: true,
|
|
269
|
+
unresolved_recv: unresolved_recv,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
@changes.add_splat_box(genv, to_a_box.ret, nil, unresolved_recv).ret
|
|
262
273
|
end
|
|
263
274
|
end
|
|
264
275
|
|
|
265
276
|
class ForNode < Node
|
|
266
277
|
def initialize(raw_node, lenv)
|
|
267
278
|
super(raw_node, lenv)
|
|
268
|
-
|
|
269
|
-
# raw_node.index
|
|
279
|
+
@index = AST.create_target_node(raw_node.index, lenv)
|
|
270
280
|
@expr = AST.create_node(raw_node.collection, lenv)
|
|
271
281
|
@body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.new(code_range.last, code_range.last), lenv)
|
|
272
282
|
end
|
|
273
283
|
|
|
274
|
-
attr_reader :expr, :body
|
|
284
|
+
attr_reader :index, :expr, :body
|
|
275
285
|
|
|
276
|
-
def subnodes = { expr:, body: }
|
|
286
|
+
def subnodes = { index:, expr:, body: }
|
|
277
287
|
|
|
278
288
|
def install0(genv)
|
|
279
289
|
@expr.install(genv)
|
|
290
|
+
|
|
291
|
+
vars = []
|
|
292
|
+
@index.modified_vars(@lenv.locals.keys, vars)
|
|
293
|
+
@body.modified_vars(@lenv.locals.keys, vars)
|
|
294
|
+
vars.uniq!
|
|
295
|
+
|
|
296
|
+
old_vtxs = {}
|
|
297
|
+
vars.each do |var|
|
|
298
|
+
vtx = @lenv.get_var(var)
|
|
299
|
+
nvtx = vtx.new_vertex(genv, self)
|
|
300
|
+
old_vtxs[var] = nvtx
|
|
301
|
+
@lenv.set_var(var, nvtx)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
@index.install(genv)
|
|
280
305
|
@body.install(genv)
|
|
306
|
+
|
|
307
|
+
vars.each do |var|
|
|
308
|
+
@changes.add_edge(genv, @lenv.get_var(var), old_vtxs[var])
|
|
309
|
+
@lenv.set_var(var, old_vtxs[var])
|
|
310
|
+
end
|
|
311
|
+
|
|
281
312
|
Source.new(genv.nil_type)
|
|
282
313
|
end
|
|
283
314
|
end
|
|
@@ -312,8 +343,7 @@ module TypeProf::Core
|
|
|
312
343
|
def subnodes = { value:, pat: }
|
|
313
344
|
|
|
314
345
|
def install0(genv)
|
|
315
|
-
@value.install(genv)
|
|
316
|
-
@pat.install(genv)
|
|
346
|
+
@pat.install_pattern(genv, @value.install(genv))
|
|
317
347
|
Source.new(genv.nil_type)
|
|
318
348
|
end
|
|
319
349
|
end
|
|
@@ -330,8 +360,7 @@ module TypeProf::Core
|
|
|
330
360
|
def subnodes = { value:, pat: }
|
|
331
361
|
|
|
332
362
|
def install0(genv)
|
|
333
|
-
@value.install(genv)
|
|
334
|
-
@pat.install(genv)
|
|
363
|
+
@pat.install_pattern(genv, @value.install(genv))
|
|
335
364
|
Source.new(genv.true_type, genv.false_type)
|
|
336
365
|
end
|
|
337
366
|
end
|
|
@@ -12,17 +12,21 @@ module TypeProf::Core
|
|
|
12
12
|
|
|
13
13
|
if @static_cpath
|
|
14
14
|
ncref = CRef.new(@static_cpath, meta ? :metaclass : :class, nil, lenv.cref)
|
|
15
|
-
nlenv = LocalEnv.new(@lenv.
|
|
15
|
+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
|
|
16
16
|
@body = raw_scope ? AST.create_node(raw_scope, nlenv, use_result) : DummyNilNode.new(code_range, lenv)
|
|
17
17
|
else
|
|
18
18
|
@body = nil
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
@
|
|
21
|
+
@cname_code_range_loc = meta ? nil : raw_node.constant_path
|
|
22
22
|
@mod_cdef = nil
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
attr_reader :tbl, :cpath, :static_cpath, :
|
|
25
|
+
attr_reader :tbl, :cpath, :static_cpath, :body
|
|
26
|
+
|
|
27
|
+
def cname_code_range
|
|
28
|
+
@cname_code_range ||= @lenv.code_range_from_node(@cname_code_range_loc) if @cname_code_range_loc
|
|
29
|
+
end
|
|
26
30
|
|
|
27
31
|
def subnodes = { cpath:, body: }
|
|
28
32
|
def attrs = { static_cpath:, tbl: }
|
|
@@ -89,7 +93,22 @@ module TypeProf::Core
|
|
|
89
93
|
def initialize(raw_node, lenv, use_result)
|
|
90
94
|
super(raw_node, lenv, raw_node.constant_path, false, raw_node.body, use_result)
|
|
91
95
|
raw_superclass = raw_node.superclass
|
|
92
|
-
|
|
96
|
+
if raw_superclass
|
|
97
|
+
# In Ruby, the superclass expression is evaluated before the class constant
|
|
98
|
+
# is created. When the superclass is a bare constant with the same name as
|
|
99
|
+
# the class being defined (e.g., `class Foo < Foo` inside a module), use the
|
|
100
|
+
# outer scope to avoid resolving to the class itself.
|
|
101
|
+
if @static_cpath && lenv.cref.outer &&
|
|
102
|
+
raw_superclass.type == :constant_read_node &&
|
|
103
|
+
raw_superclass.name == @static_cpath.last
|
|
104
|
+
slenv = LocalEnv.new(lenv.file_context, lenv.cref.outer, {}, [])
|
|
105
|
+
@superclass_cpath = AST.create_node(raw_superclass, slenv)
|
|
106
|
+
else
|
|
107
|
+
@superclass_cpath = AST.create_node(raw_superclass, lenv)
|
|
108
|
+
end
|
|
109
|
+
else
|
|
110
|
+
@superclass_cpath = nil
|
|
111
|
+
end
|
|
93
112
|
end
|
|
94
113
|
|
|
95
114
|
attr_reader :superclass_cpath
|
|
@@ -113,6 +132,21 @@ module TypeProf::Core
|
|
|
113
132
|
|
|
114
133
|
def install0(genv)
|
|
115
134
|
@superclass_cpath.install(genv) if @superclass_cpath
|
|
135
|
+
if @static_cpath && @superclass_cpath
|
|
136
|
+
const_read = @superclass_cpath.static_ret
|
|
137
|
+
if const_read && const_read.cpath
|
|
138
|
+
super_mod = genv.resolve_cpath(const_read.cpath)
|
|
139
|
+
self_mod = genv.resolve_cpath(@static_cpath)
|
|
140
|
+
mod = super_mod
|
|
141
|
+
while mod
|
|
142
|
+
if mod == self_mod
|
|
143
|
+
@changes.add_diagnostic(:code_range, "circular inheritance", @superclass_cpath)
|
|
144
|
+
break
|
|
145
|
+
end
|
|
146
|
+
mod = mod.superclass
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
116
150
|
super(genv)
|
|
117
151
|
end
|
|
118
152
|
end
|
|
@@ -22,14 +22,19 @@ module TypeProf::Core
|
|
|
22
22
|
def attrs = { rest: }
|
|
23
23
|
def subnodes = { requireds:, rest_pattern:, posts: }
|
|
24
24
|
|
|
25
|
-
def
|
|
26
|
-
@requireds.
|
|
27
|
-
pat.
|
|
25
|
+
def install_pattern0(genv, subject)
|
|
26
|
+
@requireds.each_with_index do |pat, i|
|
|
27
|
+
pat.install_pattern(genv, @changes.add_splat_box(genv, subject, i).ret)
|
|
28
|
+
end
|
|
29
|
+
if @rest_pattern
|
|
30
|
+
elem = @changes.add_splat_box(genv, subject).ret
|
|
31
|
+
@rest_pattern.install_pattern(genv, Source.new(genv.gen_ary_type(elem)))
|
|
28
32
|
end
|
|
29
|
-
@rest_pattern.install(genv) if @rest_pattern
|
|
30
33
|
@posts.each do |pat|
|
|
31
|
-
|
|
34
|
+
# TODO: precise indices for post elements (those after `*rest`)
|
|
35
|
+
pat.install_pattern(genv, @changes.add_splat_box(genv, subject).ret)
|
|
32
36
|
end
|
|
37
|
+
subject
|
|
33
38
|
end
|
|
34
39
|
end
|
|
35
40
|
|
|
@@ -39,7 +44,14 @@ module TypeProf::Core
|
|
|
39
44
|
@keys = raw_node.elements.map {|raw_assoc| raw_assoc.key.value.to_sym }
|
|
40
45
|
@values = raw_node.elements.map {|raw_assoc| AST.create_pattern_node(raw_assoc.value, lenv) }
|
|
41
46
|
@rest = !!raw_node.rest
|
|
42
|
-
@rest_pattern =
|
|
47
|
+
@rest_pattern = case raw_node.rest
|
|
48
|
+
when Prism::AssocSplatNode
|
|
49
|
+
AST.create_pattern_node(raw_node.rest.value, lenv) if raw_node.rest.value
|
|
50
|
+
when Prism::NoKeywordsParameterNode, nil
|
|
51
|
+
nil
|
|
52
|
+
else
|
|
53
|
+
raise
|
|
54
|
+
end
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
attr_reader :keys, :values, :rest, :rest_pattern
|
|
@@ -47,32 +59,37 @@ module TypeProf::Core
|
|
|
47
59
|
def attrs = { keys:, rest: }
|
|
48
60
|
def subnodes = { values:, rest_pattern: }
|
|
49
61
|
|
|
50
|
-
def
|
|
62
|
+
def install_pattern0(genv, subject)
|
|
63
|
+
# TODO: extract each key's value type from `subject` (captures stay untyped for now)
|
|
51
64
|
@values.each do |pat|
|
|
52
|
-
pat.
|
|
65
|
+
pat.install_pattern(genv, Vertex.new(self))
|
|
53
66
|
end
|
|
54
|
-
@rest_pattern.
|
|
67
|
+
@rest_pattern.install_pattern(genv, Vertex.new(self)) if @rest_pattern
|
|
68
|
+
subject
|
|
55
69
|
end
|
|
56
70
|
end
|
|
57
71
|
|
|
58
72
|
class FindPatternNode < Node
|
|
59
73
|
def initialize(raw_node, lenv)
|
|
60
74
|
super(raw_node, lenv)
|
|
61
|
-
@left = raw_node.left ? AST.create_pattern_node(raw_node.left.expression, lenv) : nil
|
|
75
|
+
@left = raw_node.left.expression ? AST.create_pattern_node(raw_node.left.expression, lenv) : nil
|
|
62
76
|
@requireds = raw_node.requireds.map {|raw_elem| AST.create_pattern_node(raw_elem, lenv) }
|
|
63
|
-
@right = raw_node.right ? AST.create_pattern_node(raw_node.right.expression, lenv) : nil
|
|
77
|
+
@right = raw_node.right.expression ? AST.create_pattern_node(raw_node.right.expression, lenv) : nil
|
|
64
78
|
end
|
|
65
79
|
|
|
66
80
|
attr_reader :left, :requireds, :right
|
|
67
81
|
|
|
68
82
|
def subnodes = { left:, requireds:, right: }
|
|
69
83
|
|
|
70
|
-
def
|
|
71
|
-
@
|
|
84
|
+
def install_pattern0(genv, subject)
|
|
85
|
+
elem = @changes.add_splat_box(genv, subject).ret
|
|
86
|
+
rest_ary = Source.new(genv.gen_ary_type(elem))
|
|
87
|
+
@left.install_pattern(genv, rest_ary) if @left
|
|
72
88
|
@requireds.each do |pat|
|
|
73
|
-
pat.
|
|
89
|
+
pat.install_pattern(genv, elem)
|
|
74
90
|
end
|
|
75
|
-
@right.
|
|
91
|
+
@right.install_pattern(genv, rest_ary) if @right
|
|
92
|
+
subject
|
|
76
93
|
end
|
|
77
94
|
end
|
|
78
95
|
|
|
@@ -87,9 +104,10 @@ module TypeProf::Core
|
|
|
87
104
|
|
|
88
105
|
def subnodes = { left:, right: }
|
|
89
106
|
|
|
90
|
-
def
|
|
91
|
-
@left.
|
|
92
|
-
@right.
|
|
107
|
+
def install_pattern0(genv, subject)
|
|
108
|
+
@left.install_pattern(genv, subject)
|
|
109
|
+
@right.install_pattern(genv, subject)
|
|
110
|
+
subject
|
|
93
111
|
end
|
|
94
112
|
end
|
|
95
113
|
|
|
@@ -104,9 +122,18 @@ module TypeProf::Core
|
|
|
104
122
|
|
|
105
123
|
def subnodes = { value:, target: }
|
|
106
124
|
|
|
107
|
-
def
|
|
108
|
-
@value.
|
|
109
|
-
|
|
125
|
+
def install_pattern0(genv, subject)
|
|
126
|
+
@value.install_pattern(genv, subject)
|
|
127
|
+
# For `Const => var`, narrow the capture by the class, as `when Const` does
|
|
128
|
+
narrowed =
|
|
129
|
+
if @value.is_a?(ConstantReadNode) && @value.static_ret
|
|
130
|
+
filtered = subject.new_vertex(genv, self)
|
|
131
|
+
IsAFilter.new(genv, self, filtered, false, @value.static_ret).next_vtx
|
|
132
|
+
else
|
|
133
|
+
subject
|
|
134
|
+
end
|
|
135
|
+
@target.install_pattern(genv, narrowed)
|
|
136
|
+
subject
|
|
110
137
|
end
|
|
111
138
|
end
|
|
112
139
|
|
|
@@ -124,9 +151,10 @@ module TypeProf::Core
|
|
|
124
151
|
|
|
125
152
|
def subnodes = { cond:, body: }
|
|
126
153
|
|
|
127
|
-
def
|
|
154
|
+
def install_pattern0(genv, subject)
|
|
128
155
|
@cond.install(genv)
|
|
129
|
-
@body.
|
|
156
|
+
@body.install_pattern(genv, subject)
|
|
157
|
+
subject
|
|
130
158
|
end
|
|
131
159
|
end
|
|
132
160
|
|