typeprof 0.21.11 → 0.30.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -31
- data/bin/typeprof +5 -0
- data/doc/doc.ja.md +134 -0
- data/doc/doc.md +136 -0
- data/lib/typeprof/cli/cli.rb +178 -0
- data/lib/typeprof/cli.rb +3 -133
- data/lib/typeprof/code_range.rb +112 -0
- data/lib/typeprof/core/ast/base.rb +263 -0
- data/lib/typeprof/core/ast/call.rb +259 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +433 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +339 -0
- data/lib/typeprof/core/ast/misc.rb +263 -0
- data/lib/typeprof/core/ast/module.rb +123 -0
- data/lib/typeprof/core/ast/pattern.rb +140 -0
- data/lib/typeprof/core/ast/sig_decl.rb +471 -0
- data/lib/typeprof/core/ast/sig_type.rb +663 -0
- data/lib/typeprof/core/ast/value.rb +319 -0
- data/lib/typeprof/core/ast/variable.rb +315 -0
- data/lib/typeprof/core/ast.rb +472 -0
- data/lib/typeprof/core/builtin.rb +146 -0
- data/lib/typeprof/core/env/method.rb +137 -0
- data/lib/typeprof/core/env/method_entity.rb +55 -0
- data/lib/typeprof/core/env/module_entity.rb +408 -0
- data/lib/typeprof/core/env/static_read.rb +155 -0
- data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
- data/lib/typeprof/core/env/value_entity.rb +32 -0
- data/lib/typeprof/core/env.rb +366 -0
- data/lib/typeprof/core/graph/box.rb +998 -0
- data/lib/typeprof/core/graph/change_set.rb +224 -0
- data/lib/typeprof/core/graph/filter.rb +155 -0
- data/lib/typeprof/core/graph/vertex.rb +225 -0
- data/lib/typeprof/core/service.rb +514 -0
- data/lib/typeprof/core/type.rb +352 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +31 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +415 -0
- data/lib/typeprof/lsp/server.rb +203 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +51 -0
- data/lib/typeprof/lsp.rb +4 -907
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +4 -18
- data/typeprof.gemspec +5 -7
- metadata +47 -33
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/main.yml +0 -39
- data/.gitignore +0 -9
- data/Gemfile +0 -17
- data/Gemfile.lock +0 -41
- data/Rakefile +0 -10
- data/exe/typeprof +0 -10
- data/lib/typeprof/analyzer.rb +0 -2598
- data/lib/typeprof/arguments.rb +0 -414
- data/lib/typeprof/block.rb +0 -176
- data/lib/typeprof/builtin.rb +0 -893
- data/lib/typeprof/code-range.rb +0 -177
- data/lib/typeprof/config.rb +0 -158
- data/lib/typeprof/container-type.rb +0 -912
- data/lib/typeprof/export.rb +0 -589
- data/lib/typeprof/import.rb +0 -852
- data/lib/typeprof/insns-def.rb +0 -65
- data/lib/typeprof/iseq.rb +0 -864
- data/lib/typeprof/method.rb +0 -355
- data/lib/typeprof/type.rb +0 -1140
- data/lib/typeprof/utils.rb +0 -212
- data/tools/coverage.rb +0 -14
- data/tools/setup-insns-def.rb +0 -30
- data/typeprof-lsp +0 -3
data/lib/typeprof/code-range.rb
DELETED
@@ -1,177 +0,0 @@
|
|
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
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
|
3
|
-
module TypeProf
|
4
|
-
ConfigData = Struct.new(
|
5
|
-
:rb_files,
|
6
|
-
:rbs_files,
|
7
|
-
:output,
|
8
|
-
:gem_rbs_features,
|
9
|
-
:collection_path,
|
10
|
-
:verbose,
|
11
|
-
:dir_filter,
|
12
|
-
:max_iter,
|
13
|
-
:max_sec,
|
14
|
-
:options,
|
15
|
-
:lsp_options,
|
16
|
-
:lsp,
|
17
|
-
keyword_init: true
|
18
|
-
)
|
19
|
-
|
20
|
-
class TypeProfError < StandardError
|
21
|
-
def report(output)
|
22
|
-
output.puts "# Analysis Error"
|
23
|
-
output.puts message
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class ConfigData
|
28
|
-
def initialize(**opt)
|
29
|
-
opt[:output] ||= $stdout
|
30
|
-
opt[:gem_rbs_features] ||= []
|
31
|
-
opt[:dir_filter] ||= DEFAULT_DIR_FILTER
|
32
|
-
opt[:verbose] ||= 0
|
33
|
-
opt[:options] ||= {}
|
34
|
-
opt[:options] = {
|
35
|
-
exclude_untyped: false,
|
36
|
-
show_typeprof_version: true,
|
37
|
-
show_indicator: true,
|
38
|
-
show_untyped: false,
|
39
|
-
show_errors: false,
|
40
|
-
show_parameter_names: true,
|
41
|
-
show_source_locations: false,
|
42
|
-
stub_execution: true,
|
43
|
-
type_depth_limit: 5,
|
44
|
-
union_width_limit: 10,
|
45
|
-
stackprof: nil,
|
46
|
-
}.merge(opt[:options])
|
47
|
-
opt[:lsp_options] = {
|
48
|
-
port: 0,
|
49
|
-
stdio: false,
|
50
|
-
}.merge(opt[:lsp_options] || {})
|
51
|
-
super(**opt)
|
52
|
-
end
|
53
|
-
|
54
|
-
def check_dir_filter(path)
|
55
|
-
dir_filter.reverse_each do |cond, dir|
|
56
|
-
return cond unless dir
|
57
|
-
return cond if path.start_with?(dir)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
DEFAULT_DIR_FILTER = [
|
62
|
-
[:include],
|
63
|
-
[:exclude, RbConfig::CONFIG["prefix"]],
|
64
|
-
[:exclude, Gem.dir],
|
65
|
-
[:exclude, Gem.user_dir],
|
66
|
-
]
|
67
|
-
end
|
68
|
-
|
69
|
-
module Config
|
70
|
-
def self.current
|
71
|
-
Thread.current[:typeprof_config]
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.set_current(config)
|
75
|
-
Thread.current[:typeprof_config] = config
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.analyze(config, cancel_token = nil)
|
80
|
-
# Deploy the config to the TypeProf::Config (Note: This is thread local)
|
81
|
-
Config.set_current(config)
|
82
|
-
|
83
|
-
if Config.current.options[:stackprof]
|
84
|
-
require "stackprof"
|
85
|
-
out = "typeprof-stackprof-#{ Config.current.options[:stackprof] }.dump"
|
86
|
-
StackProf.start(mode: Config.current.options[:stackprof], out: out, raw: true)
|
87
|
-
end
|
88
|
-
|
89
|
-
scratch = Scratch.new
|
90
|
-
Builtin.setup_initial_global_env(scratch)
|
91
|
-
|
92
|
-
Config.current.gem_rbs_features.each do |feature|
|
93
|
-
Import.import_library(scratch, feature)
|
94
|
-
end
|
95
|
-
|
96
|
-
rbs_files = []
|
97
|
-
rbs_codes = []
|
98
|
-
Config.current.rbs_files.each do |rbs|
|
99
|
-
if rbs.is_a?(Array) # [String name, String content]
|
100
|
-
rbs_codes << rbs
|
101
|
-
else
|
102
|
-
rbs_files << rbs
|
103
|
-
end
|
104
|
-
end
|
105
|
-
Import.import_rbs_files(scratch, rbs_files)
|
106
|
-
rbs_codes.each do |name, content|
|
107
|
-
Import.import_rbs_code(scratch, name, content)
|
108
|
-
end
|
109
|
-
|
110
|
-
def_code_range_table = nil
|
111
|
-
caller_code_range_table = nil
|
112
|
-
Config.current.rb_files.each do |rb|
|
113
|
-
if rb.is_a?(Array) # [String name, String content]
|
114
|
-
iseq, def_tbl, caller_tbl = ISeq.compile_str(*rb.reverse)
|
115
|
-
def_code_range_table ||= def_tbl
|
116
|
-
caller_code_range_table ||= caller_tbl
|
117
|
-
else
|
118
|
-
iseq = rb
|
119
|
-
end
|
120
|
-
scratch.add_entrypoint(iseq)
|
121
|
-
end
|
122
|
-
|
123
|
-
result = scratch.type_profile(cancel_token)
|
124
|
-
|
125
|
-
if Config.current.options[:lsp]
|
126
|
-
return scratch.report_lsp, def_code_range_table, caller_code_range_table
|
127
|
-
end
|
128
|
-
|
129
|
-
if Config.current.output.respond_to?(:write)
|
130
|
-
scratch.report(result, Config.current.output)
|
131
|
-
else
|
132
|
-
open(Config.current.output, "w") do |output|
|
133
|
-
scratch.report(result, output)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
rescue TypeProfError => exc
|
138
|
-
exc.report(Config.current.output)
|
139
|
-
|
140
|
-
return nil
|
141
|
-
ensure
|
142
|
-
if Config.current.options[:stackprof] && defined?(StackProf)
|
143
|
-
StackProf.stop
|
144
|
-
StackProf.results
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def self.starting_state(iseq)
|
149
|
-
cref = CRef.new(:bottom, Type::Builtin[:obj], false) # object
|
150
|
-
recv = Type::Instance.new(Type::Builtin[:obj])
|
151
|
-
ctx = Context.new(iseq, cref, nil)
|
152
|
-
ep = ExecutionPoint.new(ctx, 0, nil)
|
153
|
-
locals = [Type.nil] * iseq.locals.size
|
154
|
-
env = Env.new(StaticEnv.new(recv, Type.nil, false, false), locals, [], Utils::HashWrapper.new({}))
|
155
|
-
|
156
|
-
return ep, env
|
157
|
-
end
|
158
|
-
end
|