typeprof 0.15.0 → 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 +261 -66
- data/lib/typeprof/arguments.rb +1 -0
- data/lib/typeprof/builtin.rb +30 -22
- 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 +10 -1
- data/lib/typeprof/export.rb +199 -20
- data/lib/typeprof/import.rb +30 -4
- data/lib/typeprof/iseq.rb +504 -200
- data/lib/typeprof/lsp.rb +865 -0
- data/lib/typeprof/method.rb +17 -13
- 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/smoke/array15.rb +1 -1
- data/smoke/array6.rb +2 -2
- data/smoke/array8.rb +1 -1
- data/smoke/block-args2.rb +3 -3
- data/smoke/block-args3.rb +4 -4
- data/smoke/break2.rb +1 -1
- data/smoke/gvar2.rb +0 -3
- data/smoke/hash-bot.rb +1 -1
- data/smoke/hash4.rb +1 -1
- data/smoke/identifier_keywords.rb +17 -0
- data/smoke/next2.rb +1 -1
- data/smoke/or_raise.rb +18 -0
- data/smoke/parameterizedd-self.rb +2 -2
- data/smoke/pattern-match1.rb +1 -6
- data/smoke/rbs-vars.rb +0 -3
- data/testbed/ao.rb +1 -1
- 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 +20 -5
data/lib/typeprof/arguments.rb
CHANGED
data/lib/typeprof/builtin.rb
CHANGED
@@ -624,7 +624,7 @@ module TypeProf
|
|
624
624
|
end
|
625
625
|
|
626
626
|
def self.file_load(path, ep, env, scratch, &ctn)
|
627
|
-
iseq = ISeq.compile(path)
|
627
|
+
iseq, = ISeq.compile(path)
|
628
628
|
callee_ep, callee_env = TypeProf.starting_state(iseq)
|
629
629
|
scratch.merge_env(callee_ep, callee_env)
|
630
630
|
|
@@ -793,26 +793,27 @@ module TypeProf
|
|
793
793
|
|
794
794
|
Import.import_builtin(scratch)
|
795
795
|
|
796
|
-
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
|
797
|
-
Type::Builtin[:int] = scratch.get_constant(klass_obj, :Integer)
|
798
|
-
Type::Builtin[:float] = scratch.get_constant(klass_obj, :Float)
|
799
|
-
Type::Builtin[:rational] = scratch.get_constant(klass_obj, :Rational)
|
800
|
-
Type::Builtin[:complex] = scratch.get_constant(klass_obj, :Complex)
|
801
|
-
Type::Builtin[:sym] = scratch.get_constant(klass_obj, :Symbol)
|
802
|
-
Type::Builtin[:str] = scratch.get_constant(klass_obj, :String)
|
803
|
-
Type::Builtin[:struct] = scratch.get_constant(klass_obj, :Struct)
|
804
|
-
Type::Builtin[:ary] = scratch.get_constant(klass_obj, :Array)
|
805
|
-
Type::Builtin[:hash] = scratch.get_constant(klass_obj, :Hash)
|
806
|
-
Type::Builtin[:io] = scratch.get_constant(klass_obj, :IO)
|
807
|
-
Type::Builtin[:proc] = scratch.get_constant(klass_obj, :Proc)
|
808
|
-
Type::Builtin[:range] = scratch.get_constant(klass_obj, :Range)
|
809
|
-
Type::Builtin[:regexp] = scratch.get_constant(klass_obj, :Regexp)
|
810
|
-
Type::Builtin[:matchdata] = scratch.get_constant(klass_obj, :MatchData)
|
811
|
-
Type::Builtin[:class] = scratch.get_constant(klass_obj, :Class)
|
812
|
-
Type::Builtin[:module] = scratch.get_constant(klass_obj, :Module)
|
813
|
-
Type::Builtin[:exc] = scratch.get_constant(klass_obj, :Exception)
|
814
|
-
Type::Builtin[:encoding] = scratch.get_constant(klass_obj, :Encoding)
|
815
|
-
Type::Builtin[:enumerator] = scratch.get_constant(klass_obj, :Enumerator)
|
796
|
+
Type::Builtin[:vmcore] , = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
|
797
|
+
Type::Builtin[:int] , = scratch.get_constant(klass_obj, :Integer)
|
798
|
+
Type::Builtin[:float] , = scratch.get_constant(klass_obj, :Float)
|
799
|
+
Type::Builtin[:rational] , = scratch.get_constant(klass_obj, :Rational)
|
800
|
+
Type::Builtin[:complex] , = scratch.get_constant(klass_obj, :Complex)
|
801
|
+
Type::Builtin[:sym] , = scratch.get_constant(klass_obj, :Symbol)
|
802
|
+
Type::Builtin[:str] , = scratch.get_constant(klass_obj, :String)
|
803
|
+
Type::Builtin[:struct] , = scratch.get_constant(klass_obj, :Struct)
|
804
|
+
Type::Builtin[:ary] , = scratch.get_constant(klass_obj, :Array)
|
805
|
+
Type::Builtin[:hash] , = scratch.get_constant(klass_obj, :Hash)
|
806
|
+
Type::Builtin[:io] , = scratch.get_constant(klass_obj, :IO)
|
807
|
+
Type::Builtin[:proc] , = scratch.get_constant(klass_obj, :Proc)
|
808
|
+
Type::Builtin[:range] , = scratch.get_constant(klass_obj, :Range)
|
809
|
+
Type::Builtin[:regexp] , = scratch.get_constant(klass_obj, :Regexp)
|
810
|
+
Type::Builtin[:matchdata] , = scratch.get_constant(klass_obj, :MatchData)
|
811
|
+
Type::Builtin[:class] , = scratch.get_constant(klass_obj, :Class)
|
812
|
+
Type::Builtin[:module] , = scratch.get_constant(klass_obj, :Module)
|
813
|
+
Type::Builtin[:exc] , = scratch.get_constant(klass_obj, :Exception)
|
814
|
+
Type::Builtin[:encoding] , = scratch.get_constant(klass_obj, :Encoding)
|
815
|
+
Type::Builtin[:enumerator] , = scratch.get_constant(klass_obj, :Enumerator)
|
816
|
+
Type::Builtin[:kernel] , = scratch.get_constant(klass_obj, :Kernel)
|
816
817
|
|
817
818
|
klass_vmcore = Type::Builtin[:vmcore]
|
818
819
|
klass_ary = Type::Builtin[:ary]
|
@@ -825,6 +826,7 @@ module TypeProf
|
|
825
826
|
scratch.set_custom_method(klass_vmcore, :"core#undef_method", Builtin.method(:vmcore_undef_method))
|
826
827
|
scratch.set_custom_method(klass_vmcore, :"core#hash_merge_kwd", Builtin.method(:vmcore_hash_merge_kwd))
|
827
828
|
scratch.set_custom_method(klass_vmcore, :"core#raise", Builtin.method(:vmcore_raise))
|
829
|
+
|
828
830
|
scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda))
|
829
831
|
scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new))
|
830
832
|
scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p), false)
|
@@ -879,7 +881,13 @@ module TypeProf
|
|
879
881
|
# ENV: Hash[String, String]
|
880
882
|
str_ty = Type::Instance.new(Type::Builtin[:str])
|
881
883
|
env_ty = Type.gen_hash {|h| h[str_ty] = Type.optional(str_ty) }
|
882
|
-
scratch.add_constant(klass_obj, :ENV, env_ty,
|
884
|
+
scratch.add_constant(klass_obj, :ENV, env_ty, nil)
|
885
|
+
|
886
|
+
scratch.search_method(Type::Builtin[:kernel], false, :sprintf) do |mdefs,|
|
887
|
+
mdefs.each do |mdef|
|
888
|
+
scratch.add_method(klass_vmcore, :"core#sprintf", false, mdef)
|
889
|
+
end
|
890
|
+
end
|
883
891
|
end
|
884
892
|
end
|
885
893
|
end
|
data/lib/typeprof/cli.rb
CHANGED
@@ -18,11 +18,15 @@ module TypeProf
|
|
18
18
|
verbose = 1
|
19
19
|
|
20
20
|
options = {}
|
21
|
+
lsp_options = {}
|
21
22
|
dir_filter = nil
|
22
23
|
gem_rbs_features = []
|
23
24
|
gem_repo_dirs = []
|
24
25
|
show_version = false
|
25
26
|
max_sec = max_iter = nil
|
27
|
+
collection_path = RBS::Collection::Config::PATH
|
28
|
+
|
29
|
+
load_path_ext = []
|
26
30
|
|
27
31
|
opt.separator ""
|
28
32
|
opt.separator "Options:"
|
@@ -30,9 +34,12 @@ module TypeProf
|
|
30
34
|
opt.on("-q", "--quiet", "Do not display progress indicator") { options[:show_indicator] = false }
|
31
35
|
opt.on("-v", "--verbose", "Alias to --show-errors") { options[:show_errors] = true }
|
32
36
|
opt.on("--version", "Display typeprof version") { show_version = true }
|
33
|
-
opt.on("-I DIR", "Add DIR to the load/require path") {|v|
|
37
|
+
opt.on("-I DIR", "Add DIR to the load/require path") {|v| load_path_ext << v }
|
34
38
|
opt.on("-r FEATURE", "Require RBS of the FEATURE gem") {|v| gem_rbs_features << v }
|
35
39
|
opt.on("--repo DIR", "Add DIR to the RBS repository") {|v| gem_repo_dirs << v }
|
40
|
+
opt.on("--collection PATH", "File path of collection configuration") { |v| collection_path = v }
|
41
|
+
opt.on("--no-collection", "Ignore collection configuration") { collection_path = nil }
|
42
|
+
opt.on("--lsp", "LSP mode") {|v| options[:lsp] = true }
|
36
43
|
|
37
44
|
opt.separator ""
|
38
45
|
opt.separator "Analysis output options:"
|
@@ -68,8 +75,14 @@ module TypeProf
|
|
68
75
|
opt.on("--debug", "Display analysis log (for debugging purpose)") { verbose = 2 }
|
69
76
|
opt.on("--[no-]stackprof MODE", /\Acpu|wall|object\z/, "Enable stackprof (for debugging purpose)") {|v| options[:stackprof] = v.to_sym }
|
70
77
|
|
78
|
+
opt.separator ""
|
79
|
+
opt.separator "LSP options:"
|
80
|
+
opt.on("--port PORT", Integer, "Specify a port number to listen for requests on") {|v| lsp_options[:port] = v }
|
81
|
+
|
71
82
|
opt.parse!(argv)
|
72
83
|
|
84
|
+
$LOAD_PATH.unshift(*load_path_ext)
|
85
|
+
|
73
86
|
dir_filter ||= ConfigData::DEFAULT_DIR_FILTER
|
74
87
|
rb_files = []
|
75
88
|
rbs_files = []
|
@@ -82,22 +95,29 @@ module TypeProf
|
|
82
95
|
end
|
83
96
|
|
84
97
|
puts "typeprof #{ VERSION }" if show_version
|
85
|
-
if rb_files.empty?
|
98
|
+
if rb_files.empty? && !options[:lsp]
|
86
99
|
exit if show_version
|
87
100
|
raise OptionParser::InvalidOption.new("no input files")
|
88
101
|
end
|
89
102
|
|
103
|
+
if !options[:lsp] && !lsp_options.empty?
|
104
|
+
exit if show_version
|
105
|
+
raise OptionParser::InvalidOption.new("lsp options with non-lsp mode")
|
106
|
+
end
|
107
|
+
|
90
108
|
ConfigData.new(
|
91
109
|
rb_files: rb_files,
|
92
110
|
rbs_files: rbs_files,
|
93
111
|
output: output,
|
94
112
|
gem_rbs_features: gem_rbs_features,
|
95
113
|
gem_repo_dirs: gem_repo_dirs,
|
114
|
+
collection_path: collection_path,
|
96
115
|
verbose: verbose,
|
97
116
|
dir_filter: dir_filter,
|
98
117
|
max_sec: max_sec,
|
99
118
|
max_iter: max_iter,
|
100
119
|
options: options,
|
120
|
+
lsp_options: lsp_options,
|
101
121
|
)
|
102
122
|
|
103
123
|
rescue OptionParser::InvalidOption
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module TypeProf
|
2
|
+
class CodeLocation
|
3
|
+
# In Ruby, lineno is 1-origin, and column is 0-origin
|
4
|
+
def initialize(lineno, column)
|
5
|
+
@lineno = lineno
|
6
|
+
@column = column
|
7
|
+
end
|
8
|
+
|
9
|
+
def inspect
|
10
|
+
"(%d,%d)" % [@lineno, @column]
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :lineno, :column
|
14
|
+
|
15
|
+
def self.from_lsp(lsp_loc)
|
16
|
+
# In the Language Server Protocol, lineno and column are both 0-origin
|
17
|
+
CodeLocation.new(lsp_loc[:line] + 1, lsp_loc[:character])
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_lsp
|
21
|
+
{ line: @lineno - 1, character: @column }
|
22
|
+
end
|
23
|
+
|
24
|
+
def advance_cursor(offset, source_text)
|
25
|
+
new_lineno = @lineno
|
26
|
+
new_column = @column
|
27
|
+
while offset > 0
|
28
|
+
line_text = source_text.lines[new_lineno - 1]
|
29
|
+
if new_column + offset >= line_text.length
|
30
|
+
advanced = line_text.length - new_column
|
31
|
+
offset -= advanced
|
32
|
+
new_lineno += 1
|
33
|
+
new_column = 0
|
34
|
+
else
|
35
|
+
new_column += offset
|
36
|
+
break
|
37
|
+
end
|
38
|
+
end
|
39
|
+
CodeLocation.new(new_lineno, new_column)
|
40
|
+
end
|
41
|
+
|
42
|
+
def <=>(other)
|
43
|
+
ret = @lineno <=> other.lineno
|
44
|
+
return ret if ret != 0
|
45
|
+
@column <=> other.column
|
46
|
+
end
|
47
|
+
|
48
|
+
include Comparable
|
49
|
+
end
|
50
|
+
|
51
|
+
class CodeRange
|
52
|
+
def initialize(first, last)
|
53
|
+
@first, @last = first, last
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
"%p-%p" % [@first, @last]
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :first
|
61
|
+
attr_reader :last
|
62
|
+
|
63
|
+
def self.from_lsp(lsp_range)
|
64
|
+
CodeRange.new(CodeLocation.from_lsp(lsp[:start]), CodeLocation.from_lsp(lsp[:end]))
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.from_rbs(rbs_loc)
|
68
|
+
CodeRange.new(
|
69
|
+
CodeLocation.new(rbs_loc.start_line, rbs_loc.start_column),
|
70
|
+
CodeLocation.new(rbs_loc.end_line, rbs_loc.end_column),
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_lsp
|
75
|
+
{ start: @first.to_lsp, end: @last.to_lsp }
|
76
|
+
end
|
77
|
+
|
78
|
+
def contain_loc?(loc)
|
79
|
+
@first <= loc && loc < @last
|
80
|
+
end
|
81
|
+
|
82
|
+
def contain?(other)
|
83
|
+
@first <= other.first && other.last <= @last
|
84
|
+
end
|
85
|
+
|
86
|
+
def overlap?(other)
|
87
|
+
if @first <= other.first
|
88
|
+
return @last > other.first
|
89
|
+
else
|
90
|
+
return @first < other.last
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class CodeRangeTable
|
96
|
+
Entry = Struct.new(:range, :value, :children)
|
97
|
+
|
98
|
+
class Entry
|
99
|
+
def inspect
|
100
|
+
"[%p, %p, %p]" % [range, value, children]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def initialize(list = [])
|
105
|
+
@list = list # Array[Entry]
|
106
|
+
end
|
107
|
+
|
108
|
+
def []=(range, value)
|
109
|
+
i_b = @list.bsearch_index {|e| e.range.last > range.first } || @list.size
|
110
|
+
i_e = @list.bsearch_index {|e| e.range.first >= range.last } || @list.size
|
111
|
+
if i_b < i_e
|
112
|
+
# for all i in i_b...i_e, @list[i] overlaps with the range
|
113
|
+
if i_e - i_b == 1
|
114
|
+
if range.contain?(@list[i_b].range)
|
115
|
+
@list[i_b] = Entry[range, value, CodeRangeTable.new(@list[i_b, 1])]
|
116
|
+
elsif @list[i_b].range.contain?(range)
|
117
|
+
@list[i_b].children[range] = value
|
118
|
+
else
|
119
|
+
raise
|
120
|
+
end
|
121
|
+
else
|
122
|
+
if range.contain?(@list[i_b].range) && range.contain?(@list[i_e - 1].range)
|
123
|
+
@list[i_b...i_e] = [Entry[range, value, CodeRangeTable.new(@list[i_b...i_e])]]
|
124
|
+
else
|
125
|
+
raise
|
126
|
+
end
|
127
|
+
end
|
128
|
+
else
|
129
|
+
@list[i_b, 0] = [Entry[range, value, CodeRangeTable.new]]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def [](loc)
|
134
|
+
e = @list.bsearch {|e| e.range.last > loc }
|
135
|
+
if e && e.range.contain_loc?(loc)
|
136
|
+
return e.children[loc] || e.value
|
137
|
+
end
|
138
|
+
return nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if $0 == __FILE__
|
144
|
+
include TypeProf
|
145
|
+
cr1 = CodeRange.new(CodeLocation.new(1, 0), CodeLocation.new(1, 2))
|
146
|
+
cr2 = CodeRange.new(CodeLocation.new(1, 2), CodeLocation.new(1, 4))
|
147
|
+
cr3 = CodeRange.new(CodeLocation.new(2, 0), CodeLocation.new(2, 2))
|
148
|
+
cr4 = CodeRange.new(CodeLocation.new(2, 3), CodeLocation.new(2, 5))
|
149
|
+
cr1and2 = CodeRange.new(CodeLocation.new(1, 0), CodeLocation.new(1, 5))
|
150
|
+
cr3and4 = CodeRange.new(CodeLocation.new(2, 0), CodeLocation.new(2, 5))
|
151
|
+
[[cr1, "A"], [cr2, "B"], [cr3, "C"], [cr4, "D"], [cr1and2, "AB"], [cr3and4, "CD"]].permutation do |ary|
|
152
|
+
tbl = CodeRangeTable.new
|
153
|
+
ary.each do |cr, v|
|
154
|
+
tbl[cr] = v
|
155
|
+
end
|
156
|
+
values = []
|
157
|
+
[1, 2].each do |lineno|
|
158
|
+
(0..5).each do |column|
|
159
|
+
values << tbl[CodeLocation.new(lineno, column)]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
raise if values != ["A", "A", "B", "B", "AB", nil, "C", "C", "CD", "D", "D", nil]
|
163
|
+
end
|
164
|
+
|
165
|
+
source = <<~EOS
|
166
|
+
AB
|
167
|
+
CDE
|
168
|
+
F
|
169
|
+
EOS
|
170
|
+
a_loc = CodeLocation.new(1, 0)
|
171
|
+
b_loc = a_loc.advance_cursor(1, source)
|
172
|
+
raise unless b_loc.inspect == "(1,1)"
|
173
|
+
c_loc = a_loc.advance_cursor(3, source)
|
174
|
+
raise unless c_loc.inspect == "(2,0)"
|
175
|
+
f_loc = c_loc.advance_cursor(4, source)
|
176
|
+
raise unless f_loc.inspect == "(3,0)"
|
177
|
+
end
|
data/lib/typeprof/config.rb
CHANGED
@@ -7,11 +7,14 @@ module TypeProf
|
|
7
7
|
:output,
|
8
8
|
:gem_rbs_features,
|
9
9
|
:gem_repo_dirs,
|
10
|
+
:collection_path,
|
10
11
|
:verbose,
|
11
12
|
:dir_filter,
|
12
13
|
:max_iter,
|
13
14
|
:max_sec,
|
14
15
|
:options,
|
16
|
+
:lsp_options,
|
17
|
+
:lsp,
|
15
18
|
keyword_init: true
|
16
19
|
)
|
17
20
|
|
@@ -43,6 +46,9 @@ module TypeProf
|
|
43
46
|
union_width_limit: 10,
|
44
47
|
stackprof: nil,
|
45
48
|
}.merge(opt[:options])
|
49
|
+
opt[:lsp_options] = {
|
50
|
+
port: 0,
|
51
|
+
}.merge(opt[:lsp_options] || {})
|
46
52
|
super(**opt)
|
47
53
|
end
|
48
54
|
|
@@ -61,29 +67,39 @@ module TypeProf
|
|
61
67
|
]
|
62
68
|
end
|
63
69
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
TypeProf.send(:remove_const, :Config)
|
70
|
+
module Config
|
71
|
+
def self.current
|
72
|
+
Thread.current[:typeprof_config]
|
68
73
|
end
|
69
|
-
TypeProf.const_set(:Config, config)
|
70
74
|
|
71
|
-
|
75
|
+
def self.set_current(config)
|
76
|
+
Thread.current[:typeprof_config] = config
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.analyze(config, cancel_token = nil)
|
81
|
+
# Deploy the config to the TypeProf::Config (Note: This is thread local)
|
82
|
+
Config.set_current(config)
|
83
|
+
|
84
|
+
if Config.current.options[:stackprof]
|
72
85
|
require "stackprof"
|
73
|
-
out = "typeprof-stackprof-#{ Config.options[:stackprof] }.dump"
|
74
|
-
StackProf.start(mode: Config.options[:stackprof], out: out, raw: true)
|
86
|
+
out = "typeprof-stackprof-#{ Config.current.options[:stackprof] }.dump"
|
87
|
+
StackProf.start(mode: Config.current.options[:stackprof], out: out, raw: true)
|
75
88
|
end
|
76
89
|
|
77
90
|
scratch = Scratch.new
|
78
91
|
Builtin.setup_initial_global_env(scratch)
|
79
92
|
|
80
|
-
Config.gem_rbs_features.each do |feature|
|
93
|
+
Config.current.gem_rbs_features.each do |feature|
|
81
94
|
Import.import_library(scratch, feature)
|
82
95
|
end
|
83
96
|
|
97
|
+
collection_path = config.collection_path
|
98
|
+
Import.import_rbs_collection(scratch, collection_path) if collection_path&.exist?
|
99
|
+
|
84
100
|
rbs_files = []
|
85
101
|
rbs_codes = []
|
86
|
-
Config.rbs_files.each do |rbs|
|
102
|
+
Config.current.rbs_files.each do |rbs|
|
87
103
|
if rbs.is_a?(Array) # [String name, String content]
|
88
104
|
rbs_codes << rbs
|
89
105
|
else
|
@@ -95,30 +111,39 @@ module TypeProf
|
|
95
111
|
Import.import_rbs_code(scratch, name, content)
|
96
112
|
end
|
97
113
|
|
98
|
-
|
114
|
+
def_code_range_table = nil
|
115
|
+
caller_code_range_table = nil
|
116
|
+
Config.current.rb_files.each do |rb|
|
99
117
|
if rb.is_a?(Array) # [String name, String content]
|
100
|
-
iseq = ISeq.compile_str(*rb.reverse)
|
118
|
+
iseq, def_tbl, caller_tbl = ISeq.compile_str(*rb.reverse)
|
119
|
+
def_code_range_table ||= def_tbl
|
120
|
+
caller_code_range_table ||= caller_tbl
|
101
121
|
else
|
102
122
|
iseq = rb
|
103
123
|
end
|
104
124
|
scratch.add_entrypoint(iseq)
|
105
125
|
end
|
106
126
|
|
107
|
-
result = scratch.type_profile
|
127
|
+
result = scratch.type_profile(cancel_token)
|
128
|
+
|
129
|
+
if Config.current.options[:lsp]
|
130
|
+
return scratch.report_lsp, def_code_range_table, caller_code_range_table
|
131
|
+
end
|
108
132
|
|
109
|
-
if Config.output.respond_to?(:write)
|
110
|
-
scratch.report(result, Config.output)
|
133
|
+
if Config.current.output.respond_to?(:write)
|
134
|
+
scratch.report(result, Config.current.output)
|
111
135
|
else
|
112
|
-
open(Config.output, "w") do |output|
|
136
|
+
open(Config.current.output, "w") do |output|
|
113
137
|
scratch.report(result, output)
|
114
138
|
end
|
115
139
|
end
|
116
140
|
|
117
141
|
rescue TypeProfError => exc
|
118
|
-
exc.report(Config.output)
|
142
|
+
exc.report(Config.current.output)
|
119
143
|
|
144
|
+
return nil
|
120
145
|
ensure
|
121
|
-
if Config.options[:stackprof] && defined?(StackProf)
|
146
|
+
if Config.current.options[:stackprof] && defined?(StackProf)
|
122
147
|
StackProf.stop
|
123
148
|
StackProf.results
|
124
149
|
end
|
@@ -307,7 +307,11 @@ module TypeProf
|
|
307
307
|
def screen_name(scratch)
|
308
308
|
if @rest_ty == Type.bot
|
309
309
|
if @lead_tys.empty?
|
310
|
-
|
310
|
+
# This is heuristic: in general, an empty array is a wrong guess.
|
311
|
+
# Note that an empty array is representable as "[ ]" in RBS, but
|
312
|
+
# users often have to modify it to "Array[something]".
|
313
|
+
# In this term, "Array[untyped]" is considered more useful than "[ ]".
|
314
|
+
return "Array[untyped]"
|
311
315
|
end
|
312
316
|
s = @lead_tys.map do |ty|
|
313
317
|
ty.screen_name(scratch)
|
@@ -317,6 +321,9 @@ module TypeProf
|
|
317
321
|
end
|
318
322
|
|
319
323
|
"*[#{ squash.screen_name(scratch) }]"
|
324
|
+
rescue SystemStackError
|
325
|
+
p squash
|
326
|
+
exit!
|
320
327
|
end
|
321
328
|
|
322
329
|
def pretty_print(q)
|
@@ -673,6 +680,8 @@ module TypeProf
|
|
673
680
|
k_ty = k_ty.union(k)
|
674
681
|
v_ty = v_ty.union(v)
|
675
682
|
end
|
683
|
+
k_ty = Type.any if k_ty == Type.bot
|
684
|
+
v_ty = Type.any if v_ty == Type.bot
|
676
685
|
k_ty = k_ty.screen_name(scratch)
|
677
686
|
v_ty = v_ty.screen_name(scratch)
|
678
687
|
"Hash[#{ k_ty }, #{ v_ty }]"
|