typeprof 0.21.11 → 0.30.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/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 +180 -0
- data/lib/typeprof/cli.rb +2 -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 +251 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +432 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +335 -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 +360 -0
- data/lib/typeprof/core/graph/box.rb +991 -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 +222 -0
- data/lib/typeprof/core/graph.rb +3 -0
- data/lib/typeprof/core/service.rb +522 -0
- data/lib/typeprof/core/type.rb +348 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +32 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +430 -0
- data/lib/typeprof/lsp/server.rb +177 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +61 -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 +48 -35
- 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
@@ -0,0 +1,348 @@
|
|
1
|
+
module TypeProf::Core
|
2
|
+
class Type
|
3
|
+
# This new method does memoize creation of types
|
4
|
+
#: (GlobalEnv, *untyped) -> instance
|
5
|
+
def self.new(genv, *args)
|
6
|
+
genv.type_table[[self] + args] ||= super(genv, *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.strip_parens(s)
|
10
|
+
#s =~ /\A\((.*)\)\z/ ? $1 : s
|
11
|
+
s.start_with?("(") && s.end_with?(")") ? s[1..-2] || raise : s
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.default_param_map(genv, ty)
|
15
|
+
ty = ty.base_type(genv)
|
16
|
+
instance_ty = ty.is_a?(Type::Instance) ? ty : Type::Instance.new(genv, ty.mod, []) # TODO: type params
|
17
|
+
singleton_ty = ty.is_a?(Type::Instance) ? Type::Singleton.new(genv, ty.mod) : ty
|
18
|
+
{
|
19
|
+
"*self": Source.new(ty),
|
20
|
+
"*instance": Source.new(instance_ty),
|
21
|
+
"*class": Source.new(singleton_ty),
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
class Singleton < Type
|
26
|
+
#: (GlobalEnv, ModuleEntity) -> void
|
27
|
+
def initialize(genv, mod)
|
28
|
+
raise unless mod.is_a?(ModuleEntity)
|
29
|
+
# TODO: type_param
|
30
|
+
@mod = mod
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :mod
|
34
|
+
|
35
|
+
def base_type(_)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_match(genv, changes, vtx)
|
40
|
+
vtx.each_type do |other_ty|
|
41
|
+
case other_ty
|
42
|
+
when Singleton
|
43
|
+
other_mod = other_ty.mod
|
44
|
+
if other_mod.module?
|
45
|
+
# TODO: implement
|
46
|
+
else
|
47
|
+
mod = @mod
|
48
|
+
while mod
|
49
|
+
return true if mod == other_mod
|
50
|
+
changes.add_depended_superclass(mod)
|
51
|
+
mod = mod.superclass
|
52
|
+
end
|
53
|
+
end
|
54
|
+
when Instance
|
55
|
+
base_ty = @mod.module? ? genv.mod_type : genv.cls_type
|
56
|
+
return true if base_ty.check_match(genv, changes, Source.new(other_ty))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
def show
|
63
|
+
"singleton(#{ @mod.show_cpath })"
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_instance_type(genv)
|
67
|
+
params = @mod.type_params
|
68
|
+
Instance.new(genv, @mod, params ? params.map { Source.new } : [])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Instance < Type
|
73
|
+
#: (GlobalEnv, ModuleEntity, ::Array[Vertex]) -> void
|
74
|
+
def initialize(genv, mod, args)
|
75
|
+
raise mod.class.to_s unless mod.is_a?(ModuleEntity)
|
76
|
+
@mod = mod
|
77
|
+
@args = args
|
78
|
+
raise unless @args.is_a?(::Array)
|
79
|
+
end
|
80
|
+
|
81
|
+
attr_reader :mod, :args
|
82
|
+
|
83
|
+
def base_type(_)
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_match(genv, changes, vtx)
|
88
|
+
vtx.each_type do |other_ty|
|
89
|
+
case other_ty
|
90
|
+
when Instance
|
91
|
+
ty = self
|
92
|
+
while ty
|
93
|
+
if ty.mod == other_ty.mod
|
94
|
+
args_all_match = true
|
95
|
+
ty.args.zip(other_ty.args) do |arg, other_arg|
|
96
|
+
unless arg.check_match(genv, changes, other_arg)
|
97
|
+
args_all_match = false
|
98
|
+
break
|
99
|
+
end
|
100
|
+
end
|
101
|
+
return true if args_all_match
|
102
|
+
end
|
103
|
+
changes.add_depended_superclass(ty.mod)
|
104
|
+
|
105
|
+
if other_ty.mod.module?
|
106
|
+
return true if check_match_included_modules(genv, changes, ty, other_ty)
|
107
|
+
end
|
108
|
+
|
109
|
+
ty = genv.get_superclass_type(ty, changes, {})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
|
116
|
+
def check_match_included_modules(genv, changes, ty, other_ty)
|
117
|
+
ty.mod.included_modules.each do |inc_decl, inc_mod|
|
118
|
+
if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
|
119
|
+
inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, {}, ty)
|
120
|
+
else
|
121
|
+
type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
|
122
|
+
inc_ty = Type::Instance.new(genv, inc_mod, type_params)
|
123
|
+
end
|
124
|
+
if inc_ty.mod == other_ty.mod
|
125
|
+
args_all_match = true
|
126
|
+
inc_ty.args.zip(other_ty.args) do |arg, other_arg|
|
127
|
+
if other_arg && !arg.check_match(genv, changes, other_arg)
|
128
|
+
args_all_match = false
|
129
|
+
break
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return true if args_all_match
|
133
|
+
end
|
134
|
+
changes.add_depended_superclass(inc_ty.mod)
|
135
|
+
|
136
|
+
return true if check_match_included_modules(genv, changes, inc_ty, other_ty)
|
137
|
+
end
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
|
141
|
+
def show
|
142
|
+
case @mod.cpath
|
143
|
+
when [:NilClass] then "nil"
|
144
|
+
when [:TrueClass] then "true"
|
145
|
+
when [:FalseClass] then "false"
|
146
|
+
else
|
147
|
+
"#{ @mod.show_cpath }#{ @args.empty? ? "" : "[#{ @args.map {|arg| Type.strip_parens(arg.show) }.join(", ") }]" }"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class Array < Type
|
153
|
+
#: (GlobalEnv, ::Array[Vertex], Instance) -> void
|
154
|
+
def initialize(genv, elems, base_type)
|
155
|
+
@elems = elems
|
156
|
+
@base_type = base_type
|
157
|
+
raise unless base_type.is_a?(Instance)
|
158
|
+
end
|
159
|
+
|
160
|
+
attr_reader :elems
|
161
|
+
|
162
|
+
def get_elem(genv, idx = nil)
|
163
|
+
if idx && @elems
|
164
|
+
@elems[idx] || Source.new(genv.nil_type)
|
165
|
+
else
|
166
|
+
@base_type.args.first
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def splat_assign(genv, lefts, rest_elem, rights)
|
171
|
+
edges = []
|
172
|
+
state = :left
|
173
|
+
j = nil
|
174
|
+
@elems.each_with_index do |elem, i|
|
175
|
+
case state
|
176
|
+
when :left
|
177
|
+
if i < lefts.size
|
178
|
+
edges << [elem, lefts[i]]
|
179
|
+
else
|
180
|
+
break unless rest_elem
|
181
|
+
state = :rest
|
182
|
+
redo
|
183
|
+
end
|
184
|
+
when :rest
|
185
|
+
if @elems.size - i > rights.size
|
186
|
+
edges << [elem, rest_elem]
|
187
|
+
else
|
188
|
+
state = :right
|
189
|
+
j = i
|
190
|
+
redo
|
191
|
+
end
|
192
|
+
when :right
|
193
|
+
edges << [elem, rights[i - j]]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
edges
|
197
|
+
end
|
198
|
+
|
199
|
+
def base_type(genv)
|
200
|
+
@base_type
|
201
|
+
end
|
202
|
+
|
203
|
+
def check_match(genv, changes, vtx)
|
204
|
+
vtx.each_type do |other_ty|
|
205
|
+
if other_ty.is_a?(Array)
|
206
|
+
if @elems.size == other_ty.elems.size
|
207
|
+
match = true
|
208
|
+
@elems.zip(other_ty.elems) do |elem, other_elem|
|
209
|
+
unless elem.check_match(genv, changes, other_elem)
|
210
|
+
match = false
|
211
|
+
break
|
212
|
+
end
|
213
|
+
end
|
214
|
+
return true if match
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
@base_type.check_match(genv, changes, vtx)
|
219
|
+
end
|
220
|
+
|
221
|
+
def show
|
222
|
+
if @elems
|
223
|
+
"[#{ @elems.map {|e| Type.strip_parens(e.show) }.join(", ") }]"
|
224
|
+
else
|
225
|
+
"#{ @base_type.mod.show_cpath }[#{ Type.strip_parens(@unified_elem.show) }]"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
class Hash < Type
|
231
|
+
#: (GlobalEnv, ::Array[Vertex], Instance) -> void
|
232
|
+
def initialize(genv, literal_pairs, base_type)
|
233
|
+
@literal_pairs = literal_pairs
|
234
|
+
@base_type = base_type
|
235
|
+
raise unless base_type.is_a?(Instance)
|
236
|
+
end
|
237
|
+
|
238
|
+
def get_key
|
239
|
+
@base_type.args[0]
|
240
|
+
end
|
241
|
+
|
242
|
+
def get_value(key = nil)
|
243
|
+
@literal_pairs[key] || @base_type.args[1]
|
244
|
+
end
|
245
|
+
|
246
|
+
def base_type(genv)
|
247
|
+
@base_type
|
248
|
+
end
|
249
|
+
|
250
|
+
def check_match(genv, changes, vtx)
|
251
|
+
# TODO: implement
|
252
|
+
@base_type.check_match(genv, changes, vtx)
|
253
|
+
end
|
254
|
+
|
255
|
+
def show
|
256
|
+
@base_type.show
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class Proc < Type
|
261
|
+
def initialize(genv, block)
|
262
|
+
@block = block
|
263
|
+
end
|
264
|
+
|
265
|
+
attr_reader :block
|
266
|
+
|
267
|
+
def base_type(genv)
|
268
|
+
genv.proc_type
|
269
|
+
end
|
270
|
+
|
271
|
+
def check_match(genv, changes, vtx)
|
272
|
+
genv.proc_type.check_match(genv, changes, vtx)
|
273
|
+
end
|
274
|
+
|
275
|
+
def show
|
276
|
+
"<Proc>"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
class Symbol < Type
|
281
|
+
#: (GlobalEnv, ::Symbol) -> void
|
282
|
+
def initialize(genv, sym)
|
283
|
+
@sym = sym
|
284
|
+
end
|
285
|
+
|
286
|
+
attr_reader :sym
|
287
|
+
|
288
|
+
def base_type(genv)
|
289
|
+
genv.symbol_type
|
290
|
+
end
|
291
|
+
|
292
|
+
def check_match(genv, changes, vtx)
|
293
|
+
vtx.each_type do |other_ty|
|
294
|
+
case other_ty
|
295
|
+
when Symbol
|
296
|
+
return true if @sym == other_ty.sym
|
297
|
+
when Instance
|
298
|
+
return true if genv.symbol_type.check_match(genv, changes, Source.new(other_ty))
|
299
|
+
end
|
300
|
+
end
|
301
|
+
return false
|
302
|
+
end
|
303
|
+
|
304
|
+
def show
|
305
|
+
@sym.inspect
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
class Bot < Type
|
310
|
+
def initialize(genv)
|
311
|
+
end
|
312
|
+
|
313
|
+
def base_type(genv)
|
314
|
+
genv.obj_type
|
315
|
+
end
|
316
|
+
|
317
|
+
def check_match(genv, changes, vtx)
|
318
|
+
return true
|
319
|
+
end
|
320
|
+
|
321
|
+
def show
|
322
|
+
"bot"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class Var < Type
|
327
|
+
#: (GlobalEnv, ::Symbol, Vertex) -> void
|
328
|
+
def initialize(genv, name, vtx)
|
329
|
+
@name = name
|
330
|
+
@vtx = vtx
|
331
|
+
end
|
332
|
+
|
333
|
+
attr_reader :name, :vtx
|
334
|
+
|
335
|
+
def base_type(genv)
|
336
|
+
genv.obj_type # Is this ok?
|
337
|
+
end
|
338
|
+
|
339
|
+
def check_match(genv, changes, vtx)
|
340
|
+
true # should implement a better support...
|
341
|
+
end
|
342
|
+
|
343
|
+
def show
|
344
|
+
"var[#{ @name }]"
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module TypeProf::Core
|
2
|
+
class Set
|
3
|
+
def self.[](*elems)
|
4
|
+
h = Hash.new(false)
|
5
|
+
elems.each {|elem| h[elem] = true }
|
6
|
+
new(h)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(hash)
|
10
|
+
@hash = hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def internal_hash = @hash
|
14
|
+
|
15
|
+
def dup
|
16
|
+
Set.new(@hash.dup)
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(elem)
|
20
|
+
raise if @hash.include?(elem)
|
21
|
+
@hash[elem] = true
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def include?(elem)
|
26
|
+
@hash[elem]
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge(set)
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
|
33
|
+
def each(&blk)
|
34
|
+
@hash.each_key(&blk)
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty?
|
38
|
+
@hash.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(elem)
|
42
|
+
raise unless @hash.include?(elem)
|
43
|
+
@hash.delete(elem)
|
44
|
+
end
|
45
|
+
|
46
|
+
def clear
|
47
|
+
@hash.clear
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_a
|
51
|
+
@hash.keys
|
52
|
+
end
|
53
|
+
|
54
|
+
def size
|
55
|
+
@hash.size
|
56
|
+
end
|
57
|
+
|
58
|
+
def -(other)
|
59
|
+
h = @hash.dup
|
60
|
+
other.each do |elem|
|
61
|
+
h.delete(elem)
|
62
|
+
end
|
63
|
+
Set.new(h)
|
64
|
+
end
|
65
|
+
|
66
|
+
def pretty_print(q)
|
67
|
+
q.text "Set["
|
68
|
+
q.group do
|
69
|
+
q.nest(1) do
|
70
|
+
@hash.each_key do |elem|
|
71
|
+
q.breakable ""
|
72
|
+
q.pp elem
|
73
|
+
q.text ","
|
74
|
+
end
|
75
|
+
end
|
76
|
+
q.breakable ""
|
77
|
+
end
|
78
|
+
q.text "]"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "rbs"
|
2
|
+
require "prism"
|
3
|
+
require_relative "core/util"
|
4
|
+
require_relative "core/ast"
|
5
|
+
require_relative "core/ast/base"
|
6
|
+
require_relative "core/ast/module"
|
7
|
+
require_relative "core/ast/method"
|
8
|
+
require_relative "core/ast/call"
|
9
|
+
require_relative "core/ast/control"
|
10
|
+
require_relative "core/ast/const"
|
11
|
+
require_relative "core/ast/variable"
|
12
|
+
require_relative "core/ast/value"
|
13
|
+
require_relative "core/ast/misc"
|
14
|
+
require_relative "core/ast/meta"
|
15
|
+
require_relative "core/ast/pattern"
|
16
|
+
require_relative "core/ast/sig_decl"
|
17
|
+
require_relative "core/ast/sig_type"
|
18
|
+
require_relative "core/type"
|
19
|
+
require_relative "core/env"
|
20
|
+
require_relative "core/env/method_entity"
|
21
|
+
require_relative "core/env/module_entity"
|
22
|
+
require_relative "core/env/type_alias_entity"
|
23
|
+
require_relative "core/env/value_entity"
|
24
|
+
require_relative "core/env/method"
|
25
|
+
require_relative "core/env/static_read"
|
26
|
+
require_relative "core/graph"
|
27
|
+
require_relative "core/graph/change_set"
|
28
|
+
require_relative "core/graph/vertex"
|
29
|
+
require_relative "core/graph/filter"
|
30
|
+
require_relative "core/graph/box"
|
31
|
+
require_relative "core/builtin"
|
32
|
+
require_relative "core/service"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module TypeProf
|
2
|
+
class Diagnostic
|
3
|
+
def initialize(node, meth, msg)
|
4
|
+
@node = node
|
5
|
+
@meth = meth
|
6
|
+
@msg = msg
|
7
|
+
@severity = :error # TODO: keyword argument
|
8
|
+
@tags = nil # TODO: keyword argument
|
9
|
+
end
|
10
|
+
|
11
|
+
def reuse(new_node)
|
12
|
+
@node = new_node
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :msg, :severity
|
16
|
+
|
17
|
+
def code_range
|
18
|
+
@node.send(@meth)
|
19
|
+
end
|
20
|
+
|
21
|
+
SEVERITY = { error: 1, warning: 2, info: 3, hint: 4 }
|
22
|
+
TAG = { unnecessary: 1, deprecated: 2 }
|
23
|
+
|
24
|
+
def to_lsp
|
25
|
+
json = {
|
26
|
+
range: code_range.to_lsp,
|
27
|
+
source: "TypeProf",
|
28
|
+
message: @msg,
|
29
|
+
}
|
30
|
+
json[:severity] = SEVERITY[@severity] if @severity
|
31
|
+
json[:tags] = @tags.map {|tag| TAG[tag] } if @tags
|
32
|
+
json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|