typeprof 0.21.11 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) 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 +180 -0
  7. data/lib/typeprof/cli.rb +2 -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 +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -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 +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -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 +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. 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