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
|
@@ -2,8 +2,8 @@ module TypeProf::Core
|
|
|
2
2
|
class StaticRead
|
|
3
3
|
def initialize(name)
|
|
4
4
|
@name = name
|
|
5
|
-
@followers = Set
|
|
6
|
-
@source_modules = Set
|
|
5
|
+
@followers = Set.empty
|
|
6
|
+
@source_modules = Set.empty
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
attr_reader :name, :followers
|
|
@@ -37,11 +37,11 @@ module TypeProf::Core
|
|
|
37
37
|
scope = cref.cpath
|
|
38
38
|
mod = genv.resolve_cpath(scope)
|
|
39
39
|
genv.each_superclass(mod, false) do |mod, _singleton|
|
|
40
|
-
break if mod == genv.mod_object && break_object
|
|
40
|
+
break if mod == genv.mod_object && (break_object || cref.outer)
|
|
41
41
|
|
|
42
42
|
unless @source_modules.include?(mod)
|
|
43
43
|
@source_modules << mod
|
|
44
|
-
(mod.static_reads[@name] ||= Set
|
|
44
|
+
(mod.static_reads[@name] ||= Set.empty) << self
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
return if check_module(genv, mod)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module TypeProf::Core
|
|
2
2
|
class ValueEntity
|
|
3
3
|
def initialize
|
|
4
|
-
@decls = Set
|
|
5
|
-
@defs = Set
|
|
6
|
-
@read_boxes = Set
|
|
4
|
+
@decls = Set.empty
|
|
5
|
+
@defs = Set.empty
|
|
6
|
+
@read_boxes = Set.empty
|
|
7
7
|
@vtx = Vertex.new(self)
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -17,6 +17,14 @@ module TypeProf::Core
|
|
|
17
17
|
@decls.delete(decl) || raise
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Re-run all read boxes that depend on this entity. Used when a
|
|
21
|
+
# declaration is added or removed so that dependents (e.g. an
|
|
22
|
+
# IVarReadBox that previously fell back to the inferred type) can
|
|
23
|
+
# observe the new state.
|
|
24
|
+
def on_decl_changed(genv)
|
|
25
|
+
@read_boxes.each {|box| genv.add_run(box) }
|
|
26
|
+
end
|
|
27
|
+
|
|
20
28
|
def add_def(def_)
|
|
21
29
|
@defs << def_
|
|
22
30
|
end
|
|
@@ -28,5 +36,19 @@ module TypeProf::Core
|
|
|
28
36
|
def exist?
|
|
29
37
|
!@decls.empty? || !@defs.empty?
|
|
30
38
|
end
|
|
39
|
+
|
|
40
|
+
def on_const_added(genv, cpath)
|
|
41
|
+
unless exist?
|
|
42
|
+
parent_mod = genv.resolve_cpath(cpath[0..-2])
|
|
43
|
+
genv.add_static_eval_queue(:inner_modules_changed, [parent_mod, cpath[-1]])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def on_const_removed(genv, cpath)
|
|
48
|
+
unless exist?
|
|
49
|
+
parent_mod = genv.resolve_cpath(cpath[0..-2])
|
|
50
|
+
genv.add_static_eval_queue(:inner_modules_changed, [parent_mod, cpath[-1]])
|
|
51
|
+
end
|
|
52
|
+
end
|
|
31
53
|
end
|
|
32
54
|
end
|
data/lib/typeprof/core/env.rb
CHANGED
|
@@ -6,9 +6,9 @@ module TypeProf::Core
|
|
|
6
6
|
@static_eval_queue = []
|
|
7
7
|
|
|
8
8
|
@run_queue = []
|
|
9
|
-
@run_queue_set = Set
|
|
9
|
+
@run_queue_set = Set.empty
|
|
10
10
|
|
|
11
|
-
@pending_diagnostic_paths = Set
|
|
11
|
+
@pending_diagnostic_paths = Set.empty
|
|
12
12
|
|
|
13
13
|
@mod_object = ModuleEntity.new([])
|
|
14
14
|
@mod_object.inner_modules[:Object] = @mod_object
|
|
@@ -36,9 +36,12 @@ module TypeProf::Core
|
|
|
36
36
|
@complex_type = Type::Instance.new(self, resolve_cpath([:Complex]), [])
|
|
37
37
|
@proc_type = Type::Instance.new(self, resolve_cpath([:Proc]), [])
|
|
38
38
|
@symbol_type = Type::Instance.new(self, resolve_cpath([:Symbol]), [])
|
|
39
|
+
@method_type = Type::Instance.new(self, resolve_cpath([:Method]), [])
|
|
39
40
|
@set_type = Type::Instance.new(self, resolve_cpath([:Set]), [])
|
|
40
41
|
@regexp_type = Type::Instance.new(self, resolve_cpath([:Regexp]), [])
|
|
41
42
|
|
|
43
|
+
@bot_type = Type::Bot.new(self)
|
|
44
|
+
|
|
42
45
|
@run_count = 0
|
|
43
46
|
end
|
|
44
47
|
|
|
@@ -48,7 +51,8 @@ module TypeProf::Core
|
|
|
48
51
|
attr_reader :cls_type, :mod_type
|
|
49
52
|
attr_reader :obj_type, :nil_type, :true_type, :false_type, :str_type
|
|
50
53
|
attr_reader :int_type, :float_type, :rational_type, :complex_type
|
|
51
|
-
attr_reader :proc_type, :symbol_type, :set_type, :regexp_type
|
|
54
|
+
attr_reader :proc_type, :symbol_type, :method_type, :set_type, :regexp_type
|
|
55
|
+
attr_reader :bot_type
|
|
52
56
|
|
|
53
57
|
def gen_ary_type(elem_vtx)
|
|
54
58
|
Type::Instance.new(self, @mod_ary, [elem_vtx])
|
|
@@ -76,7 +80,7 @@ module TypeProf::Core
|
|
|
76
80
|
# TODO: prepended modules
|
|
77
81
|
yield mod, singleton
|
|
78
82
|
if singleton
|
|
79
|
-
|
|
83
|
+
each_extended_module(mod, &blk)
|
|
80
84
|
else
|
|
81
85
|
each_included_module(mod, &blk)
|
|
82
86
|
end
|
|
@@ -91,6 +95,15 @@ module TypeProf::Core
|
|
|
91
95
|
end
|
|
92
96
|
end
|
|
93
97
|
|
|
98
|
+
def each_extended_module(mod, &blk)
|
|
99
|
+
# An extended module contributes its instance methods (singleton = false)
|
|
100
|
+
# as the receiver's singleton methods.
|
|
101
|
+
mod.extended_modules.each do |_ext_decl, ext_mod|
|
|
102
|
+
yield ext_mod, false
|
|
103
|
+
each_included_module(ext_mod, &blk)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
94
107
|
def get_superclass(singleton, mod)
|
|
95
108
|
super_mod = mod.superclass
|
|
96
109
|
if super_mod
|
|
@@ -102,6 +115,9 @@ module TypeProf::Core
|
|
|
102
115
|
else
|
|
103
116
|
return nil
|
|
104
117
|
end
|
|
118
|
+
elsif mod == @mod_object
|
|
119
|
+
# Unresolved while loading the core RBS; the Module fallback below would cycle
|
|
120
|
+
return [singleton, @mod_basic_object]
|
|
105
121
|
elsif mod == @mod_module && !singleton
|
|
106
122
|
return nil
|
|
107
123
|
else
|
|
@@ -113,16 +129,20 @@ module TypeProf::Core
|
|
|
113
129
|
def get_instance_type(mod, type_args, changes, base_ty_env, base_ty)
|
|
114
130
|
ty_env = base_ty_env.dup
|
|
115
131
|
if base_ty.is_a?(Type::Instance)
|
|
116
|
-
base_ty.mod.type_params.zip(base_ty.args) do |param, arg|
|
|
117
|
-
ty_env[param] = arg || Source.new
|
|
132
|
+
base_ty.mod.type_params.zip(base_ty.args) do |(param, default_ty), arg|
|
|
133
|
+
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new)
|
|
118
134
|
end
|
|
119
135
|
elsif base_ty.is_a?(Type::Singleton)
|
|
120
|
-
base_ty.mod.type_params&.each do |param|
|
|
121
|
-
ty_env[param] = Source.new
|
|
136
|
+
base_ty.mod.type_params&.each do |(param, default_ty)|
|
|
137
|
+
ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new
|
|
122
138
|
end
|
|
123
139
|
end
|
|
124
|
-
args = mod.type_params.zip(type_args).map do |param, arg|
|
|
125
|
-
|
|
140
|
+
args = mod.type_params.zip(type_args).map do |(param, default_ty), arg|
|
|
141
|
+
if changes
|
|
142
|
+
(arg || default_ty)&.covariant_vertex(self, changes, ty_env) || Source.new
|
|
143
|
+
else
|
|
144
|
+
Source.new
|
|
145
|
+
end
|
|
126
146
|
end
|
|
127
147
|
Type::Instance.new(self, mod, args)
|
|
128
148
|
end
|
|
@@ -213,6 +233,18 @@ module TypeProf::Core
|
|
|
213
233
|
raise unless cpath # annotation
|
|
214
234
|
cpath.each do |cname|
|
|
215
235
|
mod = mod.inner_modules[cname] ||= ModuleEntity.new(mod.cpath + [cname], mod)
|
|
236
|
+
mod = follow_alias(mod)
|
|
237
|
+
end
|
|
238
|
+
mod
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def follow_alias(mod)
|
|
242
|
+
visited = nil
|
|
243
|
+
while mod.alias_target
|
|
244
|
+
visited ||= Set.empty
|
|
245
|
+
break if visited.include?(mod) # cycle
|
|
246
|
+
visited << mod
|
|
247
|
+
mod = mod.alias_target
|
|
216
248
|
end
|
|
217
249
|
mod
|
|
218
250
|
end
|
|
@@ -251,13 +283,30 @@ module TypeProf::Core
|
|
|
251
283
|
mod.get_type_alias(name)
|
|
252
284
|
end
|
|
253
285
|
|
|
254
|
-
|
|
255
|
-
|
|
286
|
+
# Returns the type parameter names of the first generic declaration of cpath
|
|
287
|
+
def find_type_params(decls, cpath)
|
|
288
|
+
decls.each do |decl|
|
|
289
|
+
next unless decl.cpath == cpath
|
|
290
|
+
next unless decl.respond_to?(:params)
|
|
291
|
+
params = decl.params
|
|
292
|
+
return params if params && !params.empty?
|
|
293
|
+
end
|
|
294
|
+
nil
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def load_core_rbs(raw_decls, position_encoding)
|
|
298
|
+
file_context = FileContext.new(nil, position_encoding)
|
|
299
|
+
lenv = LocalEnv.new(file_context, CRef::Toplevel, {}, [])
|
|
256
300
|
decls = raw_decls.map do |raw_decl|
|
|
257
301
|
AST.create_rbs_decl(raw_decl, lenv)
|
|
258
302
|
end.compact
|
|
259
303
|
|
|
260
|
-
|
|
304
|
+
# A module entity has one set of parameter names shared by all its declarations,
|
|
305
|
+
# so the shim must reuse the core's ones (Array's was `Elem`, and is `E` since RBS 4.1)
|
|
306
|
+
ary_elem, = find_type_params(decls, [:Array]) || [:Elem]
|
|
307
|
+
hash_key, hash_val = find_type_params(decls, [:Hash]) || [:K, :V]
|
|
308
|
+
|
|
309
|
+
decls += AST.parse_rbs("typeprof-rbs-shim.rbs", <<-RBS, position_encoding)
|
|
261
310
|
class Exception
|
|
262
311
|
include _Exception
|
|
263
312
|
end
|
|
@@ -265,12 +314,15 @@ module TypeProf::Core
|
|
|
265
314
|
include _ToS
|
|
266
315
|
include _ToStr
|
|
267
316
|
end
|
|
268
|
-
class Array[
|
|
269
|
-
include _ToAry[
|
|
270
|
-
include _Each[
|
|
317
|
+
class Array[#{ ary_elem }]
|
|
318
|
+
include _ToAry[#{ ary_elem }]
|
|
319
|
+
include _Each[#{ ary_elem }]
|
|
271
320
|
end
|
|
272
|
-
class Hash[
|
|
273
|
-
include _Each[[
|
|
321
|
+
class Hash[#{ hash_key }, #{ hash_val }]
|
|
322
|
+
include _Each[[#{ hash_key }, #{ hash_val }]]
|
|
323
|
+
end
|
|
324
|
+
class Object
|
|
325
|
+
include Hash::_Key
|
|
274
326
|
end
|
|
275
327
|
RBS
|
|
276
328
|
|
|
@@ -295,9 +347,41 @@ module TypeProf::Core
|
|
|
295
347
|
end
|
|
296
348
|
end
|
|
297
349
|
|
|
298
|
-
class
|
|
299
|
-
|
|
350
|
+
class FileContext
|
|
351
|
+
attr_reader :path, :comments, :position_encoding
|
|
352
|
+
def initialize(path, position_encoding = nil, prism_source = nil, comments = nil)
|
|
300
353
|
@path = path
|
|
354
|
+
@position_encoding = position_encoding || Encoding::UTF_16LE
|
|
355
|
+
@prism_source = prism_source
|
|
356
|
+
@code_units_cache = nil
|
|
357
|
+
@comments = comments
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Returns [start_column, end_column] for a Prism::Location, in the session-configured
|
|
361
|
+
# position encoding. UTF-8 uses Prism's native byte columns directly (Prism's UTF-8
|
|
362
|
+
# code_units_cache reports code points, not bytes — see LSP 3.17 spec).
|
|
363
|
+
def column_offsets_for(prism_location)
|
|
364
|
+
if @position_encoding == Encoding::UTF_8
|
|
365
|
+
[prism_location.start_column, prism_location.end_column]
|
|
366
|
+
else
|
|
367
|
+
cache = code_units_cache
|
|
368
|
+
[
|
|
369
|
+
prism_location.cached_start_code_units_column(cache),
|
|
370
|
+
prism_location.cached_end_code_units_column(cache),
|
|
371
|
+
]
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
private
|
|
376
|
+
|
|
377
|
+
def code_units_cache
|
|
378
|
+
@code_units_cache ||= @prism_source&.code_units_cache(@position_encoding)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
class LocalEnv
|
|
383
|
+
def initialize(file_context, cref, locals, return_boxes, forward_args = nil)
|
|
384
|
+
@file_context = file_context
|
|
301
385
|
@cref = cref
|
|
302
386
|
@locals = locals
|
|
303
387
|
@return_boxes = return_boxes
|
|
@@ -305,9 +389,16 @@ module TypeProf::Core
|
|
|
305
389
|
@next_boxes = []
|
|
306
390
|
@ivar_narrowings = {}
|
|
307
391
|
@strict_const_scope = false
|
|
392
|
+
@forward_args = forward_args
|
|
308
393
|
end
|
|
309
394
|
|
|
310
|
-
attr_reader :
|
|
395
|
+
attr_reader :file_context, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
|
|
396
|
+
attr_accessor :module_function, :forward_args
|
|
397
|
+
|
|
398
|
+
def path = @file_context&.path
|
|
399
|
+
def code_range_from_node(node)
|
|
400
|
+
TypeProf::CodeRange.from_node(node, @file_context)
|
|
401
|
+
end
|
|
311
402
|
|
|
312
403
|
def new_var(name, node)
|
|
313
404
|
@locals[name] = Vertex.new(node)
|
|
@@ -337,7 +428,6 @@ module TypeProf::Core
|
|
|
337
428
|
@break_vtx ||= Vertex.new(:break_vtx)
|
|
338
429
|
end
|
|
339
430
|
|
|
340
|
-
|
|
341
431
|
def push_ivar_narrowing(name, narrowing)
|
|
342
432
|
raise unless narrowing.is_a?(Narrowing::Constraint)
|
|
343
433
|
(@ivar_narrowings[name] ||= []) << narrowing
|
|
@@ -380,7 +470,7 @@ module TypeProf::Core
|
|
|
380
470
|
case @scope_level
|
|
381
471
|
when :instance
|
|
382
472
|
mod = genv.resolve_cpath(@cpath || [])
|
|
383
|
-
type_params = mod.type_params.map {|
|
|
473
|
+
type_params = mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
|
|
384
474
|
ty = Type::Instance.new(genv, mod, type_params)
|
|
385
475
|
Source.new(ty)
|
|
386
476
|
when :class
|