typeprof 0.33.0 → 0.33.2
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/lib/typeprof/core/ast/base.rb +14 -0
- data/lib/typeprof/core/ast/call.rb +182 -150
- data/lib/typeprof/core/ast/control.rb +45 -0
- data/lib/typeprof/core/ast/meta.rb +21 -11
- data/lib/typeprof/core/ast/method.rb +25 -24
- data/lib/typeprof/core/ast/misc.rb +9 -2
- data/lib/typeprof/core/ast/pattern.rb +4 -2
- data/lib/typeprof/core/ast/sig_decl.rb +10 -6
- data/lib/typeprof/core/ast/sig_type.rb +32 -9
- data/lib/typeprof/core/ast/value.rb +52 -3
- data/lib/typeprof/core/ast/variable.rb +7 -1
- data/lib/typeprof/core/ast.rb +15 -3
- data/lib/typeprof/core/builtin.rb +1 -1
- data/lib/typeprof/core/env/method.rb +216 -24
- data/lib/typeprof/core/env.rb +33 -32
- data/lib/typeprof/core/graph/box.rb +17 -156
- data/lib/typeprof/core/service.rb +18 -4
- data/lib/typeprof/core/type.rb +2 -2
- data/lib/typeprof/lsp/util.rb +1 -1
- data/lib/typeprof/version.rb +1 -1
- metadata +2 -2
data/lib/typeprof/core/env.rb
CHANGED
|
@@ -42,6 +42,11 @@ module TypeProf::Core
|
|
|
42
42
|
|
|
43
43
|
@bot_type = Type::Bot.new(self)
|
|
44
44
|
|
|
45
|
+
# The vertex for a type argument that is not given. This must be shared:
|
|
46
|
+
# a fresh vertex makes a different Instance type and a different edge on
|
|
47
|
+
# every run, so a box that uses it is re-run forever.
|
|
48
|
+
@untyped_arg = Source.new
|
|
49
|
+
|
|
45
50
|
@run_count = 0
|
|
46
51
|
end
|
|
47
52
|
|
|
@@ -52,7 +57,7 @@ module TypeProf::Core
|
|
|
52
57
|
attr_reader :obj_type, :nil_type, :true_type, :false_type, :str_type
|
|
53
58
|
attr_reader :int_type, :float_type, :rational_type, :complex_type
|
|
54
59
|
attr_reader :proc_type, :symbol_type, :method_type, :set_type, :regexp_type
|
|
55
|
-
attr_reader :bot_type
|
|
60
|
+
attr_reader :bot_type, :untyped_arg
|
|
56
61
|
|
|
57
62
|
def gen_ary_type(elem_vtx)
|
|
58
63
|
Type::Instance.new(self, @mod_ary, [elem_vtx])
|
|
@@ -130,18 +135,18 @@ module TypeProf::Core
|
|
|
130
135
|
ty_env = base_ty_env.dup
|
|
131
136
|
if base_ty.is_a?(Type::Instance)
|
|
132
137
|
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) :
|
|
138
|
+
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : @untyped_arg)
|
|
134
139
|
end
|
|
135
140
|
elsif base_ty.is_a?(Type::Singleton)
|
|
136
141
|
base_ty.mod.type_params&.each do |(param, default_ty)|
|
|
137
|
-
ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) :
|
|
142
|
+
ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : @untyped_arg
|
|
138
143
|
end
|
|
139
144
|
end
|
|
140
145
|
args = mod.type_params.zip(type_args).map do |(param, default_ty), arg|
|
|
141
146
|
if changes
|
|
142
|
-
(arg || default_ty)&.covariant_vertex(self, changes, ty_env) ||
|
|
147
|
+
(arg || default_ty)&.covariant_vertex(self, changes, ty_env) || @untyped_arg
|
|
143
148
|
else
|
|
144
|
-
|
|
149
|
+
@untyped_arg
|
|
145
150
|
end
|
|
146
151
|
end
|
|
147
152
|
Type::Instance.new(self, mod, args)
|
|
@@ -283,17 +288,6 @@ module TypeProf::Core
|
|
|
283
288
|
mod.get_type_alias(name)
|
|
284
289
|
end
|
|
285
290
|
|
|
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
291
|
def load_core_rbs(raw_decls, position_encoding)
|
|
298
292
|
file_context = FileContext.new(nil, position_encoding)
|
|
299
293
|
lenv = LocalEnv.new(file_context, CRef::Toplevel, {}, [])
|
|
@@ -301,11 +295,6 @@ module TypeProf::Core
|
|
|
301
295
|
AST.create_rbs_decl(raw_decl, lenv)
|
|
302
296
|
end.compact
|
|
303
297
|
|
|
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
298
|
decls += AST.parse_rbs("typeprof-rbs-shim.rbs", <<-RBS, position_encoding)
|
|
310
299
|
class Exception
|
|
311
300
|
include _Exception
|
|
@@ -314,12 +303,12 @@ module TypeProf::Core
|
|
|
314
303
|
include _ToS
|
|
315
304
|
include _ToStr
|
|
316
305
|
end
|
|
317
|
-
class Array[
|
|
318
|
-
include _ToAry[
|
|
319
|
-
include _Each[
|
|
306
|
+
class Array[Elem]
|
|
307
|
+
include _ToAry[Elem]
|
|
308
|
+
include _Each[Elem]
|
|
320
309
|
end
|
|
321
|
-
class Hash[
|
|
322
|
-
include _Each[[
|
|
310
|
+
class Hash[K, V]
|
|
311
|
+
include _Each[[K, V]]
|
|
323
312
|
end
|
|
324
313
|
class Object
|
|
325
314
|
include Hash::_Key
|
|
@@ -380,7 +369,7 @@ module TypeProf::Core
|
|
|
380
369
|
end
|
|
381
370
|
|
|
382
371
|
class LocalEnv
|
|
383
|
-
def initialize(file_context, cref, locals, return_boxes, forward_args = nil)
|
|
372
|
+
def initialize(file_context, cref, locals, return_boxes, forward_args = nil, sig_type_params: nil)
|
|
384
373
|
@file_context = file_context
|
|
385
374
|
@cref = cref
|
|
386
375
|
@locals = locals
|
|
@@ -390,10 +379,13 @@ module TypeProf::Core
|
|
|
390
379
|
@ivar_narrowings = {}
|
|
391
380
|
@strict_const_scope = false
|
|
392
381
|
@forward_args = forward_args
|
|
382
|
+
@shadowed_vars = {}
|
|
383
|
+
# [cpath, names] of the type parameters of the enclosing RBS declaration
|
|
384
|
+
@sig_type_params = sig_type_params
|
|
393
385
|
end
|
|
394
386
|
|
|
395
|
-
attr_reader :file_context, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
|
|
396
|
-
attr_accessor :module_function, :forward_args
|
|
387
|
+
attr_reader :file_context, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope, :sig_type_params
|
|
388
|
+
attr_accessor :module_function, :forward_args, :shadowed_vars
|
|
397
389
|
|
|
398
390
|
def path = @file_context&.path
|
|
399
391
|
def code_range_from_node(node)
|
|
@@ -412,6 +404,12 @@ module TypeProf::Core
|
|
|
412
404
|
@locals[name] || raise("#{ name }")
|
|
413
405
|
end
|
|
414
406
|
|
|
407
|
+
# A bare `super` passes the variables of the method, not the block
|
|
408
|
+
# parameters that shadow them
|
|
409
|
+
def get_method_var(name)
|
|
410
|
+
@shadowed_vars[name] || get_var(name)
|
|
411
|
+
end
|
|
412
|
+
|
|
415
413
|
def exist_var?(name)
|
|
416
414
|
!!@locals[name]
|
|
417
415
|
end
|
|
@@ -457,20 +455,23 @@ module TypeProf::Core
|
|
|
457
455
|
end
|
|
458
456
|
|
|
459
457
|
class CRef
|
|
460
|
-
|
|
458
|
+
# in_method: whether this is inside a method body, which a define_method
|
|
459
|
+
# block is even though its method name (mid) is not known
|
|
460
|
+
def initialize(cpath, scope_level, mid, outer, in_method: !mid.nil?)
|
|
461
461
|
@cpath = cpath
|
|
462
462
|
@scope_level = scope_level
|
|
463
463
|
@mid = mid
|
|
464
464
|
@outer = outer
|
|
465
|
+
@in_method = in_method
|
|
465
466
|
end
|
|
466
467
|
|
|
467
|
-
attr_reader :cpath, :scope_level, :mid, :outer
|
|
468
|
+
attr_reader :cpath, :scope_level, :mid, :outer, :in_method
|
|
468
469
|
|
|
469
470
|
def get_self(genv)
|
|
470
471
|
case @scope_level
|
|
471
472
|
when :instance
|
|
472
473
|
mod = genv.resolve_cpath(@cpath || [])
|
|
473
|
-
type_params = mod.type_params.map {|(_name, _default_ty)|
|
|
474
|
+
type_params = mod.type_params.map {|(_name, _default_ty)| genv.untyped_arg } # TODO: better support
|
|
474
475
|
ty = Type::Instance.new(genv, mod, type_params)
|
|
475
476
|
Source.new(ty)
|
|
476
477
|
when :class
|
|
@@ -399,7 +399,7 @@ module TypeProf::Core
|
|
|
399
399
|
a_args.block.each_type do |ty|
|
|
400
400
|
case ty
|
|
401
401
|
when Type::Proc
|
|
402
|
-
ty.block.
|
|
402
|
+
ty.block.pass_arguments(genv, changes, ActualArguments.new(blk_a_args, ::Array.new(blk_a_args.size, false), nil, nil))
|
|
403
403
|
|
|
404
404
|
if ty.block.is_a?(Block)
|
|
405
405
|
ty.block.next_boxes.each do |next_box|
|
|
@@ -625,20 +625,7 @@ module TypeProf::Core
|
|
|
625
625
|
def wrong_return_type(f_ret_show, changes)
|
|
626
626
|
actual_ty = @a_ret.show
|
|
627
627
|
msg = "expected: #{ f_ret_show }; actual: #{ actual_ty }"
|
|
628
|
-
|
|
629
|
-
when AST::ReturnNode
|
|
630
|
-
changes.add_diagnostic(:code_range, msg, @node)
|
|
631
|
-
when AST::DefNode
|
|
632
|
-
changes.add_diagnostic(:last_stmt_code_range, msg, @node)
|
|
633
|
-
when AST::NextNode
|
|
634
|
-
changes.add_diagnostic(:code_range, msg, @node)
|
|
635
|
-
when AST::CallNode
|
|
636
|
-
changes.add_diagnostic(:block_last_stmt_code_range, msg, @node)
|
|
637
|
-
when AST::AttrReaderMetaNode, AST::AttrAccessorMetaNode
|
|
638
|
-
changes.add_diagnostic(:code_range, msg, @node)
|
|
639
|
-
else
|
|
640
|
-
pp @node.class
|
|
641
|
-
end
|
|
628
|
+
changes.add_diagnostic(:ret_code_range, msg, @node)
|
|
642
629
|
end
|
|
643
630
|
end
|
|
644
631
|
|
|
@@ -693,6 +680,8 @@ module TypeProf::Core
|
|
|
693
680
|
@fallback = fallback
|
|
694
681
|
@rest.add_edge(genv, self)
|
|
695
682
|
@ret = Vertex.new(node)
|
|
683
|
+
# An empty rest never triggers a run, but the fallback still has to flow
|
|
684
|
+
genv.add_run(self)
|
|
696
685
|
end
|
|
697
686
|
|
|
698
687
|
attr_reader :ret
|
|
@@ -790,7 +779,7 @@ module TypeProf::Core
|
|
|
790
779
|
ty = Type::Singleton.new(genv, mod)
|
|
791
780
|
param_map0 = Type.default_param_map(genv, ty)
|
|
792
781
|
else
|
|
793
|
-
type_params = mod.type_params.map {|(_name, _default_ty)|
|
|
782
|
+
type_params = mod.type_params.map {|(_name, _default_ty)| genv.untyped_arg } # TODO: better support
|
|
794
783
|
ty = Type::Instance.new(genv, mod, type_params)
|
|
795
784
|
param_map0 = Type.default_param_map(genv, ty)
|
|
796
785
|
if ty.is_a?(Type::Instance)
|
|
@@ -838,143 +827,11 @@ module TypeProf::Core
|
|
|
838
827
|
end
|
|
839
828
|
|
|
840
829
|
def pass_arguments(changes, genv, a_args)
|
|
841
|
-
|
|
842
|
-
# there is at least one splat actual argument
|
|
843
|
-
|
|
844
|
-
lower = @f_args.req_positionals.size + @f_args.post_positionals.size
|
|
845
|
-
upper = @f_args.rest_positionals ? nil : lower + @f_args.opt_positionals.size
|
|
846
|
-
if upper && upper < a_args.positionals.size
|
|
847
|
-
meth = changes.node.mid_code_range ? :mid_code_range : :code_range
|
|
848
|
-
err = "#{ a_args.positionals.size } for #{ lower }#{ upper ? lower < upper ? "...#{ upper }" : "" : "+" }"
|
|
849
|
-
changes.add_diagnostic(meth, "wrong number of arguments (#{ err })")
|
|
850
|
-
return false
|
|
851
|
-
end
|
|
852
|
-
|
|
853
|
-
start_rest = [a_args.splat_flags.index(true), @f_args.req_positionals.size + @f_args.opt_positionals.size].min
|
|
854
|
-
end_rest = [a_args.splat_flags.rindex(true) + 1, a_args.positionals.size - @f_args.post_positionals.size].max
|
|
855
|
-
rest_vtxs = a_args.get_rest_args(genv, changes, start_rest, end_rest)
|
|
856
|
-
|
|
857
|
-
@f_args.req_positionals.each_with_index do |f_vtx, i|
|
|
858
|
-
if i < start_rest
|
|
859
|
-
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
860
|
-
else
|
|
861
|
-
rest_vtxs.each do |vtx|
|
|
862
|
-
changes.add_edge(genv, vtx, f_vtx)
|
|
863
|
-
end
|
|
864
|
-
end
|
|
865
|
-
end
|
|
866
|
-
@f_args.opt_positionals.each_with_index do |f_vtx, i|
|
|
867
|
-
i += @f_args.req_positionals.size
|
|
868
|
-
if i < start_rest
|
|
869
|
-
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
870
|
-
else
|
|
871
|
-
rest_vtxs.each do |vtx|
|
|
872
|
-
changes.add_edge(genv, vtx, f_vtx)
|
|
873
|
-
end
|
|
874
|
-
end
|
|
875
|
-
end
|
|
876
|
-
@f_args.post_positionals.each_with_index do |f_vtx, i|
|
|
877
|
-
i += a_args.positionals.size - @f_args.post_positionals.size
|
|
878
|
-
if end_rest <= i
|
|
879
|
-
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
880
|
-
else
|
|
881
|
-
rest_vtxs.each do |vtx|
|
|
882
|
-
changes.add_edge(genv, vtx, f_vtx)
|
|
883
|
-
end
|
|
884
|
-
end
|
|
885
|
-
end
|
|
886
|
-
|
|
887
|
-
if @f_args.rest_positionals
|
|
888
|
-
rest_vtxs.each do |vtx|
|
|
889
|
-
@f_args.rest_positionals.each_type do |ty|
|
|
890
|
-
if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
|
|
891
|
-
changes.add_edge(genv, vtx, ty.args[0])
|
|
892
|
-
end
|
|
893
|
-
end
|
|
894
|
-
end
|
|
895
|
-
end
|
|
896
|
-
else
|
|
897
|
-
# there is no splat actual argument
|
|
898
|
-
|
|
899
|
-
lower = @f_args.req_positionals.size + @f_args.post_positionals.size
|
|
900
|
-
upper = @f_args.rest_positionals ? nil : lower + @f_args.opt_positionals.size
|
|
901
|
-
if a_args.positionals.size < lower || (upper && upper < a_args.positionals.size)
|
|
902
|
-
meth = changes.node.mid_code_range ? :mid_code_range : :code_range
|
|
903
|
-
err = "#{ a_args.positionals.size } for #{ lower }#{ upper ? lower < upper ? "...#{ upper }" : "" : "+" }"
|
|
904
|
-
changes.add_diagnostic(meth, "wrong number of arguments (#{ err })")
|
|
905
|
-
return false
|
|
906
|
-
end
|
|
907
|
-
|
|
908
|
-
@f_args.req_positionals.each_with_index do |f_vtx, i|
|
|
909
|
-
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
910
|
-
end
|
|
911
|
-
@f_args.post_positionals.each_with_index do |f_vtx, i|
|
|
912
|
-
i -= @f_args.post_positionals.size
|
|
913
|
-
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
914
|
-
end
|
|
915
|
-
start_rest = @f_args.req_positionals.size
|
|
916
|
-
end_rest = a_args.positionals.size - @f_args.post_positionals.size
|
|
917
|
-
i = 0
|
|
918
|
-
while i < @f_args.opt_positionals.size && start_rest < end_rest
|
|
919
|
-
f_arg = @f_args.opt_positionals[i]
|
|
920
|
-
changes.add_edge(genv, a_args.positionals[start_rest], f_arg)
|
|
921
|
-
i += 1
|
|
922
|
-
start_rest += 1
|
|
923
|
-
end
|
|
924
|
-
|
|
925
|
-
if start_rest < end_rest
|
|
926
|
-
if @f_args.rest_positionals
|
|
927
|
-
(start_rest..end_rest-1).each do |i|
|
|
928
|
-
@f_args.rest_positionals.each_type do |ty|
|
|
929
|
-
if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
|
|
930
|
-
changes.add_edge(genv, a_args.positionals[i], ty.args[0])
|
|
931
|
-
end
|
|
932
|
-
end
|
|
933
|
-
end
|
|
934
|
-
end
|
|
935
|
-
end
|
|
936
|
-
end
|
|
937
|
-
|
|
938
|
-
if a_args.keywords
|
|
939
|
-
# TODO: support diagnostics
|
|
940
|
-
@node.req_keywords.zip(@f_args.req_keywords) do |name, f_vtx|
|
|
941
|
-
changes.add_edge(genv, a_args.get_keyword_arg(genv, changes, name), f_vtx)
|
|
942
|
-
end
|
|
943
|
-
|
|
944
|
-
@node.opt_keywords.zip(@f_args.opt_keywords).each do |name, f_vtx|
|
|
945
|
-
changes.add_edge(genv, a_args.get_keyword_arg(genv, changes, name), f_vtx)
|
|
946
|
-
end
|
|
947
|
-
|
|
948
|
-
if @node.rest_keywords
|
|
949
|
-
named_keys = @node.req_keywords + @node.opt_keywords
|
|
950
|
-
a_args.keywords.each_type do |kw_ty|
|
|
951
|
-
case kw_ty
|
|
952
|
-
when Type::Record
|
|
953
|
-
rest_fields = kw_ty.fields.reject {|key, _| named_keys.include?(key) }
|
|
954
|
-
base = kw_ty.base_type(genv)
|
|
955
|
-
rest_record = Type::Record.new(genv, rest_fields, base)
|
|
956
|
-
changes.add_edge(genv, Source.new(rest_record), @f_args.rest_keywords)
|
|
957
|
-
when Type::Hash, Type::Instance
|
|
958
|
-
changes.add_edge(genv, Source.new(kw_ty), @f_args.rest_keywords)
|
|
959
|
-
end
|
|
960
|
-
end
|
|
961
|
-
end
|
|
962
|
-
end
|
|
963
|
-
|
|
964
|
-
return true
|
|
965
|
-
end
|
|
966
|
-
|
|
967
|
-
def normalize_keyword_hash_argument_for_def(a_args)
|
|
968
|
-
return a_args unless a_args.keywords
|
|
969
|
-
return a_args if @node.no_keywords
|
|
970
|
-
return a_args if @node.rest_keywords
|
|
971
|
-
return a_args unless @node.req_keywords.empty? && @node.opt_keywords.empty?
|
|
972
|
-
|
|
973
|
-
a_args.with_keywords_as_last_positional_hash
|
|
830
|
+
@f_args.pass_arguments(changes, genv, a_args, @node)
|
|
974
831
|
end
|
|
975
832
|
|
|
976
833
|
def call(changes, genv, a_args, ret)
|
|
977
|
-
a_args =
|
|
834
|
+
a_args = a_args.with_keywords_normalized_for(@node)
|
|
978
835
|
if pass_arguments(changes, genv, a_args)
|
|
979
836
|
if @node.is_a?(AST::DefNode)
|
|
980
837
|
@node.body.lenv.forward_args&.accept_actual_arguments(genv, changes, a_args)
|
|
@@ -985,7 +842,7 @@ module TypeProf::Core
|
|
|
985
842
|
end
|
|
986
843
|
end
|
|
987
844
|
|
|
988
|
-
def show(output_parameter_names)
|
|
845
|
+
def show(output_parameter_names, ret: nil)
|
|
989
846
|
block_show = []
|
|
990
847
|
if @record_block.used
|
|
991
848
|
blk_f_args = @record_block.f_args.map {|arg| arg.show }.join(", ")
|
|
@@ -1036,7 +893,7 @@ module TypeProf::Core
|
|
|
1036
893
|
args = args.join(", ")
|
|
1037
894
|
s = args.empty? ? [] : ["(#{ args })"]
|
|
1038
895
|
s << "#{ block_show.sort.join(" | ") }" unless block_show.empty?
|
|
1039
|
-
s << "-> #{ @mid == :initialize ? "void" : @ret.show }"
|
|
896
|
+
s << "-> #{ ret || (@mid == :initialize ? "void" : @ret.show) }"
|
|
1040
897
|
s.join(" ")
|
|
1041
898
|
end
|
|
1042
899
|
end
|
|
@@ -1127,7 +984,7 @@ module TypeProf::Core
|
|
|
1127
984
|
ty_env = Type.default_param_map(genv, orig_ty)
|
|
1128
985
|
if ty.is_a?(Type::Instance)
|
|
1129
986
|
ty.mod.type_params.zip(ty.args) do |(param, default_ty), arg|
|
|
1130
|
-
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(genv, changes, ty_env) :
|
|
987
|
+
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(genv, changes, ty_env) : genv.untyped_arg)
|
|
1131
988
|
end
|
|
1132
989
|
end
|
|
1133
990
|
mdecl.resolve_overloads(changes, genv, @node, ty_env, a_args, @ret) do |method_type|
|
|
@@ -1170,6 +1027,8 @@ module TypeProf::Core
|
|
|
1170
1027
|
next if orig_ty == genv.bot_type
|
|
1171
1028
|
if @mid == :"*super"
|
|
1172
1029
|
mid = @node.lenv.cref.mid
|
|
1030
|
+
# Outside a method or in a define_method block, the method is unknown
|
|
1031
|
+
next unless mid
|
|
1173
1032
|
skip = true
|
|
1174
1033
|
else
|
|
1175
1034
|
mid = @mid
|
|
@@ -1236,7 +1095,7 @@ module TypeProf::Core
|
|
|
1236
1095
|
if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
|
|
1237
1096
|
prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, base_ty_env, ty)
|
|
1238
1097
|
else
|
|
1239
|
-
type_params = prep_mod.type_params.map {
|
|
1098
|
+
type_params = prep_mod.type_params.map { genv.untyped_arg } # TODO: better support
|
|
1240
1099
|
prep_ty = Type::Instance.new(genv, prep_mod, type_params)
|
|
1241
1100
|
end
|
|
1242
1101
|
|
|
@@ -1291,7 +1150,7 @@ module TypeProf::Core
|
|
|
1291
1150
|
if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
|
|
1292
1151
|
inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, base_ty_env, ty)
|
|
1293
1152
|
else
|
|
1294
|
-
type_params = inc_mod.type_params.map {
|
|
1153
|
+
type_params = inc_mod.type_params.map { genv.untyped_arg } # TODO: better support
|
|
1295
1154
|
inc_ty = Type::Instance.new(genv, inc_mod, type_params)
|
|
1296
1155
|
end
|
|
1297
1156
|
|
|
@@ -1322,7 +1181,7 @@ module TypeProf::Core
|
|
|
1322
1181
|
if ext_decl.is_a?(AST::SigExtendNode) && ext_mod.type_params
|
|
1323
1182
|
ext_ty = genv.get_instance_type(ext_mod, ext_decl.args, changes, base_ty_env, ty)
|
|
1324
1183
|
else
|
|
1325
|
-
type_params = ext_mod.type_params.map {
|
|
1184
|
+
type_params = ext_mod.type_params.map { genv.untyped_arg } # TODO: better support
|
|
1326
1185
|
ext_ty = Type::Instance.new(genv, ext_mod, type_params)
|
|
1327
1186
|
end
|
|
1328
1187
|
|
|
@@ -1351,6 +1210,8 @@ module TypeProf::Core
|
|
|
1351
1210
|
base_ty = ty.base_type(genv)
|
|
1352
1211
|
singleton = base_ty.is_a?(Type::Singleton)
|
|
1353
1212
|
mod = base_ty.mod
|
|
1213
|
+
# Every class descends from Object, so this would only find unrelated methods
|
|
1214
|
+
next if mod.cpath.empty?
|
|
1354
1215
|
mod.each_descendant do |desc_mod|
|
|
1355
1216
|
next if mod == desc_mod
|
|
1356
1217
|
me = desc_mod.get_method(singleton, @mid)
|
|
@@ -55,10 +55,15 @@ module TypeProf::Core
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def update_rb_file(path, code)
|
|
58
|
+
code = File.binread(path) unless code
|
|
59
|
+
update_rb_ast(path, Prism.parse(code))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# path is used only as a key to find the previous analysis; the file is not read.
|
|
63
|
+
def update_rb_ast(path, parse_result)
|
|
58
64
|
prev_node = @rb_text_nodes[path]
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
node = AST.parse_rb(path, code, @options[:position_encoding])
|
|
66
|
+
node = AST.build_rb(path, parse_result, @options[:position_encoding])
|
|
62
67
|
return false unless node
|
|
63
68
|
|
|
64
69
|
node.diff(@rb_text_nodes[path]) if prev_node
|
|
@@ -117,7 +122,8 @@ module TypeProf::Core
|
|
|
117
122
|
def update_rbs_file(path, code)
|
|
118
123
|
prev_decls = @rbs_text_nodes[path]
|
|
119
124
|
|
|
120
|
-
code = File.read(path) unless code
|
|
125
|
+
code = File.read(path, encoding: "UTF-8") unless code
|
|
126
|
+
return false unless code.valid_encoding?
|
|
121
127
|
begin
|
|
122
128
|
decls = AST.parse_rbs(path, code, @options[:position_encoding])
|
|
123
129
|
rescue RBS::ParsingError
|
|
@@ -515,6 +521,14 @@ module TypeProf::Core
|
|
|
515
521
|
!@genv.resolve_method(node.static_cpath, mdef.singleton, mdef.mid).defs.empty?
|
|
516
522
|
out << " " * stack.size + "def #{ mdef.singleton ? "self." : "" }#{ mdef.mid }: " + mdef.show(@options[:output_parameter_names])
|
|
517
523
|
end
|
|
524
|
+
if node.is_a?(AST::StructNewNode) && node.kind == :struct &&
|
|
525
|
+
@genv.resolve_method(node.static_cpath, true, :[]).defs.empty?
|
|
526
|
+
# Struct.[] takes the same arguments as the initialize it reaches
|
|
527
|
+
init_mdef = @genv.resolve_method(node.static_cpath, false, :initialize).defs.to_a.first ||
|
|
528
|
+
@genv.resolve_method(node.struct_base_cpath, false, :initialize).defs.to_a.first
|
|
529
|
+
ret = Type::Instance.new(@genv, mod, []).show
|
|
530
|
+
out << " " * stack.size + "def self.[]: " + init_mdef.show(@options[:output_parameter_names], ret:)
|
|
531
|
+
end
|
|
518
532
|
else
|
|
519
533
|
stack.pop
|
|
520
534
|
out << " " * stack.size + "end"
|
|
@@ -581,7 +595,7 @@ module TypeProf::Core
|
|
|
581
595
|
i += 1
|
|
582
596
|
end
|
|
583
597
|
|
|
584
|
-
res = update_file(file,
|
|
598
|
+
res = update_file(file, nil)
|
|
585
599
|
|
|
586
600
|
if res
|
|
587
601
|
true
|
data/lib/typeprof/core/type.rb
CHANGED
|
@@ -48,7 +48,7 @@ module TypeProf::Core
|
|
|
48
48
|
|
|
49
49
|
def self.default_param_map(genv, ty)
|
|
50
50
|
ty = ty.base_type(genv)
|
|
51
|
-
instance_ty = ty.is_a?(Type::Instance) ? ty :
|
|
51
|
+
instance_ty = ty.is_a?(Type::Instance) ? ty : ty.get_instance_type(genv)
|
|
52
52
|
singleton_ty = ty.is_a?(Type::Instance) ? Type::Singleton.new(genv, ty.mod) : ty
|
|
53
53
|
{
|
|
54
54
|
"*self": Source.new(ty),
|
|
@@ -77,7 +77,7 @@ module TypeProf::Core
|
|
|
77
77
|
|
|
78
78
|
def get_instance_type(genv)
|
|
79
79
|
params = @mod.type_params
|
|
80
|
-
Instance.new(genv, @mod, params ? params.map {
|
|
80
|
+
Instance.new(genv, @mod, params ? params.map { genv.untyped_arg } : []) # TODO: respect param_default_types
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
data/lib/typeprof/lsp/util.rb
CHANGED
data/lib/typeprof/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typeprof
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.33.
|
|
4
|
+
version: 0.33.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yusuke Endoh
|
|
@@ -118,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
118
118
|
- !ruby/object:Gem::Version
|
|
119
119
|
version: '0'
|
|
120
120
|
requirements: []
|
|
121
|
-
rubygems_version: 4.0.
|
|
121
|
+
rubygems_version: 4.0.20
|
|
122
122
|
specification_version: 4
|
|
123
123
|
summary: TypeProf is a type analysis tool for Ruby code based on abstract interpretation
|
|
124
124
|
test_files: []
|