typeprof 0.31.0 → 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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/doc/report_guide.md +88 -0
  4. data/lib/typeprof/cli/cli.rb +9 -3
  5. data/lib/typeprof/code_range.rb +7 -5
  6. data/lib/typeprof/core/ast/base.rb +18 -6
  7. data/lib/typeprof/core/ast/call.rb +96 -32
  8. data/lib/typeprof/core/ast/const.rb +12 -9
  9. data/lib/typeprof/core/ast/control.rb +60 -30
  10. data/lib/typeprof/core/ast/meta.rb +194 -2
  11. data/lib/typeprof/core/ast/method.rb +74 -20
  12. data/lib/typeprof/core/ast/misc.rb +84 -7
  13. data/lib/typeprof/core/ast/module.rb +33 -3
  14. data/lib/typeprof/core/ast/sig_decl.rb +85 -24
  15. data/lib/typeprof/core/ast/sig_type.rb +78 -32
  16. data/lib/typeprof/core/ast/value.rb +14 -6
  17. data/lib/typeprof/core/ast/variable.rb +11 -4
  18. data/lib/typeprof/core/ast.rb +97 -14
  19. data/lib/typeprof/core/builtin.rb +184 -12
  20. data/lib/typeprof/core/env/method.rb +171 -6
  21. data/lib/typeprof/core/env/method_entity.rb +18 -15
  22. data/lib/typeprof/core/env/module_entity.rb +56 -18
  23. data/lib/typeprof/core/env/static_read.rb +4 -4
  24. data/lib/typeprof/core/env/type_alias_entity.rb +1 -1
  25. data/lib/typeprof/core/env/value_entity.rb +25 -3
  26. data/lib/typeprof/core/env.rb +81 -15
  27. data/lib/typeprof/core/graph/box.rb +380 -53
  28. data/lib/typeprof/core/graph/change_set.rb +59 -46
  29. data/lib/typeprof/core/graph/filter.rb +8 -5
  30. data/lib/typeprof/core/graph/vertex.rb +20 -19
  31. data/lib/typeprof/core/service.rb +317 -23
  32. data/lib/typeprof/core/type.rb +43 -8
  33. data/lib/typeprof/core/util.rb +6 -0
  34. data/lib/typeprof/lsp/messages.rb +5 -0
  35. data/lib/typeprof/lsp/server.rb +35 -4
  36. data/lib/typeprof/version.rb +1 -1
  37. metadata +3 -2
@@ -1,7 +1,7 @@
1
1
  module TypeProf::Core
2
2
  class TypeAliasEntity
3
3
  def initialize
4
- @decls = Set[]
4
+ @decls = Set.empty
5
5
  @type = nil
6
6
  end
7
7
 
@@ -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
@@ -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])
@@ -113,12 +117,20 @@ module TypeProf::Core
113
117
  def get_instance_type(mod, type_args, changes, base_ty_env, base_ty)
114
118
  ty_env = base_ty_env.dup
115
119
  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
120
+ base_ty.mod.type_params.zip(base_ty.args) do |(param, default_ty), arg|
121
+ ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new)
122
+ end
123
+ elsif base_ty.is_a?(Type::Singleton)
124
+ base_ty.mod.type_params&.each do |(param, default_ty)|
125
+ ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new
118
126
  end
119
127
  end
120
- args = mod.type_params.zip(type_args).map do |param, arg|
121
- arg && changes ? arg.covariant_vertex(self, changes, ty_env) : Source.new
128
+ args = mod.type_params.zip(type_args).map do |(param, default_ty), arg|
129
+ if changes
130
+ (arg || default_ty)&.covariant_vertex(self, changes, ty_env) || Source.new
131
+ else
132
+ Source.new
133
+ end
122
134
  end
123
135
  Type::Instance.new(self, mod, args)
124
136
  end
@@ -209,6 +221,18 @@ module TypeProf::Core
209
221
  raise unless cpath # annotation
210
222
  cpath.each do |cname|
211
223
  mod = mod.inner_modules[cname] ||= ModuleEntity.new(mod.cpath + [cname], mod)
224
+ mod = follow_alias(mod)
225
+ end
226
+ mod
227
+ end
228
+
229
+ def follow_alias(mod)
230
+ visited = nil
231
+ while mod.alias_target
232
+ visited ||= Set.empty
233
+ break if visited.include?(mod) # cycle
234
+ visited << mod
235
+ mod = mod.alias_target
212
236
  end
213
237
  mod
214
238
  end
@@ -247,13 +271,14 @@ module TypeProf::Core
247
271
  mod.get_type_alias(name)
248
272
  end
249
273
 
250
- def load_core_rbs(raw_decls)
251
- lenv = LocalEnv.new(nil, CRef::Toplevel, {}, [])
274
+ def load_core_rbs(raw_decls, position_encoding)
275
+ file_context = FileContext.new(nil, position_encoding)
276
+ lenv = LocalEnv.new(file_context, CRef::Toplevel, {}, [])
252
277
  decls = raw_decls.map do |raw_decl|
253
278
  AST.create_rbs_decl(raw_decl, lenv)
254
279
  end.compact
255
280
 
256
- decls += AST.parse_rbs("typeprof-rbs-shim.rbs", <<-RBS)
281
+ decls += AST.parse_rbs("typeprof-rbs-shim.rbs", <<-RBS, position_encoding)
257
282
  class Exception
258
283
  include _Exception
259
284
  end
@@ -268,6 +293,9 @@ module TypeProf::Core
268
293
  class Hash[K, V]
269
294
  include _Each[[K, V]]
270
295
  end
296
+ class Object
297
+ include Hash::_Key
298
+ end
271
299
  RBS
272
300
 
273
301
  # Loading frequently used modules first will reduces constant resolution
@@ -291,9 +319,41 @@ module TypeProf::Core
291
319
  end
292
320
  end
293
321
 
294
- class LocalEnv
295
- def initialize(path, cref, locals, return_boxes)
322
+ class FileContext
323
+ attr_reader :path, :comments, :position_encoding
324
+ def initialize(path, position_encoding = nil, prism_source = nil, comments = nil)
296
325
  @path = path
326
+ @position_encoding = position_encoding || Encoding::UTF_16LE
327
+ @prism_source = prism_source
328
+ @code_units_cache = nil
329
+ @comments = comments
330
+ end
331
+
332
+ # Returns [start_column, end_column] for a Prism::Location, in the session-configured
333
+ # position encoding. UTF-8 uses Prism's native byte columns directly (Prism's UTF-8
334
+ # code_units_cache reports code points, not bytes — see LSP 3.17 spec).
335
+ def column_offsets_for(prism_location)
336
+ if @position_encoding == Encoding::UTF_8
337
+ [prism_location.start_column, prism_location.end_column]
338
+ else
339
+ cache = code_units_cache
340
+ [
341
+ prism_location.cached_start_code_units_column(cache),
342
+ prism_location.cached_end_code_units_column(cache),
343
+ ]
344
+ end
345
+ end
346
+
347
+ private
348
+
349
+ def code_units_cache
350
+ @code_units_cache ||= @prism_source&.code_units_cache(@position_encoding)
351
+ end
352
+ end
353
+
354
+ class LocalEnv
355
+ def initialize(file_context, cref, locals, return_boxes, forward_args = nil)
356
+ @file_context = file_context
297
357
  @cref = cref
298
358
  @locals = locals
299
359
  @return_boxes = return_boxes
@@ -301,9 +361,16 @@ module TypeProf::Core
301
361
  @next_boxes = []
302
362
  @ivar_narrowings = {}
303
363
  @strict_const_scope = false
364
+ @forward_args = forward_args
304
365
  end
305
366
 
306
- attr_reader :path, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
367
+ attr_reader :file_context, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
368
+ attr_accessor :module_function, :forward_args
369
+
370
+ def path = @file_context&.path
371
+ def code_range_from_node(node)
372
+ TypeProf::CodeRange.from_node(node, @file_context)
373
+ end
307
374
 
308
375
  def new_var(name, node)
309
376
  @locals[name] = Vertex.new(node)
@@ -333,7 +400,6 @@ module TypeProf::Core
333
400
  @break_vtx ||= Vertex.new(:break_vtx)
334
401
  end
335
402
 
336
-
337
403
  def push_ivar_narrowing(name, narrowing)
338
404
  raise unless narrowing.is_a?(Narrowing::Constraint)
339
405
  (@ivar_narrowings[name] ||= []) << narrowing
@@ -376,7 +442,7 @@ module TypeProf::Core
376
442
  case @scope_level
377
443
  when :instance
378
444
  mod = genv.resolve_cpath(@cpath || [])
379
- type_params = mod.type_params.map {|ty_param| Source.new() } # TODO: better support
445
+ type_params = mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
380
446
  ty = Type::Instance.new(genv, mod, type_params)
381
447
  Source.new(ty)
382
448
  when :class