typeprof 0.15.3 → 0.20.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/.github/workflows/main.yml +1 -1
- data/Gemfile.lock +4 -4
- data/exe/typeprof +5 -1
- data/lib/typeprof/analyzer.rb +228 -54
- data/lib/typeprof/arguments.rb +1 -0
- data/lib/typeprof/builtin.rb +23 -23
- data/lib/typeprof/cli.rb +22 -2
- data/lib/typeprof/code-range.rb +177 -0
- data/lib/typeprof/config.rb +43 -18
- data/lib/typeprof/container-type.rb +3 -0
- data/lib/typeprof/export.rb +191 -15
- data/lib/typeprof/import.rb +25 -4
- data/lib/typeprof/iseq.rb +218 -16
- data/lib/typeprof/lsp.rb +865 -0
- data/lib/typeprof/method.rb +15 -11
- data/lib/typeprof/type.rb +46 -38
- data/lib/typeprof/utils.rb +18 -1
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +3 -0
- data/typeprof-lsp +3 -0
- data/typeprof.gemspec +1 -1
- data/vscode/.gitignore +5 -0
- data/vscode/.vscode/launch.json +16 -0
- data/vscode/.vscodeignore +7 -0
- data/vscode/README.md +22 -0
- data/vscode/development.md +31 -0
- data/vscode/package-lock.json +2211 -0
- data/vscode/package.json +71 -0
- data/vscode/sandbox/test.rb +24 -0
- data/vscode/src/extension.ts +285 -0
- data/vscode/tsconfig.json +15 -0
- metadata +18 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 109bbaf7daec0e4dce2f23c17a73d9528c51441cf61f1e23f5dc5d3c2c47dbff
|
4
|
+
data.tar.gz: bbd47838c15aa0e2a12645a8c9d5f56b0587323e96d919240681d747e2b73696
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e1ff8245d59eb81f253544b9a1a0e6a54f154fb17634e739210d4320e96619d59b70f9efd6811f600ab67e52ea341d3d9a886ab2b00d397ede5594f23ce8340
|
7
|
+
data.tar.gz: 2723c535e5f42e13e419e2646607ba9a5ec0a90c266fd2a927e658b133703f658af0cdfc2f392c6acd7f6f96fbbb54019251163f2109b1624158a48e019a56f2
|
data/.github/workflows/main.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
5
|
-
rbs (>= 1.
|
4
|
+
typeprof (0.20.0)
|
5
|
+
rbs (>= 1.6.2)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
docile (1.4.0)
|
12
12
|
power_assert (2.0.0)
|
13
13
|
rake (13.0.1)
|
14
|
-
rbs (1.6.
|
14
|
+
rbs (1.6.2)
|
15
15
|
simplecov (0.21.2)
|
16
16
|
docile (~> 1.1)
|
17
17
|
simplecov-html (~> 0.11)
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
simplecov-html (0.12.3)
|
20
20
|
simplecov_json_formatter (0.1.3)
|
21
21
|
stackprof (0.2.17)
|
22
|
-
test-unit (3.4.
|
22
|
+
test-unit (3.4.4)
|
23
23
|
power_assert
|
24
24
|
|
25
25
|
PLATFORMS
|
data/exe/typeprof
CHANGED
data/lib/typeprof/analyzer.rb
CHANGED
@@ -43,6 +43,14 @@ module TypeProf
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
def detailed_source_location(pc)
|
47
|
+
if @iseq
|
48
|
+
@iseq.detailed_source_location(pc)
|
49
|
+
else
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
46
54
|
def replace_cref(cref)
|
47
55
|
Context.new(@iseq, cref, @mid)
|
48
56
|
end
|
@@ -66,6 +74,14 @@ module TypeProf
|
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
77
|
+
def detailed_source_location(_pc)
|
78
|
+
if @caller_ep
|
79
|
+
@caller_ep.source_location
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
69
85
|
def replace_cref(cref)
|
70
86
|
# What to do?
|
71
87
|
end
|
@@ -101,6 +117,14 @@ module TypeProf
|
|
101
117
|
def source_location
|
102
118
|
@ctx.source_location(@pc)
|
103
119
|
end
|
120
|
+
|
121
|
+
def detailed_source_location
|
122
|
+
@ctx.detailed_source_location(@pc)
|
123
|
+
end
|
124
|
+
|
125
|
+
def absolute_path
|
126
|
+
@ctx.iseq.absolute_path
|
127
|
+
end
|
104
128
|
end
|
105
129
|
|
106
130
|
class StaticEnv
|
@@ -287,6 +311,9 @@ module TypeProf
|
|
287
311
|
|
288
312
|
@types_being_shown = []
|
289
313
|
@namespace = nil
|
314
|
+
|
315
|
+
@lsp_completion = nil
|
316
|
+
@lsp_signature_help = CodeRangeTable.new
|
290
317
|
end
|
291
318
|
|
292
319
|
def add_entrypoint(iseq)
|
@@ -335,7 +362,7 @@ module TypeProf
|
|
335
362
|
@subclasses = []
|
336
363
|
end
|
337
364
|
|
338
|
-
attr_reader :kind, :modules, :
|
365
|
+
attr_reader :kind, :modules, :methods, :ivars, :cvars, :absolute_path, :subclasses
|
339
366
|
attr_accessor :name, :klass_obj
|
340
367
|
|
341
368
|
def mix_module(kind, mod, type_args, singleton, absolute_path)
|
@@ -350,24 +377,43 @@ module TypeProf
|
|
350
377
|
end
|
351
378
|
|
352
379
|
def get_constant(name)
|
353
|
-
ty, = @consts[name]
|
354
|
-
ty || Type.any # XXX: warn?
|
380
|
+
ty, locs = @consts[name]
|
381
|
+
ty = ty || Type.any # XXX: warn?
|
382
|
+
return ty, locs
|
355
383
|
end
|
356
384
|
|
357
|
-
def add_constant(name, ty,
|
385
|
+
def add_constant(name, ty, def_ep)
|
358
386
|
if @consts[name]
|
359
387
|
# XXX: warn!
|
388
|
+
_, eps = @consts[name]
|
389
|
+
@consts[name] = [ty, eps + [def_ep&.detailed_source_location]]
|
390
|
+
return
|
391
|
+
end
|
392
|
+
@consts[name] = [ty, [def_ep&.detailed_source_location]]
|
393
|
+
end
|
394
|
+
|
395
|
+
def consts
|
396
|
+
@consts.lazy.flat_map do |name, (ty, eps)|
|
397
|
+
eps.map do |ep|
|
398
|
+
[name, [ty, ep]]
|
399
|
+
end
|
360
400
|
end
|
361
|
-
@consts[name] = [ty, absolute_path]
|
362
401
|
end
|
363
402
|
|
403
|
+
def add_class_open(name, open_ep)
|
404
|
+
ty, eps = @consts[name]
|
405
|
+
raise "call this only if the class is opened more than once" if ty.nil?
|
406
|
+
@consts[name] = [ty, eps + [open_ep&.detailed_source_location]]
|
407
|
+
end
|
408
|
+
|
409
|
+
|
364
410
|
def adjust_substitution_for_module(mods, mid, mthd, subst, &blk)
|
365
411
|
mods.each do |mod_def, type_args,|
|
366
412
|
if mod_def.klass_obj.type_params && type_args
|
367
413
|
subst2 = {}
|
368
414
|
mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
|
369
415
|
tyvar = Type::Var.new(tyvar)
|
370
|
-
subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
|
416
|
+
subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit])
|
371
417
|
end
|
372
418
|
mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
|
373
419
|
end
|
@@ -444,23 +490,23 @@ module TypeProf
|
|
444
490
|
cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
|
445
491
|
end
|
446
492
|
|
447
|
-
def new_class(cbase, name, type_params, superclass,
|
493
|
+
def new_class(cbase, name, type_params, superclass, def_ep)
|
448
494
|
show_name = cbase_path(cbase) + [name]
|
449
495
|
idx = @class_defs.size
|
450
496
|
if superclass
|
451
|
-
@class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
|
497
|
+
@class_defs[idx] = ClassDef.new(:class, show_name, def_ep&.absolute_path)
|
452
498
|
@class_defs[superclass.idx].subclasses << idx unless superclass == :__root__
|
453
499
|
klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
|
454
500
|
@class_defs[idx].klass_obj = klass
|
455
501
|
cbase ||= klass # for bootstrap
|
456
|
-
add_constant(cbase, name, klass,
|
502
|
+
add_constant(cbase, name, klass, def_ep)
|
457
503
|
return klass
|
458
504
|
else
|
459
505
|
# module
|
460
|
-
@class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
|
506
|
+
@class_defs[idx] = ClassDef.new(:module, show_name, def_ep&.absolute_path)
|
461
507
|
mod = Type::Class.new(:module, idx, type_params, nil, show_name)
|
462
508
|
@class_defs[idx].klass_obj = mod
|
463
|
-
add_constant(cbase, name, mod,
|
509
|
+
add_constant(cbase, name, mod, def_ep)
|
464
510
|
return mod
|
465
511
|
end
|
466
512
|
end
|
@@ -519,7 +565,7 @@ module TypeProf
|
|
519
565
|
subst2 = {}
|
520
566
|
klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
|
521
567
|
tyvar = Type::Var.new(tyvar)
|
522
|
-
subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
|
568
|
+
subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit])
|
523
569
|
end
|
524
570
|
subst = subst2
|
525
571
|
end
|
@@ -601,29 +647,53 @@ module TypeProf
|
|
601
647
|
nil
|
602
648
|
end
|
603
649
|
|
650
|
+
def get_all_methods(klass, singleton, _include_subclasses)
|
651
|
+
names = {}
|
652
|
+
|
653
|
+
if klass.kind == :class
|
654
|
+
while klass != :__root__
|
655
|
+
# TODO: module
|
656
|
+
@class_defs[klass.idx].methods.each_key do |singleton0, name|
|
657
|
+
if singleton == singleton0
|
658
|
+
names[name] = true
|
659
|
+
end
|
660
|
+
end
|
661
|
+
klass = klass.superclass
|
662
|
+
end
|
663
|
+
else
|
664
|
+
@class_defs[klass.idx].methods.each_key do |singleton0, name|
|
665
|
+
if singleton == singleton0
|
666
|
+
names[name] = true
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
names
|
672
|
+
end
|
673
|
+
|
604
674
|
def get_constant(klass, name)
|
605
675
|
if klass == Type.any
|
606
|
-
Type.any
|
676
|
+
[Type.any, nil]
|
607
677
|
elsif klass.is_a?(Type::Class)
|
608
678
|
@class_defs[klass.idx].get_constant(name)
|
609
679
|
else
|
610
|
-
Type.any
|
680
|
+
[Type.any, nil]
|
611
681
|
end
|
612
682
|
end
|
613
683
|
|
614
684
|
def search_constant(cref, name)
|
615
685
|
while cref != :bottom
|
616
|
-
|
617
|
-
return
|
686
|
+
ty, locs = get_constant(cref.klass, name)
|
687
|
+
return ty, locs if ty != Type.any
|
618
688
|
cref = cref.outer
|
619
689
|
end
|
620
690
|
|
621
|
-
Type.any
|
691
|
+
return Type.any, nil
|
622
692
|
end
|
623
693
|
|
624
|
-
def add_constant(klass, name, value,
|
694
|
+
def add_constant(klass, name, value, def_ep)
|
625
695
|
if klass.is_a?(Type::Class)
|
626
|
-
@class_defs[klass.idx].add_constant(name, value,
|
696
|
+
@class_defs[klass.idx].add_constant(name, value, def_ep)
|
627
697
|
end
|
628
698
|
end
|
629
699
|
|
@@ -694,7 +764,13 @@ module TypeProf
|
|
694
764
|
end
|
695
765
|
|
696
766
|
def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn)
|
697
|
-
|
767
|
+
if callee_ctx.is_a?(Context)
|
768
|
+
@executed_iseqs << callee_ctx.iseq
|
769
|
+
callee_type = callee_ctx.iseq.type
|
770
|
+
if caller_ep.ctx.is_a?(Context) && (callee_type == :method || callee_type == :block)
|
771
|
+
caller_ep.ctx.iseq&.add_called_iseq(caller_ep.pc, callee_ctx.iseq)
|
772
|
+
end
|
773
|
+
end
|
698
774
|
|
699
775
|
@callsites[callee_ctx] ||= {}
|
700
776
|
@callsites[callee_ctx][caller_ep] = ctn
|
@@ -743,23 +819,23 @@ module TypeProf
|
|
743
819
|
end
|
744
820
|
|
745
821
|
class VarTable
|
746
|
-
Entry = Struct.new(:rbs_declared, :read_continuations, :type, :absolute_paths)
|
822
|
+
Entry = Struct.new(:rbs_declared, :read_continuations, :type, :absolute_paths, :write_eps)
|
747
823
|
|
748
824
|
def initialize
|
749
825
|
@tbl = {}
|
750
826
|
end
|
751
827
|
|
752
828
|
def add_read!(site, ep, &ctn)
|
753
|
-
entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new)
|
829
|
+
entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new)
|
754
830
|
entry.read_continuations[ep] = ctn
|
755
831
|
entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context)
|
756
832
|
ty = entry.type
|
757
833
|
ty = Type.nil if ty == Type.bot
|
758
|
-
ctn[ty, ep]
|
834
|
+
ctn[ty, ep, entry.write_eps]
|
759
835
|
end
|
760
836
|
|
761
837
|
def add_write!(site, ty, ep, scratch)
|
762
|
-
entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new)
|
838
|
+
entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new)
|
763
839
|
if ep
|
764
840
|
if entry.rbs_declared
|
765
841
|
unless Type.match?(ty, entry.type)
|
@@ -768,10 +844,11 @@ module TypeProf
|
|
768
844
|
end
|
769
845
|
end
|
770
846
|
entry.absolute_paths << ep.ctx.iseq.absolute_path
|
847
|
+
entry.write_eps << ep
|
771
848
|
end
|
772
849
|
entry.type = entry.type.union(ty)
|
773
|
-
entry.read_continuations.each do |
|
774
|
-
ctn[ty, ep]
|
850
|
+
entry.read_continuations.each do |read_ep, ctn|
|
851
|
+
ctn[ty, read_ep, [ep]]
|
775
852
|
end
|
776
853
|
end
|
777
854
|
|
@@ -815,7 +892,8 @@ module TypeProf
|
|
815
892
|
recv.each_child do |recv|
|
816
893
|
class_def, singleton = get_ivar(recv, var)
|
817
894
|
next unless class_def
|
818
|
-
|
895
|
+
site = [singleton, var]
|
896
|
+
class_def.ivars.add_write!(site, ty, ep, self)
|
819
897
|
end
|
820
898
|
end
|
821
899
|
|
@@ -846,18 +924,18 @@ module TypeProf
|
|
846
924
|
end
|
847
925
|
|
848
926
|
def error(ep, msg)
|
849
|
-
p [ep.source_location, "[error] " + msg] if Config.verbose >= 2
|
927
|
+
p [ep.source_location, "[error] " + msg] if Config.current.verbose >= 2
|
850
928
|
@errors << [ep, "[error] " + msg]
|
851
929
|
end
|
852
930
|
|
853
931
|
def warn(ep, msg)
|
854
|
-
p [ep.source_location, "[warning] " + msg] if Config.verbose >= 2
|
932
|
+
p [ep.source_location, "[warning] " + msg] if Config.current.verbose >= 2
|
855
933
|
@errors << [ep, "[warning] " + msg]
|
856
934
|
end
|
857
935
|
|
858
936
|
def reveal_type(ep, ty)
|
859
937
|
key = ep.source_location
|
860
|
-
puts "reveal:#{ ep.source_location }:#{ ty.screen_name(self) }" if Config.verbose >= 2
|
938
|
+
puts "reveal:#{ ep.source_location }:#{ ty.screen_name(self) }" if Config.current.verbose >= 2
|
861
939
|
if @reveal_types[key]
|
862
940
|
@reveal_types[key] = @reveal_types[key].union(ty)
|
863
941
|
else
|
@@ -924,8 +1002,9 @@ module TypeProf
|
|
924
1002
|
end
|
925
1003
|
end
|
926
1004
|
|
927
|
-
def type_profile
|
928
|
-
|
1005
|
+
def type_profile(cancel_token = nil)
|
1006
|
+
cancel_token ||= Utils::TimerCancelToken.new(Config.current.max_sec)
|
1007
|
+
tick = Time.now
|
929
1008
|
iter_counter = 0
|
930
1009
|
stat_eps = Utils::MutableSet.new
|
931
1010
|
|
@@ -938,7 +1017,7 @@ module TypeProf
|
|
938
1017
|
if entrypoint.is_a?(String)
|
939
1018
|
file = entrypoint
|
940
1019
|
next if @loaded_files[File.expand_path(file)]
|
941
|
-
iseq = ISeq.compile(file)
|
1020
|
+
iseq, = ISeq.compile(file)
|
942
1021
|
else
|
943
1022
|
iseq = entrypoint
|
944
1023
|
end
|
@@ -953,7 +1032,7 @@ module TypeProf
|
|
953
1032
|
ep = @worklist.deletemin
|
954
1033
|
|
955
1034
|
iter_counter += 1
|
956
|
-
if Config.options[:show_indicator]
|
1035
|
+
if Config.current.options[:show_indicator]
|
957
1036
|
tick2 = Time.now
|
958
1037
|
if tick2 - tick >= 1
|
959
1038
|
tick = tick2
|
@@ -962,7 +1041,7 @@ module TypeProf
|
|
962
1041
|
end
|
963
1042
|
end
|
964
1043
|
|
965
|
-
if (Config.
|
1044
|
+
if (Config.current.max_iter && Config.current.max_iter <= iter_counter) || cancel_token.cancelled?
|
966
1045
|
@terminated = true
|
967
1046
|
break
|
968
1047
|
end
|
@@ -973,7 +1052,7 @@ module TypeProf
|
|
973
1052
|
|
974
1053
|
break if @terminated
|
975
1054
|
|
976
|
-
break unless Config.options[:stub_execution]
|
1055
|
+
break unless Config.current.options[:stub_execution]
|
977
1056
|
|
978
1057
|
begin
|
979
1058
|
iseq, (kind, dummy_continuation) = @pending_execution.first
|
@@ -981,7 +1060,7 @@ module TypeProf
|
|
981
1060
|
@pending_execution.delete(iseq)
|
982
1061
|
end while @executed_iseqs.include?(iseq)
|
983
1062
|
|
984
|
-
puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
|
1063
|
+
puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.current.verbose >= 2
|
985
1064
|
|
986
1065
|
break if !iseq
|
987
1066
|
case kind
|
@@ -1000,7 +1079,7 @@ module TypeProf
|
|
1000
1079
|
end
|
1001
1080
|
end
|
1002
1081
|
|
1003
|
-
$stderr.print "\r\e[K" if Config.options[:show_indicator]
|
1082
|
+
$stderr.print "\r\e[K" if Config.current.options[:show_indicator]
|
1004
1083
|
|
1005
1084
|
stat_eps
|
1006
1085
|
end
|
@@ -1017,13 +1096,70 @@ module TypeProf
|
|
1017
1096
|
RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show(stat_eps, output)
|
1018
1097
|
end
|
1019
1098
|
|
1099
|
+
def report_lsp
|
1100
|
+
errs = @errors.map do |ep, msg|
|
1101
|
+
[ep&.detailed_source_location, msg]
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
res = RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show_lsp
|
1105
|
+
|
1106
|
+
path, loc = Config.current.options[:signature_help_loc]
|
1107
|
+
if path
|
1108
|
+
sig_help_res = []
|
1109
|
+
sig_help = @lsp_signature_help[loc]
|
1110
|
+
if sig_help
|
1111
|
+
recv = sig_help[:recv]
|
1112
|
+
mid = sig_help[:mid]
|
1113
|
+
singleton = sig_help[:singleton]
|
1114
|
+
mdefs = sig_help[:mdefs]
|
1115
|
+
node_id = sig_help[:node_id]
|
1116
|
+
mdefs.each do |mdef|
|
1117
|
+
case mdef
|
1118
|
+
when ISeqMethodDef
|
1119
|
+
ctxs = @iseq_method_to_ctxs[mdef]
|
1120
|
+
next unless ctxs
|
1121
|
+
|
1122
|
+
ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
|
1123
|
+
|
1124
|
+
method_name = mid
|
1125
|
+
method_name = "self.#{ method_name }" if singleton
|
1126
|
+
|
1127
|
+
str = recv.screen_name(self)
|
1128
|
+
str += singleton ? "." : "#"
|
1129
|
+
str += method_name.to_s
|
1130
|
+
str += ": "
|
1131
|
+
sig, _, sig_help = show_method_signature(ctx)
|
1132
|
+
offset = str.size
|
1133
|
+
sig_help = sig_help.transform_values {|r| (r.begin + offset ... r.end + offset) }
|
1134
|
+
str += sig
|
1135
|
+
sig_help_res << [str, sig_help, node_id]
|
1136
|
+
when AliasMethodDef
|
1137
|
+
# TODO
|
1138
|
+
when TypedMethodDef
|
1139
|
+
mdef.rbs_source&.[](1)&.each do |rbs|
|
1140
|
+
# TODO: sig_help
|
1141
|
+
sig_help_res << [rbs, {}, node_id]
|
1142
|
+
end
|
1143
|
+
end
|
1144
|
+
end
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
{
|
1149
|
+
sigs: res,
|
1150
|
+
errors: errs,
|
1151
|
+
completion: @lsp_completion,
|
1152
|
+
signature_help: sig_help_res,
|
1153
|
+
}
|
1154
|
+
end
|
1155
|
+
|
1020
1156
|
def globalize_type(ty, env, ep)
|
1021
1157
|
if ep.outer
|
1022
1158
|
tmp_ep = ep
|
1023
1159
|
tmp_ep = tmp_ep.outer while tmp_ep.outer
|
1024
1160
|
env = @return_envs[tmp_ep]
|
1025
1161
|
end
|
1026
|
-
ty.globalize(env, {}, Config.options[:type_depth_limit])
|
1162
|
+
ty.globalize(env, {}, Config.current.options[:type_depth_limit])
|
1027
1163
|
end
|
1028
1164
|
|
1029
1165
|
def localize_type(ty, env, ep, alloc_site = AllocationSite.new(ep))
|
@@ -1031,13 +1167,13 @@ module TypeProf
|
|
1031
1167
|
tmp_ep = ep
|
1032
1168
|
tmp_ep = tmp_ep.outer while tmp_ep.outer
|
1033
1169
|
target_env = @return_envs[tmp_ep]
|
1034
|
-
target_env, ty = ty.localize(target_env, alloc_site, Config.options[:type_depth_limit])
|
1170
|
+
target_env, ty = ty.localize(target_env, alloc_site, Config.current.options[:type_depth_limit])
|
1035
1171
|
merge_return_env(tmp_ep) do |env|
|
1036
1172
|
env ? env.merge(target_env) : target_env
|
1037
1173
|
end
|
1038
1174
|
return env, ty
|
1039
1175
|
else
|
1040
|
-
return ty.localize(env, alloc_site, Config.options[:type_depth_limit])
|
1176
|
+
return ty.localize(env, alloc_site, Config.current.options[:type_depth_limit])
|
1041
1177
|
end
|
1042
1178
|
end
|
1043
1179
|
|
@@ -1099,13 +1235,16 @@ module TypeProf
|
|
1099
1235
|
end
|
1100
1236
|
|
1101
1237
|
def get_instance_variable(recv, var, ep, env)
|
1102
|
-
add_ivar_read!(recv, var, ep) do |ty, ep|
|
1238
|
+
add_ivar_read!(recv, var, ep) do |ty, ep, write_eps|
|
1103
1239
|
alloc_site = AllocationSite.new(ep)
|
1104
1240
|
nenv, ty = localize_type(ty, env, ep, alloc_site)
|
1105
1241
|
case ty
|
1106
1242
|
when Type::Local
|
1107
1243
|
@alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
|
1108
1244
|
end
|
1245
|
+
write_eps.each do |write_ep|
|
1246
|
+
ep.ctx.iseq.add_def_loc(ep.pc, write_ep.detailed_source_location)
|
1247
|
+
end
|
1109
1248
|
yield ty, nenv
|
1110
1249
|
end
|
1111
1250
|
end
|
@@ -1122,7 +1261,7 @@ module TypeProf
|
|
1122
1261
|
insn = ep.ctx.iseq.insns[ep.pc]
|
1123
1262
|
operands = insn.operands
|
1124
1263
|
|
1125
|
-
if Config.verbose >= 2
|
1264
|
+
if Config.current.verbose >= 2
|
1126
1265
|
# XXX: more dedicated output
|
1127
1266
|
puts "DEBUG: stack=%p" % [env.stack]
|
1128
1267
|
puts "DEBUG: %s (%s) PC=%d insn=%s sp=%d" % [ep.source_location, ep.ctx.iseq.name, ep.pc, insn.insn, env.stack.size]
|
@@ -1291,8 +1430,10 @@ module TypeProf
|
|
1291
1430
|
case flags & 7
|
1292
1431
|
when 0, 2 # CLASS / MODULE
|
1293
1432
|
type = (flags & 7) == 2 ? :module : :class
|
1294
|
-
existing_klass = get_constant(cbase, id) # TODO: multiple return values
|
1433
|
+
existing_klass, = get_constant(cbase, id) # TODO: multiple return values
|
1295
1434
|
if existing_klass.is_a?(Type::Class)
|
1435
|
+
# record re-opening location
|
1436
|
+
@class_defs[cbase.idx].add_class_open(id, ep)
|
1296
1437
|
klass = existing_klass
|
1297
1438
|
else
|
1298
1439
|
if existing_klass != Type.any
|
@@ -1317,7 +1458,7 @@ module TypeProf
|
|
1317
1458
|
superclass = nil
|
1318
1459
|
end
|
1319
1460
|
if cbase.is_a?(Type::Class)
|
1320
|
-
klass = new_class(cbase, id, [], superclass, ep
|
1461
|
+
klass = new_class(cbase, id, [], superclass, ep)
|
1321
1462
|
if superclass
|
1322
1463
|
add_superclass_type_args!(klass, superclass.type_params.map { Type.any })
|
1323
1464
|
|
@@ -1631,7 +1772,7 @@ module TypeProf
|
|
1631
1772
|
var, = operands
|
1632
1773
|
ty = Type.builtin_global_variable_type(var)
|
1633
1774
|
if ty
|
1634
|
-
ty = get_constant(Type::Builtin[:obj], ty) if ty.is_a?(Symbol)
|
1775
|
+
ty, locs = get_constant(Type::Builtin[:obj], ty) if ty.is_a?(Symbol)
|
1635
1776
|
env, ty = localize_type(ty, env, ep)
|
1636
1777
|
env = env.push(ty)
|
1637
1778
|
else
|
@@ -1776,20 +1917,23 @@ module TypeProf
|
|
1776
1917
|
name, = operands
|
1777
1918
|
env, (cbase, _allow_nil,) = env.pop(2)
|
1778
1919
|
if cbase == Type.nil
|
1779
|
-
ty = search_constant(ep.ctx.cref, name)
|
1920
|
+
ty, locs = search_constant(ep.ctx.cref, name)
|
1780
1921
|
env, ty = localize_type(ty, env, ep)
|
1781
1922
|
env = env.push(ty)
|
1782
1923
|
elsif cbase == Type.any
|
1783
1924
|
env = env.push(Type.any) # XXX: warning needed?
|
1784
1925
|
else
|
1785
|
-
ty = get_constant(cbase, name)
|
1926
|
+
ty, locs = get_constant(cbase, name)
|
1786
1927
|
env, ty = localize_type(ty, env, ep)
|
1787
1928
|
env = env.push(ty)
|
1788
1929
|
end
|
1930
|
+
locs&.each do |loc|
|
1931
|
+
ep.ctx.iseq.add_def_loc(ep.pc, loc)
|
1932
|
+
end
|
1789
1933
|
when :setconstant
|
1790
1934
|
name, = operands
|
1791
1935
|
env, (ty, cbase) = env.pop(2)
|
1792
|
-
old_ty = get_constant(cbase, name)
|
1936
|
+
old_ty, = get_constant(cbase, name)
|
1793
1937
|
if old_ty != Type.any # XXX???
|
1794
1938
|
warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }")
|
1795
1939
|
end
|
@@ -1798,7 +1942,7 @@ module TypeProf
|
|
1798
1942
|
@class_defs[ty.idx].name = cbase_path(cbase) + [name]
|
1799
1943
|
end
|
1800
1944
|
end
|
1801
|
-
add_constant(cbase, name, globalize_type(ty, env, ep), ep
|
1945
|
+
add_constant(cbase, name, globalize_type(ty, env, ep), ep)
|
1802
1946
|
|
1803
1947
|
when :getspecial
|
1804
1948
|
key, type = operands
|
@@ -2186,10 +2330,26 @@ module TypeProf
|
|
2186
2330
|
merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env }
|
2187
2331
|
end
|
2188
2332
|
|
2333
|
+
aargs.node_id = opt[:node_id]
|
2334
|
+
|
2189
2335
|
return env, recv, mid, aargs
|
2190
2336
|
end
|
2191
2337
|
|
2192
2338
|
def do_send(recvs, mid, aargs, ep, env, &ctn)
|
2339
|
+
if mid == :__typeprof_lsp_completion
|
2340
|
+
names = {}
|
2341
|
+
recvs.each_child do |recv|
|
2342
|
+
case recv
|
2343
|
+
when Type::Void, Type::Any
|
2344
|
+
else
|
2345
|
+
klass, singleton, include_subclasses = recv.method_dispatch_info
|
2346
|
+
names.merge!(get_all_methods(klass, singleton, include_subclasses)) if klass
|
2347
|
+
end
|
2348
|
+
end
|
2349
|
+
@lsp_completion = names
|
2350
|
+
return ctn[Type.any, ep, env]
|
2351
|
+
end
|
2352
|
+
|
2193
2353
|
recvs.each_child do |recv|
|
2194
2354
|
case recv
|
2195
2355
|
when Type::Void
|
@@ -2201,6 +2361,19 @@ module TypeProf
|
|
2201
2361
|
klass, singleton, include_subclasses = recv.method_dispatch_info
|
2202
2362
|
meths = get_method(klass, singleton, include_subclasses, mid) if klass
|
2203
2363
|
if meths
|
2364
|
+
path, loc = Config.current.options[:signature_help_loc]
|
2365
|
+
if path && path == ep.ctx.iseq.path && mid != :inherited # XXX: too ad-hoc!!!
|
2366
|
+
path, code_range = ep&.detailed_source_location
|
2367
|
+
if path && code_range&.contain_loc?(loc)
|
2368
|
+
@lsp_signature_help[code_range] = {
|
2369
|
+
recv: recv,
|
2370
|
+
mid: mid,
|
2371
|
+
singleton: singleton,
|
2372
|
+
mdefs: meths,
|
2373
|
+
node_id: aargs.node_id,
|
2374
|
+
}
|
2375
|
+
end
|
2376
|
+
end
|
2204
2377
|
meths.each do |meth|
|
2205
2378
|
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2206
2379
|
end
|
@@ -2282,7 +2455,7 @@ module TypeProf
|
|
2282
2455
|
|
2283
2456
|
bsig ||= BlockSignature.new([], [], nil, Type.nil)
|
2284
2457
|
|
2285
|
-
bsig = bsig.screen_name(nil, self)
|
2458
|
+
bsig, = bsig.screen_name(nil, self)
|
2286
2459
|
ret_ty = ret_ty.screen_name(self)
|
2287
2460
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2288
2461
|
|
@@ -2317,7 +2490,7 @@ module TypeProf
|
|
2317
2490
|
|
2318
2491
|
begin
|
2319
2492
|
@types_being_shown << farg_tys << ret_ty
|
2320
|
-
farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
|
2493
|
+
farg_tys, = farg_tys ? farg_tys.screen_name(nil, self) : ["(unknown)"]
|
2321
2494
|
ret_ty = ret_ty.screen_name(self)
|
2322
2495
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2323
2496
|
|
@@ -2330,15 +2503,16 @@ module TypeProf
|
|
2330
2503
|
|
2331
2504
|
def show_method_signature(ctx)
|
2332
2505
|
farg_tys = @method_signatures[ctx]
|
2506
|
+
return nil unless farg_tys
|
2333
2507
|
ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot
|
2334
2508
|
|
2335
2509
|
untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self)
|
2336
2510
|
|
2337
|
-
farg_tys = farg_tys.screen_name(ctx.iseq, self)
|
2511
|
+
farg_tys, ranges = farg_tys.screen_name(ctx.iseq, self)
|
2338
2512
|
ret_ty = ret_ty.screen_name(self)
|
2339
2513
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2340
2514
|
|
2341
|
-
|
2515
|
+
return "#{ (farg_tys.empty? ? "" : "#{ farg_tys } ") }-> #{ ret_ty }", untyped, ranges
|
2342
2516
|
end
|
2343
2517
|
end
|
2344
2518
|
end
|
data/lib/typeprof/arguments.rb
CHANGED