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.
@@ -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.accept_args(genv, changes, blk_a_args)
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
- case @node
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)| Source.new() } # TODO: better support
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
- if a_args.splat_flags.any?
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 = normalize_keyword_hash_argument_for_def(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) : Source.new)
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 { Source.new() } # TODO: better support
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 { Source.new() } # TODO: better support
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 { Source.new() } # TODO: better support
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.read(path) unless code
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, File.read(file))
598
+ res = update_file(file, nil)
590
599
 
591
600
  if res
592
601
  true
@@ -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 : Type::Instance.new(genv, ty.mod, []) # TODO: type params
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 { Source.new } : []) # TODO: respect param_default_types
80
+ Instance.new(genv, @mod, params ? params.map { genv.untyped_arg } : []) # TODO: respect param_default_types
81
81
  end
82
82
  end
83
83
 
@@ -1,6 +1,6 @@
1
1
  module TypeProf::LSP
2
2
  def self.load_json_with_comments(path, **opts)
3
- json = File.read(path)
3
+ json = File.read(path, encoding: "UTF-8")
4
4
 
5
5
  state = :normal
6
6
  last_comma_index = nil
@@ -1,3 +1,3 @@
1
1
  module TypeProf
2
- VERSION = "0.33.1"
2
+ VERSION = "0.33.2"
3
3
  end
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.1
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.16
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: []