typeprof 0.33.1 → 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_type.rb +13 -4
- data/lib/typeprof/core/ast/value.rb +52 -3
- data/lib/typeprof/core/ast/variable.rb +7 -1
- data/lib/typeprof/core/ast.rb +3 -1
- data/lib/typeprof/core/builtin.rb +1 -1
- data/lib/typeprof/core/env/method.rb +216 -24
- data/lib/typeprof/core/env.rb +24 -9
- data/lib/typeprof/core/graph/box.rb +17 -156
- data/lib/typeprof/core/service.rb +12 -3
- 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
|
@@ -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,7 +55,7 @@ module TypeProf::Core
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def update_rb_file(path, code)
|
|
58
|
-
code = File.
|
|
58
|
+
code = File.binread(path) unless code
|
|
59
59
|
update_rb_ast(path, Prism.parse(code))
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -122,7 +122,8 @@ module TypeProf::Core
|
|
|
122
122
|
def update_rbs_file(path, code)
|
|
123
123
|
prev_decls = @rbs_text_nodes[path]
|
|
124
124
|
|
|
125
|
-
code = File.read(path) unless code
|
|
125
|
+
code = File.read(path, encoding: "UTF-8") unless code
|
|
126
|
+
return false unless code.valid_encoding?
|
|
126
127
|
begin
|
|
127
128
|
decls = AST.parse_rbs(path, code, @options[:position_encoding])
|
|
128
129
|
rescue RBS::ParsingError
|
|
@@ -520,6 +521,14 @@ module TypeProf::Core
|
|
|
520
521
|
!@genv.resolve_method(node.static_cpath, mdef.singleton, mdef.mid).defs.empty?
|
|
521
522
|
out << " " * stack.size + "def #{ mdef.singleton ? "self." : "" }#{ mdef.mid }: " + mdef.show(@options[:output_parameter_names])
|
|
522
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
|
|
523
532
|
else
|
|
524
533
|
stack.pop
|
|
525
534
|
out << " " * stack.size + "end"
|
|
@@ -586,7 +595,7 @@ module TypeProf::Core
|
|
|
586
595
|
i += 1
|
|
587
596
|
end
|
|
588
597
|
|
|
589
|
-
res = update_file(file,
|
|
598
|
+
res = update_file(file, nil)
|
|
590
599
|
|
|
591
600
|
if res
|
|
592
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: []
|