typeprof 0.30.1 → 0.31.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 +23 -4
- data/lib/typeprof/cli/cli.rb +27 -7
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +85 -24
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +345 -71
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +15 -5
- data/lib/typeprof/core/ast/misc.rb +21 -2
- data/lib/typeprof/core/ast/module.rb +10 -7
- data/lib/typeprof/core/ast/pattern.rb +9 -1
- data/lib/typeprof/core/ast/sig_decl.rb +163 -42
- data/lib/typeprof/core/ast/sig_type.rb +394 -24
- data/lib/typeprof/core/ast/value.rb +10 -2
- data/lib/typeprof/core/ast/variable.rb +32 -2
- data/lib/typeprof/core/ast.rb +15 -4
- data/lib/typeprof/core/builtin.rb +15 -9
- data/lib/typeprof/core/env/method.rb +21 -16
- data/lib/typeprof/core/env/method_entity.rb +11 -2
- data/lib/typeprof/core/env/module_entity.rb +57 -0
- data/lib/typeprof/core/env/narrowing.rb +131 -0
- data/lib/typeprof/core/env/static_read.rb +9 -8
- data/lib/typeprof/core/env.rb +37 -12
- data/lib/typeprof/core/graph/box.rb +207 -97
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +4 -21
- data/lib/typeprof/core/service.rb +30 -1
- data/lib/typeprof/core/type.rb +48 -123
- data/lib/typeprof/core.rb +1 -0
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +21 -15
- data/lib/typeprof/lsp/server.rb +132 -39
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -6
|
@@ -17,6 +17,29 @@ module TypeProf::Core
|
|
|
17
17
|
def retrieve_at(pos)
|
|
18
18
|
yield self if code_range.include?(pos)
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
def narrowings
|
|
22
|
+
@narrowings ||= [
|
|
23
|
+
Narrowing.new({ @var => Narrowing::NilConstraint.new(false) }),
|
|
24
|
+
Narrowing.new({ @var => Narrowing::NilConstraint.new(true) }),
|
|
25
|
+
]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class ItLocalVariableReadNode < Node
|
|
30
|
+
def initialize(raw_node, lenv)
|
|
31
|
+
super(raw_node, lenv)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def attrs = {}
|
|
35
|
+
|
|
36
|
+
def install0(genv)
|
|
37
|
+
@lenv.get_var(:it)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def retrieve_at(pos)
|
|
41
|
+
yield self if code_range.include?(pos)
|
|
42
|
+
end
|
|
20
43
|
end
|
|
21
44
|
|
|
22
45
|
class LocalVariableWriteNode < Node
|
|
@@ -64,7 +87,7 @@ module TypeProf::Core
|
|
|
64
87
|
case @lenv.cref.scope_level
|
|
65
88
|
when :class, :instance
|
|
66
89
|
box = @changes.add_ivar_read_box(genv, lenv.cref.cpath, lenv.cref.scope_level == :class, @var)
|
|
67
|
-
@lenv.
|
|
90
|
+
@lenv.apply_ivar_narrowing(genv, self, @var, box.ret)
|
|
68
91
|
else
|
|
69
92
|
Source.new()
|
|
70
93
|
end
|
|
@@ -73,6 +96,13 @@ module TypeProf::Core
|
|
|
73
96
|
def retrieve_at(pos)
|
|
74
97
|
yield self if code_range.include?(pos)
|
|
75
98
|
end
|
|
99
|
+
|
|
100
|
+
def narrowings
|
|
101
|
+
@narrowings ||= [
|
|
102
|
+
Narrowing.new({ @var => Narrowing::NilConstraint.new(false) }),
|
|
103
|
+
Narrowing.new({ @var => Narrowing::NilConstraint.new(true) }),
|
|
104
|
+
]
|
|
105
|
+
end
|
|
76
106
|
end
|
|
77
107
|
|
|
78
108
|
class InstanceVariableWriteNode < Node
|
|
@@ -289,7 +319,7 @@ module TypeProf::Core
|
|
|
289
319
|
|
|
290
320
|
def install0(genv)
|
|
291
321
|
box = @changes.add_cvar_read_box(genv, lenv.cref.cpath, @var)
|
|
292
|
-
@lenv.
|
|
322
|
+
@lenv.apply_ivar_narrowing(genv, self, @var, box.ret)
|
|
293
323
|
end
|
|
294
324
|
|
|
295
325
|
def retrieve_at(pos)
|
data/lib/typeprof/core/ast.rb
CHANGED
|
@@ -58,6 +58,7 @@ module TypeProf::Core
|
|
|
58
58
|
when :begin_node then BeginNode.new(raw_node, lenv)
|
|
59
59
|
when :retry_node then RetryNode.new(raw_node, lenv)
|
|
60
60
|
when :rescue_modifier_node then RescueModifierNode.new(raw_node, lenv)
|
|
61
|
+
when :rescue_node then RescueNode.new(raw_node, lenv)
|
|
61
62
|
|
|
62
63
|
# constants
|
|
63
64
|
when :constant_read_node, :constant_path_node
|
|
@@ -92,6 +93,8 @@ module TypeProf::Core
|
|
|
92
93
|
# variables
|
|
93
94
|
when :local_variable_read_node
|
|
94
95
|
LocalVariableReadNode.new(raw_node, lenv)
|
|
96
|
+
when :it_local_variable_read_node
|
|
97
|
+
ItLocalVariableReadNode.new(raw_node, lenv)
|
|
95
98
|
when :local_variable_write_node
|
|
96
99
|
LocalVariableWriteNode.new(raw_node, AST.create_node(raw_node.value, lenv), lenv)
|
|
97
100
|
when :local_variable_operator_write_node
|
|
@@ -223,7 +226,7 @@ module TypeProf::Core
|
|
|
223
226
|
when :flip_flop_node then FlipFlopNode.new(raw_node, lenv)
|
|
224
227
|
when :shareable_constant_node then create_node(raw_node.write, lenv)
|
|
225
228
|
when :match_required_node then MatchRequiredNode.new(raw_node, lenv)
|
|
226
|
-
when :match_predicate_node then
|
|
229
|
+
when :match_predicate_node then MatchPredicateNode.new(raw_node, lenv)
|
|
227
230
|
|
|
228
231
|
# call
|
|
229
232
|
when :super_node then SuperNode.new(raw_node, lenv)
|
|
@@ -343,8 +346,7 @@ module TypeProf::Core
|
|
|
343
346
|
break
|
|
344
347
|
when :constant_path_node, :constant_path_target_node
|
|
345
348
|
if raw_node.parent
|
|
346
|
-
|
|
347
|
-
names << (raw_node.respond_to?(:name) ? raw_node.name : raw_node.child.name)
|
|
349
|
+
names << raw_node.name
|
|
348
350
|
raw_node = raw_node.parent
|
|
349
351
|
else
|
|
350
352
|
return names.reverse
|
|
@@ -356,7 +358,8 @@ module TypeProf::Core
|
|
|
356
358
|
return nil
|
|
357
359
|
end
|
|
358
360
|
end
|
|
359
|
-
|
|
361
|
+
cpath = cref.cpath # annotate
|
|
362
|
+
return cpath + names.reverse if cpath
|
|
360
363
|
end
|
|
361
364
|
|
|
362
365
|
def self.parse_rbs(path, src)
|
|
@@ -397,6 +400,8 @@ module TypeProf::Core
|
|
|
397
400
|
SigDefNode.new(raw_decl, lenv)
|
|
398
401
|
when RBS::AST::Members::Include
|
|
399
402
|
SigIncludeNode.new(raw_decl, lenv)
|
|
403
|
+
when RBS::AST::Members::Prepend
|
|
404
|
+
SigPrependNode.new(raw_decl, lenv)
|
|
400
405
|
when RBS::AST::Members::Extend
|
|
401
406
|
when RBS::AST::Members::Public
|
|
402
407
|
when RBS::AST::Members::Private
|
|
@@ -410,6 +415,12 @@ module TypeProf::Core
|
|
|
410
415
|
SigAttrAccessorNode.new(raw_decl, lenv)
|
|
411
416
|
when RBS::AST::Declarations::Base
|
|
412
417
|
self.create_rbs_decl(raw_decl, lenv)
|
|
418
|
+
when RBS::AST::Members::InstanceVariable
|
|
419
|
+
SigInstanceVariableNode.new(raw_decl, lenv, false)
|
|
420
|
+
when RBS::AST::Members::ClassInstanceVariable
|
|
421
|
+
SigInstanceVariableNode.new(raw_decl, lenv, true)
|
|
422
|
+
when RBS::AST::Members::ClassVariable
|
|
423
|
+
SigClassVariableNode.new(raw_decl, lenv)
|
|
413
424
|
else
|
|
414
425
|
raise "unsupported: #{ raw_decl.class }"
|
|
415
426
|
end
|
|
@@ -5,12 +5,11 @@ module TypeProf::Core
|
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def class_new(changes, node, ty, a_args, ret)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
end
|
|
8
|
+
type_param_vtxs = ty.mod.type_params.map { Vertex.new(node) }
|
|
9
|
+
temp_instance_ty = Type::Instance.new(@genv, ty.mod, type_param_vtxs)
|
|
10
|
+
recv = Source.new(temp_instance_ty)
|
|
11
|
+
changes.add_method_call_box(@genv, recv, :initialize, a_args, false)
|
|
12
|
+
changes.add_edge(@genv, recv, ret)
|
|
14
13
|
true
|
|
15
14
|
end
|
|
16
15
|
|
|
@@ -26,7 +25,8 @@ module TypeProf::Core
|
|
|
26
25
|
def proc_call(changes, node, ty, a_args, ret)
|
|
27
26
|
case ty
|
|
28
27
|
when Type::Proc
|
|
29
|
-
ty.block.accept_args(@genv, changes, a_args.positionals
|
|
28
|
+
ty.block.accept_args(@genv, changes, a_args.positionals)
|
|
29
|
+
ty.block.add_ret(@genv, changes, ret)
|
|
30
30
|
true
|
|
31
31
|
else
|
|
32
32
|
false
|
|
@@ -90,10 +90,16 @@ module TypeProf::Core
|
|
|
90
90
|
def hash_aref(changes, node, ty, a_args, ret)
|
|
91
91
|
if a_args.positionals.size == 1
|
|
92
92
|
case ty
|
|
93
|
-
when Type::Hash
|
|
93
|
+
when Type::Hash, Type::Record
|
|
94
94
|
idx = node.positional_args[0]
|
|
95
95
|
idx = idx.is_a?(AST::SymbolNode) ? idx.lit : nil
|
|
96
|
-
|
|
96
|
+
value = ty.get_value(idx)
|
|
97
|
+
if value
|
|
98
|
+
changes.add_edge(@genv, value, ret)
|
|
99
|
+
else
|
|
100
|
+
# Return untyped for unknown fields
|
|
101
|
+
changes.add_edge(@genv, Source.new(), ret)
|
|
102
|
+
end
|
|
97
103
|
true
|
|
98
104
|
else
|
|
99
105
|
false
|
|
@@ -41,7 +41,7 @@ module TypeProf::Core
|
|
|
41
41
|
ActualArguments.new(positionals, splat_flags, keywords, block)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def get_rest_args(genv, start_rest, end_rest)
|
|
44
|
+
def get_rest_args(genv, changes, start_rest, end_rest)
|
|
45
45
|
vtxs = []
|
|
46
46
|
|
|
47
47
|
start_rest.upto(end_rest - 1) do |i|
|
|
@@ -50,7 +50,7 @@ module TypeProf::Core
|
|
|
50
50
|
a_arg.each_type do |ty|
|
|
51
51
|
ty = ty.base_type(genv)
|
|
52
52
|
if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
|
|
53
|
-
vtxs <<
|
|
53
|
+
vtxs << changes.new_vertex(genv, self, ty.args[0])
|
|
54
54
|
else
|
|
55
55
|
"???"
|
|
56
56
|
end
|
|
@@ -82,6 +82,7 @@ module TypeProf::Core
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
class Block
|
|
85
|
+
#: (AST::CallBaseNode, Vertex, Array[Vertex], Array[EscapeBox]) -> void
|
|
85
86
|
def initialize(node, f_ary_arg, f_args, next_boxes)
|
|
86
87
|
@node = node
|
|
87
88
|
@f_ary_arg = f_ary_arg
|
|
@@ -89,25 +90,26 @@ module TypeProf::Core
|
|
|
89
90
|
@next_boxes = next_boxes
|
|
90
91
|
end
|
|
91
92
|
|
|
92
|
-
attr_reader :node, :f_args, :
|
|
93
|
+
attr_reader :node, :f_args, :next_boxes
|
|
93
94
|
|
|
94
|
-
def accept_args(genv, changes, caller_positionals
|
|
95
|
+
def accept_args(genv, changes, caller_positionals)
|
|
95
96
|
if caller_positionals.size == 1 && @f_args.size >= 2
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
single_arg = caller_positionals[0]
|
|
98
|
+
|
|
99
|
+
@f_args.each_with_index do |f_arg, i|
|
|
100
|
+
elem_vtx = changes.add_splat_box(genv, single_arg, i).ret
|
|
101
|
+
changes.add_edge(genv, elem_vtx, f_arg)
|
|
102
|
+
end
|
|
98
103
|
else
|
|
99
104
|
caller_positionals.zip(@f_args) do |a_arg, f_arg|
|
|
100
105
|
changes.add_edge(genv, a_arg, f_arg) if f_arg
|
|
101
106
|
end
|
|
102
107
|
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@next_boxes.each do |box|
|
|
109
|
-
changes.add_edge(genv, box.a_ret, caller_ret)
|
|
110
|
-
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def add_ret(genv, changes, ret)
|
|
111
|
+
@next_boxes.each do |box|
|
|
112
|
+
changes.add_edge(genv, box.a_ret, ret)
|
|
111
113
|
end
|
|
112
114
|
end
|
|
113
115
|
end
|
|
@@ -126,12 +128,15 @@ module TypeProf::Core
|
|
|
126
128
|
|
|
127
129
|
attr_reader :node, :f_args, :ret, :used
|
|
128
130
|
|
|
129
|
-
def accept_args(genv, changes, caller_positionals
|
|
131
|
+
def accept_args(genv, changes, caller_positionals)
|
|
130
132
|
@used = true
|
|
131
133
|
caller_positionals.each_with_index do |a_arg, i|
|
|
132
134
|
changes.add_edge(genv, a_arg.new_vertex(genv, @node), get_f_arg(i))
|
|
133
135
|
end
|
|
134
|
-
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def add_ret(genv, changes, ret)
|
|
139
|
+
changes.add_edge(genv, ret, @ret)
|
|
135
140
|
end
|
|
136
141
|
end
|
|
137
142
|
end
|
|
@@ -3,6 +3,7 @@ module TypeProf::Core
|
|
|
3
3
|
def initialize
|
|
4
4
|
@builtin = nil
|
|
5
5
|
@decls = Set[]
|
|
6
|
+
@overloading_decls = Set[]
|
|
6
7
|
@defs = Set[]
|
|
7
8
|
@aliases = {}
|
|
8
9
|
@method_call_boxes = Set[]
|
|
@@ -12,11 +13,19 @@ module TypeProf::Core
|
|
|
12
13
|
attr_accessor :builtin
|
|
13
14
|
|
|
14
15
|
def add_decl(decl)
|
|
15
|
-
|
|
16
|
+
if decl.overloading
|
|
17
|
+
@overloading_decls << decl
|
|
18
|
+
else
|
|
19
|
+
@decls << decl
|
|
20
|
+
end
|
|
16
21
|
end
|
|
17
22
|
|
|
18
23
|
def remove_decl(decl)
|
|
19
|
-
|
|
24
|
+
if decl.overloading
|
|
25
|
+
@overloading_decls.delete(decl) || raise
|
|
26
|
+
else
|
|
27
|
+
@decls.delete(decl) || raise
|
|
28
|
+
end
|
|
20
29
|
end
|
|
21
30
|
|
|
22
31
|
def add_def(mdef)
|
|
@@ -7,6 +7,8 @@ module TypeProf::Core
|
|
|
7
7
|
@module_defs = Set[]
|
|
8
8
|
@include_decls = Set[]
|
|
9
9
|
@include_defs = Set[]
|
|
10
|
+
@prepend_decls = []
|
|
11
|
+
@prepend_defs = []
|
|
10
12
|
|
|
11
13
|
@inner_modules = {}
|
|
12
14
|
@outer_module = outer_module
|
|
@@ -15,6 +17,7 @@ module TypeProf::Core
|
|
|
15
17
|
@superclass = nil
|
|
16
18
|
@self_types = {}
|
|
17
19
|
@included_modules = {}
|
|
20
|
+
@prepended_modules = {}
|
|
18
21
|
@basic_object = @cpath == [:BasicObject]
|
|
19
22
|
|
|
20
23
|
# child modules (subclasses and all modules that include me)
|
|
@@ -46,6 +49,7 @@ module TypeProf::Core
|
|
|
46
49
|
attr_reader :superclass
|
|
47
50
|
attr_reader :self_types
|
|
48
51
|
attr_reader :included_modules
|
|
52
|
+
attr_reader :prepended_modules
|
|
49
53
|
attr_reader :child_modules
|
|
50
54
|
|
|
51
55
|
attr_reader :superclass_type_args
|
|
@@ -192,6 +196,26 @@ module TypeProf::Core
|
|
|
192
196
|
genv.add_static_eval_queue(:parent_modules_changed, self)
|
|
193
197
|
end
|
|
194
198
|
|
|
199
|
+
def add_prepend_decl(genv, node)
|
|
200
|
+
@prepend_decls << node
|
|
201
|
+
genv.add_static_eval_queue(:parent_modules_changed, self)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def remove_prepend_decl(genv, node)
|
|
205
|
+
@prepend_decls.delete(node) || raise
|
|
206
|
+
genv.add_static_eval_queue(:parent_modules_changed, self)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def add_prepend_def(genv, node)
|
|
210
|
+
@prepend_defs << node
|
|
211
|
+
genv.add_static_eval_queue(:parent_modules_changed, self)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def remove_prepend_def(genv, node)
|
|
215
|
+
@prepend_defs.delete(node) || raise
|
|
216
|
+
genv.add_static_eval_queue(:parent_modules_changed, self)
|
|
217
|
+
end
|
|
218
|
+
|
|
195
219
|
def update_parent(genv, origin, old_parent, new_parent_cpath)
|
|
196
220
|
new_parent = new_parent_cpath ? genv.resolve_cpath(new_parent_cpath) : nil
|
|
197
221
|
if old_parent != new_parent
|
|
@@ -323,6 +347,30 @@ module TypeProf::Core
|
|
|
323
347
|
any_updated = true
|
|
324
348
|
end
|
|
325
349
|
end
|
|
350
|
+
@prepend_decls.each do |pdecl|
|
|
351
|
+
new_parent_cpath = pdecl.static_ret.last.cpath
|
|
352
|
+
new_parent, updated = update_parent(genv, pdecl, @prepended_modules[pdecl], new_parent_cpath)
|
|
353
|
+
if updated
|
|
354
|
+
if new_parent
|
|
355
|
+
@prepended_modules[pdecl] = new_parent
|
|
356
|
+
else
|
|
357
|
+
@prepended_modules.delete(pdecl) || raise
|
|
358
|
+
end
|
|
359
|
+
any_updated = true
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
@prepend_defs.each do |pdef|
|
|
363
|
+
new_parent_cpath = pdef.static_ret ? pdef.static_ret.cpath : nil
|
|
364
|
+
new_parent, updated = update_parent(genv, pdef, @prepended_modules[pdef], new_parent_cpath)
|
|
365
|
+
if updated
|
|
366
|
+
if new_parent
|
|
367
|
+
@prepended_modules[pdef] = new_parent
|
|
368
|
+
else
|
|
369
|
+
@prepended_modules.delete(pdef) || raise
|
|
370
|
+
end
|
|
371
|
+
any_updated = true
|
|
372
|
+
end
|
|
373
|
+
end
|
|
326
374
|
@included_modules.delete_if do |origin, old_mod|
|
|
327
375
|
if @include_decls.include?(origin) || @include_defs.include?(origin)
|
|
328
376
|
false
|
|
@@ -332,6 +380,15 @@ module TypeProf::Core
|
|
|
332
380
|
true
|
|
333
381
|
end
|
|
334
382
|
end
|
|
383
|
+
@prepended_modules.delete_if do |origin, old_mod|
|
|
384
|
+
if @prepend_decls.include?(origin) || @prepend_defs.include?(origin)
|
|
385
|
+
false
|
|
386
|
+
else
|
|
387
|
+
_new_parent, updated = update_parent(genv, origin, old_mod, nil)
|
|
388
|
+
any_updated ||= updated
|
|
389
|
+
true
|
|
390
|
+
end
|
|
391
|
+
end
|
|
335
392
|
|
|
336
393
|
if any_updated
|
|
337
394
|
@subclass_checks.each do |mcall_box|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
module TypeProf::Core
|
|
2
|
+
class Narrowing
|
|
3
|
+
def initialize(map)
|
|
4
|
+
raise unless map.is_a?(Hash)
|
|
5
|
+
@map = map
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_reader :map
|
|
9
|
+
|
|
10
|
+
def and(other)
|
|
11
|
+
new_map = @map.dup
|
|
12
|
+
other.map.each do |var, constraint|
|
|
13
|
+
new_map[var] = new_map[var] ? new_map[var].and(constraint) : constraint
|
|
14
|
+
end
|
|
15
|
+
Narrowing.new(new_map)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def or(other)
|
|
19
|
+
new_map = {}
|
|
20
|
+
@map.each do |var, constraint|
|
|
21
|
+
new_map[var] = constraint.or(other.map[var]) if other.map[var]
|
|
22
|
+
end
|
|
23
|
+
Narrowing.new(new_map)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
EmptyNarrowings = [Narrowing.new({}), Narrowing.new({})]
|
|
27
|
+
|
|
28
|
+
# Narrowing system for type refinement
|
|
29
|
+
class Constraint
|
|
30
|
+
def and(other)
|
|
31
|
+
AndConstraint.new(self, other)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def or(other)
|
|
35
|
+
OrConstraint.new(self, other)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class IsAConstraint < Constraint
|
|
40
|
+
def initialize(arg, neg)
|
|
41
|
+
@arg = arg
|
|
42
|
+
@neg = neg
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
attr_reader :arg, :neg
|
|
46
|
+
|
|
47
|
+
def negate
|
|
48
|
+
IsAConstraint.new(@arg, !@neg)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def inspect
|
|
52
|
+
@neg ? "!#{@arg}" : "#{@arg}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def narrow(genv, node, vtx)
|
|
56
|
+
if @arg.static_ret
|
|
57
|
+
IsAFilter.new(genv, node, vtx, @neg, @arg.static_ret).next_vtx
|
|
58
|
+
else
|
|
59
|
+
vtx
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class NilConstraint < Constraint
|
|
65
|
+
def initialize(neg)
|
|
66
|
+
@neg = neg
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
attr_reader :neg
|
|
70
|
+
|
|
71
|
+
def inspect
|
|
72
|
+
@neg ? "!nil" : "nil"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def negate
|
|
76
|
+
NilConstraint.new(!@neg)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def narrow(genv, node, vtx)
|
|
80
|
+
NilFilter.new(genv, node, vtx, @neg).next_vtx
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class AndConstraint < Constraint
|
|
85
|
+
def initialize(left, right)
|
|
86
|
+
@left = left
|
|
87
|
+
@right = right
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
attr_reader :left, :right
|
|
91
|
+
|
|
92
|
+
def inspect
|
|
93
|
+
"(#{@left.inspect} & #{@right.inspect})"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def negate
|
|
97
|
+
OrConstraint.new(@left.negate, @right.negate)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def narrow(genv, node, vtx)
|
|
101
|
+
@left.narrow(genv, node, @right.narrow(genv, node, vtx))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class OrConstraint < Constraint
|
|
106
|
+
def initialize(left, right)
|
|
107
|
+
@left = left
|
|
108
|
+
@right = right
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
attr_reader :left, :right
|
|
112
|
+
|
|
113
|
+
def inspect
|
|
114
|
+
"(#{@left.inspect} | #{@right.inspect})"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def negate
|
|
118
|
+
AndConstraint.new(@left.negate, @right.negate)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def narrow(genv, node, vtx)
|
|
122
|
+
ret = Vertex.new(node)
|
|
123
|
+
vtx1 = @left.narrow(genv, node, vtx)
|
|
124
|
+
vtx2 = @right.narrow(genv, node, vtx)
|
|
125
|
+
vtx1.add_edge(genv, ret)
|
|
126
|
+
vtx2.add_edge(genv, ret)
|
|
127
|
+
ret
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -30,10 +30,9 @@ module TypeProf::Core
|
|
|
30
30
|
@source_modules.clear
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def resolve(genv, cref, break_object)
|
|
33
|
+
def resolve(genv, cref, search_ancestors, break_object)
|
|
34
34
|
destroy(genv)
|
|
35
35
|
|
|
36
|
-
first = true
|
|
37
36
|
while cref
|
|
38
37
|
scope = cref.cpath
|
|
39
38
|
mod = genv.resolve_cpath(scope)
|
|
@@ -47,9 +46,9 @@ module TypeProf::Core
|
|
|
47
46
|
|
|
48
47
|
return if check_module(genv, mod)
|
|
49
48
|
|
|
50
|
-
break unless
|
|
49
|
+
break unless search_ancestors
|
|
51
50
|
end
|
|
52
|
-
|
|
51
|
+
search_ancestors = false
|
|
53
52
|
cref = cref.outer
|
|
54
53
|
end
|
|
55
54
|
resolution_failed(genv)
|
|
@@ -57,29 +56,31 @@ module TypeProf::Core
|
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
class BaseStaticRead < StaticRead
|
|
60
|
-
def initialize(genv, name, cref)
|
|
59
|
+
def initialize(genv, name, cref, strict_const_scope)
|
|
61
60
|
super(name)
|
|
62
61
|
@cref = cref
|
|
62
|
+
@search_ancestors = !strict_const_scope
|
|
63
63
|
genv.add_static_eval_queue(:static_read_changed, self)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
attr_reader :cref
|
|
67
67
|
|
|
68
68
|
def on_scope_updated(genv)
|
|
69
|
-
resolve(genv, @cref, false)
|
|
69
|
+
resolve(genv, @cref, @search_ancestors, false)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
class ScopedStaticRead < StaticRead
|
|
74
|
-
def initialize(name, cbase)
|
|
74
|
+
def initialize(name, cbase, strict_const_scope)
|
|
75
75
|
super(name)
|
|
76
76
|
@cbase = cbase
|
|
77
77
|
@cbase.followers << self if @cbase
|
|
78
|
+
@search_ancestors = !strict_const_scope
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
def on_cbase_updated(genv)
|
|
81
82
|
if @cbase && @cbase.cpath
|
|
82
|
-
resolve(genv, CRef.new(@cbase.cpath, :class, nil, nil), true)
|
|
83
|
+
resolve(genv, CRef.new(@cbase.cpath, :class, nil, nil), @search_ancestors, true)
|
|
83
84
|
else
|
|
84
85
|
resolution_failed(genv)
|
|
85
86
|
end
|
data/lib/typeprof/core/env.rb
CHANGED
|
@@ -8,6 +8,8 @@ module TypeProf::Core
|
|
|
8
8
|
@run_queue = []
|
|
9
9
|
@run_queue_set = Set[]
|
|
10
10
|
|
|
11
|
+
@pending_diagnostic_paths = Set[]
|
|
12
|
+
|
|
11
13
|
@mod_object = ModuleEntity.new([])
|
|
12
14
|
@mod_object.inner_modules[:Object] = @mod_object
|
|
13
15
|
|
|
@@ -112,7 +114,7 @@ module TypeProf::Core
|
|
|
112
114
|
ty_env = base_ty_env.dup
|
|
113
115
|
if base_ty.is_a?(Type::Instance)
|
|
114
116
|
base_ty.mod.type_params.zip(base_ty.args) do |param, arg|
|
|
115
|
-
ty_env[param] = arg
|
|
117
|
+
ty_env[param] = arg || Source.new
|
|
116
118
|
end
|
|
117
119
|
end
|
|
118
120
|
args = mod.type_params.zip(type_args).map do |param, arg|
|
|
@@ -179,6 +181,19 @@ module TypeProf::Core
|
|
|
179
181
|
@run_count += run_count
|
|
180
182
|
end
|
|
181
183
|
|
|
184
|
+
def process_diagnostic_paths
|
|
185
|
+
processed_paths = []
|
|
186
|
+
@pending_diagnostic_paths.each do |path|
|
|
187
|
+
processed = yield path
|
|
188
|
+
processed_paths << path if processed
|
|
189
|
+
end
|
|
190
|
+
processed_paths.each {|path| @pending_diagnostic_paths.delete(path) }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def add_diagnostic_path(path)
|
|
194
|
+
@pending_diagnostic_paths << path unless @pending_diagnostic_paths.include?(path)
|
|
195
|
+
end
|
|
196
|
+
|
|
182
197
|
# just for validation
|
|
183
198
|
def get_vertexes(vtxs)
|
|
184
199
|
@mod_object.get_vertexes(vtxs)
|
|
@@ -284,10 +299,11 @@ module TypeProf::Core
|
|
|
284
299
|
@return_boxes = return_boxes
|
|
285
300
|
@break_vtx = nil
|
|
286
301
|
@next_boxes = []
|
|
287
|
-
@
|
|
302
|
+
@ivar_narrowings = {}
|
|
303
|
+
@strict_const_scope = false
|
|
288
304
|
end
|
|
289
305
|
|
|
290
|
-
attr_reader :path, :cref, :locals, :return_boxes, :break_vtx, :next_boxes
|
|
306
|
+
attr_reader :path, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
|
|
291
307
|
|
|
292
308
|
def new_var(name, node)
|
|
293
309
|
@locals[name] = Vertex.new(node)
|
|
@@ -318,23 +334,32 @@ module TypeProf::Core
|
|
|
318
334
|
end
|
|
319
335
|
|
|
320
336
|
|
|
321
|
-
def
|
|
322
|
-
|
|
337
|
+
def push_ivar_narrowing(name, narrowing)
|
|
338
|
+
raise unless narrowing.is_a?(Narrowing::Constraint)
|
|
339
|
+
(@ivar_narrowings[name] ||= []) << narrowing
|
|
323
340
|
end
|
|
324
341
|
|
|
325
|
-
def
|
|
326
|
-
(@
|
|
342
|
+
def pop_ivar_narrowing(name)
|
|
343
|
+
(@ivar_narrowings[name] ||= []).pop
|
|
327
344
|
end
|
|
328
345
|
|
|
329
|
-
def
|
|
330
|
-
if @
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
346
|
+
def apply_ivar_narrowing(genv, node, name, vtx)
|
|
347
|
+
if @ivar_narrowings[name] && !@ivar_narrowings[name].empty?
|
|
348
|
+
# Apply all accumulated narrowings in order
|
|
349
|
+
@ivar_narrowings[name].each do |narrowing|
|
|
350
|
+
vtx = narrowing.narrow(genv, node, vtx)
|
|
334
351
|
end
|
|
352
|
+
return vtx
|
|
335
353
|
end
|
|
336
354
|
vtx
|
|
337
355
|
end
|
|
356
|
+
|
|
357
|
+
def use_strict_const_scope
|
|
358
|
+
@strict_const_scope = true
|
|
359
|
+
yield
|
|
360
|
+
ensure
|
|
361
|
+
@strict_const_scope = false
|
|
362
|
+
end
|
|
338
363
|
end
|
|
339
364
|
|
|
340
365
|
class CRef
|