typeprof 0.21.11 → 0.30.1

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +178 -0
  7. data/lib/typeprof/cli.rb +3 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +259 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +433 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +339 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +366 -0
  31. data/lib/typeprof/core/graph/box.rb +998 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +225 -0
  35. data/lib/typeprof/core/service.rb +514 -0
  36. data/lib/typeprof/core/type.rb +352 -0
  37. data/lib/typeprof/core/util.rb +81 -0
  38. data/lib/typeprof/core.rb +31 -0
  39. data/lib/typeprof/diagnostic.rb +35 -0
  40. data/lib/typeprof/lsp/messages.rb +415 -0
  41. data/lib/typeprof/lsp/server.rb +203 -0
  42. data/lib/typeprof/lsp/text.rb +69 -0
  43. data/lib/typeprof/lsp/util.rb +51 -0
  44. data/lib/typeprof/lsp.rb +4 -907
  45. data/lib/typeprof/version.rb +1 -1
  46. data/lib/typeprof.rb +4 -18
  47. data/typeprof.gemspec +5 -7
  48. metadata +47 -33
  49. data/.github/dependabot.yml +0 -6
  50. data/.github/workflows/main.yml +0 -39
  51. data/.gitignore +0 -9
  52. data/Gemfile +0 -17
  53. data/Gemfile.lock +0 -41
  54. data/Rakefile +0 -10
  55. data/exe/typeprof +0 -10
  56. data/lib/typeprof/analyzer.rb +0 -2598
  57. data/lib/typeprof/arguments.rb +0 -414
  58. data/lib/typeprof/block.rb +0 -176
  59. data/lib/typeprof/builtin.rb +0 -893
  60. data/lib/typeprof/code-range.rb +0 -177
  61. data/lib/typeprof/config.rb +0 -158
  62. data/lib/typeprof/container-type.rb +0 -912
  63. data/lib/typeprof/export.rb +0 -589
  64. data/lib/typeprof/import.rb +0 -852
  65. data/lib/typeprof/insns-def.rb +0 -65
  66. data/lib/typeprof/iseq.rb +0 -864
  67. data/lib/typeprof/method.rb +0 -355
  68. data/lib/typeprof/type.rb +0 -1140
  69. data/lib/typeprof/utils.rb +0 -212
  70. data/tools/coverage.rb +0 -14
  71. data/tools/setup-insns-def.rb +0 -30
  72. data/typeprof-lsp +0 -3
@@ -1,355 +0,0 @@
1
- module TypeProf
2
- class MethodDef
3
- attr_accessor :pub_meth
4
-
5
- include Utils::StructuralEquality
6
- end
7
-
8
- class ISeqMethodDef < MethodDef
9
- def initialize(iseq, cref, outer_ep, pub_meth)
10
- @iseq = iseq
11
- raise if iseq.nil?
12
- @cref = cref
13
- @outer_ep = outer_ep
14
- @pub_meth = pub_meth
15
- end
16
-
17
- attr_reader :iseq
18
-
19
- def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
20
- recv = recv.base_type while recv.respond_to?(:base_type)
21
- recv = scratch.globalize_type(recv, caller_env, caller_ep)
22
- aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
23
-
24
- locals = [Type.nil] * @iseq.locals.size
25
-
26
- blk_ty, start_pcs = aargs.setup_formal_arguments(:method, locals, @iseq.fargs_format)
27
- if blk_ty.is_a?(String)
28
- scratch.error(caller_ep, blk_ty)
29
- ctn[Type.any, caller_ep, caller_env]
30
- return
31
- end
32
-
33
- nctx = Context.new(@iseq, @cref, mid)
34
- callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
35
- nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
36
- alloc_site = AllocationSite.new(callee_ep)
37
- locals.each_with_index do |ty, i|
38
- alloc_site2 = alloc_site.add_id(i)
39
- # nenv is top-level, so it is okay to call Type#localize directly
40
- nenv, ty = ty.localize(nenv, alloc_site2, Config.current.options[:type_depth_limit])
41
- nenv = nenv.local_update(i, ty)
42
- end
43
-
44
- start_pcs.each do |start_pc|
45
- scratch.merge_env(ExecutionPoint.new(nctx, start_pc, @outer_ep), nenv)
46
- end
47
-
48
- scratch.add_iseq_method_call!(self, nctx)
49
- scratch.add_callsite!(nctx, caller_ep, caller_env, &ctn)
50
- end
51
-
52
- def do_check_send(msig, recv, mid, ep, scratch)
53
- klass, singleton = recv.method_dispatch_info
54
- cur_subst = {}
55
- direct_method = true
56
- scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
57
- direct_method &&= direct
58
- cur_subst = Type.merge_substitution(cur_subst, subst)
59
- end
60
-
61
- lead_num = @iseq.fargs_format[:lead_num] || 0
62
- post_num = @iseq.fargs_format[:post_num] || 0
63
- rest_start = @iseq.fargs_format[:rest_start]
64
- opt = @iseq.fargs_format[:opt] || [0]
65
-
66
- # TODO: check keywords
67
- if rest_start
68
- # almost ok
69
- else
70
- if msig.rest_ty
71
- scratch.error(ep, "RBS says that a rest argument is accepted, but the method definition does not accept one")
72
- return
73
- end
74
- if msig.lead_tys.size + msig.post_tys.size < lead_num + post_num
75
- scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at least %d arguments" % [msig.lead_tys.size + msig.post_tys.size, lead_num + post_num])
76
- return
77
- end
78
- if msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size > lead_num + opt.size - 1 + post_num
79
- scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at most %d arguments" % [msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size, lead_num + opt.size - 1 + post_num])
80
- return
81
- end
82
- end
83
-
84
- lead_num = @iseq.fargs_format[:lead_num] || 0
85
- post_start = @iseq.fargs_format[:post_start]
86
- kw_start = @iseq.fargs_format[:kwbits]
87
- keyword = @iseq.fargs_format[:keyword]
88
- kw_start -= keyword.size if kw_start
89
- kw_rest = @iseq.fargs_format[:kwrest]
90
- block_start = @iseq.fargs_format[:block_start]
91
-
92
- # XXX: need to check .rbs msig and .rb fargs
93
-
94
- ctx = Context.new(@iseq, @cref, mid)
95
- callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
96
-
97
- locals = [Type.nil] * @iseq.locals.size
98
- nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
99
- alloc_site = AllocationSite.new(callee_ep)
100
- idx = 0
101
- msig.lead_tys.each_with_index do |ty, i|
102
- alloc_site2 = alloc_site.add_id(idx += 1)
103
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
104
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
105
- nenv = nenv.local_update(i, ty)
106
- end
107
- if msig.opt_tys
108
- msig.opt_tys.each_with_index do |ty, i|
109
- alloc_site2 = alloc_site.add_id(idx += 1)
110
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
111
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
112
- nenv = nenv.local_update(lead_num + i, ty)
113
- end
114
- end
115
- if msig.rest_ty
116
- alloc_site2 = alloc_site.add_id(idx += 1)
117
- ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
118
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
119
- nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
120
- # TODO: handle a case where rest_start is not found
121
- nenv = nenv.local_update(rest_start, rest_ty)
122
- elsif rest_start
123
- alloc_site2 = alloc_site.add_id(idx += 1)
124
- ty = Type::Array.new(Type::Array::Elements.new([], Type.any), Type::Instance.new(Type::Builtin[:ary]))
125
- nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
126
- nenv = nenv.local_update(rest_start, rest_ty)
127
- end
128
- if msig.post_tys
129
- msig.post_tys.each_with_index do |ty, i|
130
- alloc_site2 = alloc_site.add_id(idx += 1)
131
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
132
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
133
- nenv = nenv.local_update(post_start + i, ty)
134
- end
135
- end
136
- if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
137
- msig.kw_tys.each do |_, key, ty|
138
- i = keyword.index {|callee_key,| callee_key == key }
139
- unless i
140
- # warn
141
- next
142
- end
143
- alloc_site2 = alloc_site.add_id(key)
144
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
145
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
146
- nenv = nenv.local_update(kw_start + i, ty)
147
- end
148
- end
149
- if msig.kw_rest_ty
150
- ty = msig.kw_rest_ty
151
- alloc_site2 = alloc_site.add_id(:**)
152
- ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
153
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
154
- nenv = nenv.local_update(kw_rest, ty)
155
- elsif kw_rest
156
- alloc_site2 = alloc_site.add_id(:**)
157
- ty = Type.gen_hash {}
158
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
159
- nenv = nenv.local_update(kw_rest, ty)
160
- end
161
- nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
162
-
163
- opt.each do |start_pc|
164
- scratch.merge_env(callee_ep.jump(start_pc), nenv)
165
- end
166
- scratch.add_executed_iseq(@iseq)
167
-
168
- ctx
169
- end
170
- end
171
-
172
- class AliasMethodDef < MethodDef
173
- def initialize(orig_mid, mdef, def_ep)
174
- @orig_mid = orig_mid
175
- @mdef = mdef
176
- @pub_meth = mdef.pub_meth
177
- @def_ep = def_ep
178
- end
179
-
180
- attr_reader :orig_mid, :mdef, :def_ep
181
-
182
- def do_send(recv, _mid, aargs, caller_ep, caller_env, scratch, &ctn)
183
- @mdef.do_send(recv, @orig_mid, aargs, caller_ep, caller_env, scratch, &ctn)
184
- end
185
-
186
- def do_check_send(msig, recv, mid, ep, scratch)
187
- @mdef.do_check_send(msig, recv, mid, ep, scratch)
188
- end
189
- end
190
-
191
- class AttrMethodDef < MethodDef
192
- def initialize(ivar, kind, pub_meth)
193
- @ivar = ivar
194
- @kind = kind # :reader | :writer
195
- @pub_meth = pub_meth
196
- end
197
-
198
- attr_reader :ivar, :kind
199
-
200
- def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
201
- case @kind
202
- when :reader
203
- if aargs.lead_tys.size == 0
204
- scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
205
- ctn[ty, caller_ep, caller_env]
206
- end
207
- else
208
- ctn[Type.any, caller_ep, caller_env]
209
- end
210
- when :writer
211
- if aargs.lead_tys.size == 1
212
- ty = aargs.lead_tys[0]
213
- scratch.set_instance_variable(recv, @ivar, ty, caller_ep, caller_env)
214
- ctn[ty, caller_ep, caller_env]
215
- else
216
- ctn[Type.any, caller_ep, caller_env]
217
- end
218
- end
219
- end
220
- end
221
-
222
- class ExecutedAttrMethodDef < AttrMethodDef
223
- def initialize(ivar, kind, pub_meth, def_ep)
224
- super(ivar, kind, pub_meth)
225
- @def_ep = def_ep
226
- end
227
-
228
- attr_reader :def_ep
229
- end
230
-
231
- class TypedAttrMethodDef < AttrMethodDef
232
- def initialize(ivar, kind, pub_meth, rbs_source)
233
- @rbs_source = rbs_source
234
-
235
- super(ivar, kind, pub_meth)
236
- end
237
-
238
- attr_reader :rbs_source
239
- end
240
-
241
- class TypedMethodDef < MethodDef
242
- def initialize(sig_rets, rbs_source, pub_meth) # sig_rets: Array<[MethodSignature, (return)Type]>
243
- @sig_rets = sig_rets
244
- @rbs_source = rbs_source
245
- @pub_meth = pub_meth
246
- @iseq = nil
247
- end
248
-
249
- attr_reader :rbs_source, :iseq
250
-
251
- def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
252
- recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
253
-
254
- klass, singleton = recv_orig.method_dispatch_info
255
- cur_subst = {}
256
- direct_method = true
257
- scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
258
- direct_method &&= direct
259
- cur_subst = Type.merge_substitution(cur_subst, subst)
260
- end
261
-
262
- found = false
263
- aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
264
- @sig_rets.each do |msig, ret_ty|
265
- ncaller_env = caller_env
266
- #pp [mid, aargs, msig]
267
- # XXX: support self type in msig
268
- subst = aargs.consistent_with_method_signature?(msig)
269
- next unless subst
270
-
271
- if direct_method && recv_orig.is_a?(Type::Local)
272
- ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
273
- end
274
-
275
- subst = Type.merge_substitution(subst, cur_subst)
276
- # need to check self tyvar?
277
- subst[Type::Var.new(:self)] = recv
278
-
279
- found = true
280
- if aargs.blk_ty.is_a?(Type::Proc)
281
- #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
282
- dummy_ctx = TypedContext.new(caller_ep, mid)
283
- dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
284
- s_recv = recv
285
- s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
286
- dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
287
- if msig.blk_ty.is_a?(Type::Proc)
288
- scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
289
- bsig = msig.blk_ty.block_body.msig
290
- alloc_site = AllocationSite.new(caller_ep).add_id(self)
291
- nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
292
- ty = ty.substitute(subst, Config.current.options[:type_depth_limit]).remove_type_vars
293
- dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
294
- ty
295
- end
296
- 0.upto(bsig.opt_tys.size) do |n|
297
- naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
298
- scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
299
- subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
300
- if subst2
301
- subst2 = Type.merge_substitution(subst, subst2)
302
- if direct_method && recv_orig.is_a?(Type::Local)
303
- ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
304
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
305
- end
306
- ret_ty2 = ret_ty.substitute(subst2, Config.current.options[:type_depth_limit]).remove_type_vars
307
- else
308
- ret_ty2 = Type.any
309
- end
310
- # XXX: check the return type from the block
311
- # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
312
- scratch.add_return_value!(dummy_ctx, ret_ty2)
313
- end
314
- # scratch.add_return_value!(dummy_ctx, ret_ty) ?
315
- # This makes `def foo; 1.times { return "str" }; end` return Integer|String
316
- end
317
- else
318
- # XXX: a block is passed to a method that does not accept block.
319
- # Should we call the passed block with any arguments?
320
- ret_ty = ret_ty.remove_type_vars
321
- ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot
322
- end
323
- else
324
- ret_ty = ret_ty.substitute(subst, Config.current.options[:type_depth_limit])
325
- ret_ty = ret_ty.remove_type_vars
326
- ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot
327
- end
328
- end
329
-
330
- unless found
331
- scratch.error(caller_ep, "failed to resolve overload: #{ recv.screen_name(scratch) }##{ mid }")
332
- ctn[Type.any, caller_ep, caller_env]
333
- end
334
- end
335
-
336
- def do_match_iseq_mdef(iseq_mdef, recv, mid, env, ep, scratch)
337
- recv = scratch.globalize_type(recv, env, ep)
338
- @sig_rets.each do |msig, _ret_ty|
339
- iseq_mdef.do_check_send(msig, recv, mid, ep, scratch)
340
- end
341
- @iseq ||= iseq_mdef.iseq
342
- end
343
- end
344
-
345
- class CustomMethodDef < MethodDef
346
- def initialize(impl, pub_meth)
347
- @impl = impl
348
- @pub_meth = pub_meth
349
- end
350
-
351
- def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
352
- @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
353
- end
354
- end
355
- end