typeprof 0.14.1 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -5
- data/lib/typeprof/analyzer.rb +121 -73
- data/lib/typeprof/builtin.rb +14 -12
- data/lib/typeprof/cli.rb +1 -0
- data/lib/typeprof/config.rb +2 -1
- data/lib/typeprof/export.rb +1 -0
- data/lib/typeprof/import.rb +55 -21
- data/lib/typeprof/type.rb +96 -46
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias2.rb +1 -1
- data/smoke/array3.rb +1 -1
- data/smoke/attr-module.rb +1 -4
- data/smoke/attr-vis.rb +1 -1
- data/smoke/attr.rb +1 -1
- data/smoke/huge_union.rb +86 -0
- data/smoke/initialize.rb +1 -1
- data/smoke/ivar2.rb +1 -1
- data/smoke/ivar3.rb +1 -1
- data/smoke/kwrest.rb +2 -2
- data/smoke/kwrest.rbs +1 -1
- data/smoke/method_missing.rb +1 -1
- data/smoke/noname.rb +9 -0
- data/smoke/proc6.rb +13 -0
- data/smoke/proc7.rb +32 -0
- data/smoke/rbs-tyvar4.rb +1 -1
- data/smoke/require1.rb +13 -0
- data/smoke/require2.rb +13 -0
- data/smoke/struct5.rb +1 -1
- data/smoke/struct6.rb +1 -1
- data/smoke/struct7.rb +1 -1
- data/smoke/super3.rb +1 -1
- data/smoke/symbol-proc-attr.rb +1 -1
- data/smoke/symbol-proc-attr2.rb +1 -1
- data/typeprof.gemspec +1 -1
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcefd3a4da176820246ad53757286aa1f7f8b2d21a6d1300763c91ba252e95ca
|
4
|
+
data.tar.gz: 1bf7429a4cf7d59e1ab4ca10f5f065a22b85adbbda922c67060d0ede64aab60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff14f14aa923ca807db9d7f1bc7f537c46e735bd194a0b59758dfdba0e04c04175ca0505fe6c00f739fec7933eeeab5010646891f56e14d5245f5b8613dd7d3b
|
7
|
+
data.tar.gz: 73a05bece353a7b4dbefba9f16e723fb088795e9f029b143721b03543e53ae19a8adb9908b3de41c839fbfb10a8d34c76ed0fa4f1b072801d7334233be63b1c9
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
5
|
-
rbs (>= 1.
|
4
|
+
typeprof (0.15.0)
|
5
|
+
rbs (>= 1.3.1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
docile (1.4.0)
|
12
12
|
power_assert (2.0.0)
|
13
13
|
rake (13.0.1)
|
14
|
-
rbs (1.
|
14
|
+
rbs (1.3.1)
|
15
15
|
simplecov (0.21.2)
|
16
16
|
docile (~> 1.1)
|
17
17
|
simplecov-html (~> 0.11)
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
simplecov-html (0.12.3)
|
20
20
|
simplecov_json_formatter (0.1.3)
|
21
21
|
stackprof (0.2.17)
|
22
|
-
test-unit (3.4.
|
22
|
+
test-unit (3.4.2)
|
23
23
|
power_assert
|
24
24
|
|
25
25
|
PLATFORMS
|
@@ -36,4 +36,4 @@ DEPENDENCIES
|
|
36
36
|
typeprof!
|
37
37
|
|
38
38
|
BUNDLED WITH
|
39
|
-
2.
|
39
|
+
2.2.15
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -277,20 +277,22 @@ module TypeProf
|
|
277
277
|
@pending_execution = {}
|
278
278
|
@executed_iseqs = Utils::MutableSet.new
|
279
279
|
|
280
|
-
@
|
280
|
+
@loaded_files = {}
|
281
281
|
|
282
282
|
@rbs_reader = RBSReader.new
|
283
283
|
|
284
284
|
@terminated = false
|
285
285
|
|
286
286
|
@anonymous_struct_gen_id = 0
|
287
|
+
|
288
|
+
@types_being_shown = []
|
287
289
|
end
|
288
290
|
|
289
291
|
def add_entrypoint(iseq)
|
290
292
|
@entrypoints << iseq
|
291
293
|
end
|
292
294
|
|
293
|
-
attr_reader :return_envs, :
|
295
|
+
attr_reader :return_envs, :loaded_files, :rbs_reader
|
294
296
|
|
295
297
|
def get_env(ep)
|
296
298
|
@ep2env[ep]
|
@@ -329,9 +331,10 @@ module TypeProf
|
|
329
331
|
@cvars = VarTable.new
|
330
332
|
@absolute_path = absolute_path
|
331
333
|
@namespace = nil
|
334
|
+
@subclasses = []
|
332
335
|
end
|
333
336
|
|
334
|
-
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
|
337
|
+
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path, :subclasses
|
335
338
|
attr_accessor :name, :klass_obj
|
336
339
|
|
337
340
|
def mix_module(kind, mod, type_args, singleton, absolute_path)
|
@@ -445,6 +448,7 @@ module TypeProf
|
|
445
448
|
idx = @class_defs.size
|
446
449
|
if superclass
|
447
450
|
@class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
|
451
|
+
@class_defs[superclass.idx].subclasses << idx unless superclass == :__root__
|
448
452
|
klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
|
449
453
|
@class_defs[idx].klass_obj = klass
|
450
454
|
cbase ||= klass # for bootstrap
|
@@ -471,6 +475,7 @@ module TypeProf
|
|
471
475
|
superclass = Type::Builtin[:struct]
|
472
476
|
name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
|
473
477
|
@class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
|
478
|
+
#@class_defs[superclass.idx].subclasses << idx # needed?
|
474
479
|
klass = Type::Class.new(:class, idx, [], superclass, name)
|
475
480
|
add_superclass_type_args!(klass, [Type.any])
|
476
481
|
@class_defs[idx].klass_obj = klass
|
@@ -526,6 +531,13 @@ module TypeProf
|
|
526
531
|
end
|
527
532
|
end
|
528
533
|
|
534
|
+
def traverse_subclasses(klass, &blk)
|
535
|
+
@class_defs[klass.idx].subclasses.each do |subclass|
|
536
|
+
yield @class_defs[subclass]
|
537
|
+
traverse_subclasses(@class_defs[subclass].klass_obj, &blk)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
529
541
|
def search_method(klass, singleton, mid, &blk)
|
530
542
|
# XXX: support method alias correctly
|
531
543
|
klass_orig = klass
|
@@ -545,7 +557,18 @@ module TypeProf
|
|
545
557
|
end
|
546
558
|
end
|
547
559
|
|
548
|
-
def get_method(klass, singleton, mid)
|
560
|
+
def get_method(klass, singleton, include_subclasses, mid)
|
561
|
+
if include_subclasses
|
562
|
+
subclasses_mthds = []
|
563
|
+
traverse_subclasses(klass) do |subclass|
|
564
|
+
subclass.search_method(singleton, mid, {}) do |mthds,|
|
565
|
+
subclasses_mthds.concat(mthds.to_a)
|
566
|
+
end
|
567
|
+
end
|
568
|
+
search_method(klass, singleton, mid) {|mthds,| return subclasses_mthds + mthds.to_a }
|
569
|
+
return subclasses_mthds
|
570
|
+
end
|
571
|
+
|
549
572
|
search_method(klass, singleton, mid) {|mthds,| return mthds }
|
550
573
|
end
|
551
574
|
|
@@ -646,9 +669,10 @@ module TypeProf
|
|
646
669
|
if klass == Type.any
|
647
670
|
self
|
648
671
|
else
|
649
|
-
mdefs = get_method(klass, singleton, orig_mid)
|
672
|
+
mdefs = get_method(klass, singleton, false, orig_mid) # XXX: include_subclass == false??
|
650
673
|
if mdefs
|
651
|
-
|
674
|
+
# dup is needed for `alias foo foo` (otherwise, "can't add a new key into hash during iteration" error occurs)
|
675
|
+
mdefs.dup.each do |mdef|
|
652
676
|
@class_defs[klass.idx].add_method(alias_mid, singleton, AliasMethodDef.new(orig_mid, mdef, ep))
|
653
677
|
end
|
654
678
|
end
|
@@ -755,24 +779,32 @@ module TypeProf
|
|
755
779
|
end
|
756
780
|
end
|
757
781
|
|
758
|
-
def
|
782
|
+
def identify_class_for_ivar(recv, var)
|
783
|
+
klass, singleton = recv.method_dispatch_info
|
784
|
+
return nil unless klass
|
785
|
+
search_method(klass, singleton, var) do |mthds, klass0, singleton0|
|
786
|
+
if mthds.any? {|mthd| mthd.is_a?(AttrMethodDef) }
|
787
|
+
return klass0, singleton
|
788
|
+
end
|
789
|
+
end
|
790
|
+
return klass, singleton
|
791
|
+
end
|
792
|
+
|
793
|
+
def get_ivar(recv, var)
|
759
794
|
recv = recv.base_type while recv.respond_to?(:base_type)
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
when Type::Any
|
766
|
-
return
|
795
|
+
|
796
|
+
klass, singleton = identify_class_for_ivar(recv, var.to_s[1..].to_sym) # search attr_reader
|
797
|
+
|
798
|
+
if klass
|
799
|
+
return @class_defs[klass.idx], singleton
|
767
800
|
else
|
768
|
-
|
769
|
-
return
|
801
|
+
return nil
|
770
802
|
end
|
771
803
|
end
|
772
804
|
|
773
805
|
def add_ivar_read!(recv, var, ep, &ctn)
|
774
806
|
recv.each_child do |recv|
|
775
|
-
class_def, singleton = get_ivar(recv)
|
807
|
+
class_def, singleton = get_ivar(recv, var)
|
776
808
|
next unless class_def
|
777
809
|
class_def.ivars.add_read!([singleton, var], ep, &ctn)
|
778
810
|
end
|
@@ -780,7 +812,7 @@ module TypeProf
|
|
780
812
|
|
781
813
|
def add_ivar_write!(recv, var, ty, ep)
|
782
814
|
recv.each_child do |recv|
|
783
|
-
class_def, singleton = get_ivar(recv)
|
815
|
+
class_def, singleton = get_ivar(recv, var)
|
784
816
|
next unless class_def
|
785
817
|
class_def.ivars.add_write!([singleton, var], ty, ep, self)
|
786
818
|
end
|
@@ -901,7 +933,16 @@ module TypeProf
|
|
901
933
|
prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
|
902
934
|
|
903
935
|
until @entrypoints.empty?
|
904
|
-
|
936
|
+
entrypoint = @entrypoints.shift
|
937
|
+
if entrypoint.is_a?(String)
|
938
|
+
file = entrypoint
|
939
|
+
next if @loaded_files[File.expand_path(file)]
|
940
|
+
iseq = ISeq.compile(file)
|
941
|
+
else
|
942
|
+
iseq = entrypoint
|
943
|
+
end
|
944
|
+
|
945
|
+
@loaded_files[iseq.absolute_path] = true
|
905
946
|
ep, env = TypeProf.starting_state(iseq)
|
906
947
|
merge_env(ep, env)
|
907
948
|
add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
|
@@ -1316,12 +1357,10 @@ module TypeProf
|
|
1316
1357
|
when :send
|
1317
1358
|
env, recvs, mid, aargs = setup_actual_arguments(:method, operands, ep, env)
|
1318
1359
|
recvs = Type.any if recvs == Type.bot
|
1319
|
-
recvs
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
merge_env(ep.next, nenv)
|
1324
|
-
end
|
1360
|
+
do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
|
1361
|
+
nenv, ret_ty, = localize_type(ret_ty, env, ep)
|
1362
|
+
nenv = nenv.push(ret_ty)
|
1363
|
+
merge_env(ep.next, nenv)
|
1325
1364
|
end
|
1326
1365
|
return
|
1327
1366
|
when :recv_getlocal_send_branch
|
@@ -1389,24 +1428,22 @@ module TypeProf
|
|
1389
1428
|
send_operands, branch_operands = operands
|
1390
1429
|
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1391
1430
|
recvs = Type.any if recvs == Type.bot
|
1392
|
-
recvs
|
1393
|
-
|
1394
|
-
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1431
|
+
do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
|
1432
|
+
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1395
1433
|
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1434
|
+
branchtype, target, = branch_operands
|
1435
|
+
# branchtype: :if or :unless or :nil
|
1436
|
+
ep_then = ep.next
|
1437
|
+
ep_else = ep.jump(target)
|
1400
1438
|
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
end
|
1439
|
+
case ret_ty
|
1440
|
+
when Type::Instance.new(Type::Builtin[:true])
|
1441
|
+
merge_env(branchtype == :if ? ep_else : ep_then, env)
|
1442
|
+
when Type::Instance.new(Type::Builtin[:false])
|
1443
|
+
merge_env(branchtype == :if ? ep_then : ep_else, env)
|
1444
|
+
else
|
1445
|
+
merge_env(ep_then, env)
|
1446
|
+
merge_env(ep_else, env)
|
1410
1447
|
end
|
1411
1448
|
end
|
1412
1449
|
return
|
@@ -1440,12 +1477,10 @@ module TypeProf
|
|
1440
1477
|
# XXX: this decomposition is really needed??
|
1441
1478
|
# It calls `Object.new` with union receiver which causes an error, but
|
1442
1479
|
# it may be a fault of builtin Object.new implementation.
|
1443
|
-
recv
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
merge_env(ep.next, nenv)
|
1448
|
-
end
|
1480
|
+
meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
|
1481
|
+
nenv, ret_ty, = localize_type(ret_ty, env, ep)
|
1482
|
+
nenv = nenv.push(ret_ty)
|
1483
|
+
merge_env(ep.next, nenv)
|
1449
1484
|
end
|
1450
1485
|
end
|
1451
1486
|
end
|
@@ -2133,30 +2168,32 @@ module TypeProf
|
|
2133
2168
|
return env, recv, mid, aargs
|
2134
2169
|
end
|
2135
2170
|
|
2136
|
-
def do_send(
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
klass, singleton = recv.method_dispatch_info
|
2145
|
-
meths = get_method(klass, singleton, mid) if klass
|
2146
|
-
if meths
|
2147
|
-
meths.each do |meth|
|
2148
|
-
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2149
|
-
end
|
2171
|
+
def do_send(recvs, mid, aargs, ep, env, &ctn)
|
2172
|
+
recvs.each_child do |recv|
|
2173
|
+
case recv
|
2174
|
+
when Type::Void
|
2175
|
+
error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2176
|
+
ctn[Type.any, ep, env]
|
2177
|
+
when Type::Any
|
2178
|
+
ctn[Type.any, ep, env]
|
2150
2179
|
else
|
2151
|
-
|
2180
|
+
klass, singleton, include_subclasses = recv.method_dispatch_info
|
2181
|
+
meths = get_method(klass, singleton, include_subclasses, mid) if klass
|
2152
2182
|
if meths
|
2153
|
-
aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
|
2154
2183
|
meths.each do |meth|
|
2155
|
-
meth.do_send(recv,
|
2184
|
+
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2156
2185
|
end
|
2157
2186
|
else
|
2158
|
-
|
2159
|
-
|
2187
|
+
meths = get_method(klass, singleton, include_subclasses, :method_missing) if klass
|
2188
|
+
if meths
|
2189
|
+
aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
|
2190
|
+
meths.each do |meth|
|
2191
|
+
meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
|
2192
|
+
end
|
2193
|
+
else
|
2194
|
+
error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2195
|
+
ctn[Type.any, ep, env]
|
2196
|
+
end
|
2160
2197
|
end
|
2161
2198
|
end
|
2162
2199
|
end
|
@@ -2241,7 +2278,11 @@ module TypeProf
|
|
2241
2278
|
next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
|
2242
2279
|
@block_to_ctx[blk.block_body].each do |blk_ctx|
|
2243
2280
|
if farg_tys
|
2244
|
-
|
2281
|
+
if @method_signatures[blk_ctx]
|
2282
|
+
farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
|
2283
|
+
else
|
2284
|
+
# this occurs when screen_name is called before type-profiling finished (e.g., error message)
|
2285
|
+
end
|
2245
2286
|
else
|
2246
2287
|
farg_tys = @method_signatures[blk_ctx]
|
2247
2288
|
end
|
@@ -2251,17 +2292,24 @@ module TypeProf
|
|
2251
2292
|
end
|
2252
2293
|
end
|
2253
2294
|
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2295
|
+
return Type.any.screen_name(self) if @types_being_shown.include?(farg_tys) || @types_being_shown.include?(ret_ty)
|
2296
|
+
|
2297
|
+
begin
|
2298
|
+
@types_being_shown << farg_tys << ret_ty
|
2299
|
+
farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
|
2300
|
+
ret_ty = ret_ty.screen_name(self)
|
2301
|
+
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2257
2302
|
|
2258
|
-
|
2259
|
-
|
2303
|
+
farg_tys = farg_tys + " " if farg_tys != ""
|
2304
|
+
"^#{ farg_tys }-> #{ ret_ty }"
|
2305
|
+
ensure
|
2306
|
+
@types_being_shown.pop(2)
|
2307
|
+
end
|
2260
2308
|
end
|
2261
2309
|
|
2262
2310
|
def show_method_signature(ctx)
|
2263
2311
|
farg_tys = @method_signatures[ctx]
|
2264
|
-
ret_ty = @return_values[ctx] || Type.bot
|
2312
|
+
ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot
|
2265
2313
|
|
2266
2314
|
untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self)
|
2267
2315
|
|
data/lib/typeprof/builtin.rb
CHANGED
@@ -73,9 +73,9 @@ module TypeProf
|
|
73
73
|
else
|
74
74
|
ty = Type::Instance.new(recv)
|
75
75
|
end
|
76
|
-
meths = scratch.get_method(recv, false, :initialize)
|
76
|
+
meths = scratch.get_method(recv, false, false, :initialize)
|
77
77
|
meths.flat_map do |meth|
|
78
|
-
meth.do_send(ty, :initialize, aargs, ep, env, scratch) do |
|
78
|
+
meth.do_send(ty, :initialize, aargs, ep, env, scratch) do |_ret_ty, ep, env|
|
79
79
|
ctn[ty, ep, env]
|
80
80
|
end
|
81
81
|
end
|
@@ -104,7 +104,7 @@ module TypeProf
|
|
104
104
|
sym = get_sym("respond_to?", aargs.lead_tys[0], ep, scratch)
|
105
105
|
if sym
|
106
106
|
klass, singleton = recv.method_dispatch_info
|
107
|
-
if scratch.get_method(klass, singleton, sym)
|
107
|
+
if scratch.get_method(klass, singleton, false, sym)
|
108
108
|
true_val = Type::Instance.new(Type::Builtin[:true])
|
109
109
|
ctn[true_val, ep, env]
|
110
110
|
else
|
@@ -334,7 +334,7 @@ module TypeProf
|
|
334
334
|
else
|
335
335
|
aargs.lead_tys.each do |aarg|
|
336
336
|
sym = get_sym("module_function", aarg, ep, scratch) or next
|
337
|
-
meths = scratch.get_method(recv, false, sym)
|
337
|
+
meths = scratch.get_method(recv, false, false, sym)
|
338
338
|
meths.each do |mdef|
|
339
339
|
scratch.add_method(recv, sym, true, mdef)
|
340
340
|
end
|
@@ -350,7 +350,7 @@ module TypeProf
|
|
350
350
|
if recv.is_a?(Type::Class)
|
351
351
|
aargs.lead_tys.each do |aarg|
|
352
352
|
sym = get_sym("public", aarg, ep, scratch) or next
|
353
|
-
meths = scratch.get_method(recv, false, sym)
|
353
|
+
meths = scratch.get_method(recv, false, false, sym)
|
354
354
|
next unless meths
|
355
355
|
meths.each do |mdef|
|
356
356
|
mdef.pub_meth = true if mdef.respond_to?(:pub_meth=)
|
@@ -370,7 +370,7 @@ module TypeProf
|
|
370
370
|
if recv.is_a?(Type::Class)
|
371
371
|
aargs.lead_tys.each do |aarg|
|
372
372
|
sym = get_sym("private", aarg, ep, scratch) or next
|
373
|
-
meths = scratch.get_method(recv, false, sym)
|
373
|
+
meths = scratch.get_method(recv, false, false, sym)
|
374
374
|
next unless meths
|
375
375
|
meths.each do |mdef|
|
376
376
|
mdef.pub_meth = false if mdef.respond_to?(:pub_meth=)
|
@@ -635,9 +635,6 @@ module TypeProf
|
|
635
635
|
end
|
636
636
|
|
637
637
|
def self.file_require(feature, scratch)
|
638
|
-
return :done, :false if scratch.loaded_features[feature]
|
639
|
-
scratch.loaded_features[feature] = true
|
640
|
-
|
641
638
|
# XXX: dynamic RBS load is really needed?? Another idea:
|
642
639
|
#
|
643
640
|
# * RBS should be loaded in advance of analysis
|
@@ -653,7 +650,11 @@ module TypeProf
|
|
653
650
|
|
654
651
|
begin
|
655
652
|
filetype, path = $LOAD_PATH.resolve_feature_path(feature)
|
653
|
+
|
656
654
|
if filetype == :rb
|
655
|
+
return :done, :false if scratch.loaded_files[path]
|
656
|
+
scratch.loaded_files[path] = true
|
657
|
+
|
657
658
|
return :do, path if File.readable?(path)
|
658
659
|
|
659
660
|
return :error, "failed to load: #{ path }"
|
@@ -714,13 +715,14 @@ module TypeProf
|
|
714
715
|
return ctn[Type.any, ep, env]
|
715
716
|
end
|
716
717
|
|
717
|
-
|
718
|
+
path = File.join(File.dirname(ep.ctx.iseq.absolute_path), feature) + ".rb" # XXX
|
719
|
+
|
720
|
+
if scratch.loaded_files[path]
|
718
721
|
result = Type::Instance.new(Type::Builtin[:false])
|
719
722
|
return ctn[result, ep, env]
|
720
723
|
end
|
721
|
-
scratch.
|
724
|
+
scratch.loaded_files[path] = true
|
722
725
|
|
723
|
-
path = File.join(File.dirname(ep.ctx.iseq.path), feature) + ".rb" # XXX
|
724
726
|
return Builtin.file_load(path, ep, env, scratch, &ctn) if File.readable?(path)
|
725
727
|
|
726
728
|
scratch.warn(ep, "failed to load: #{ path }")
|
data/lib/typeprof/cli.rb
CHANGED
@@ -64,6 +64,7 @@ module TypeProf
|
|
64
64
|
opt.separator "Advanced options:"
|
65
65
|
opt.on("--[no-]stub-execution", "Force to call all unreachable methods with \"untyped\" arguments") {|v| options[:stub_execution] = v }
|
66
66
|
opt.on("--type-depth-limit DEPTH", Integer, "Limit the maximum depth of nested types") {|v| options[:type_depth_limit] = v }
|
67
|
+
opt.on("--union-width-limit WIDTH", Integer, "Limit the maximum count of class instances in one union type") {|v| options[:union_width_limit] = v }
|
67
68
|
opt.on("--debug", "Display analysis log (for debugging purpose)") { verbose = 2 }
|
68
69
|
opt.on("--[no-]stackprof MODE", /\Acpu|wall|object\z/, "Enable stackprof (for debugging purpose)") {|v| options[:stackprof] = v.to_sym }
|
69
70
|
|
data/lib/typeprof/config.rb
CHANGED
@@ -40,6 +40,7 @@ module TypeProf
|
|
40
40
|
show_source_locations: false,
|
41
41
|
stub_execution: true,
|
42
42
|
type_depth_limit: 5,
|
43
|
+
union_width_limit: 10,
|
43
44
|
stackprof: nil,
|
44
45
|
}.merge(opt[:options])
|
45
46
|
super(**opt)
|
@@ -98,7 +99,7 @@ module TypeProf
|
|
98
99
|
if rb.is_a?(Array) # [String name, String content]
|
99
100
|
iseq = ISeq.compile_str(*rb.reverse)
|
100
101
|
else
|
101
|
-
iseq =
|
102
|
+
iseq = rb
|
102
103
|
end
|
103
104
|
scratch.add_entrypoint(iseq)
|
104
105
|
end
|
data/lib/typeprof/export.rb
CHANGED
@@ -149,6 +149,7 @@ module TypeProf
|
|
149
149
|
source_locations[key] ||= ctx.iseq.source_location(0)
|
150
150
|
(methods[key] ||= []) << @scratch.show_method_signature(ctx)
|
151
151
|
when AliasMethodDef
|
152
|
+
next if mdef.def_ep && Config.check_dir_filter(mdef.def_ep.source_location) == :exclude
|
152
153
|
alias_name, orig_name = mid, mdef.orig_mid
|
153
154
|
if singleton
|
154
155
|
alias_name = "self.#{ alias_name }"
|
data/lib/typeprof/import.rb
CHANGED
@@ -373,25 +373,30 @@ module TypeProf
|
|
373
373
|
end
|
374
374
|
|
375
375
|
def conv_block(rbs_block)
|
376
|
-
|
376
|
+
blk = rbs_block.type
|
377
377
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
conv_type(type.type)
|
387
|
-
end
|
388
|
-
opt_tys = type.optional_positionals.map do |type|
|
389
|
-
conv_type(type.type)
|
390
|
-
end
|
378
|
+
lead_tys = blk.required_positionals.map {|type| conv_type(type.type) }
|
379
|
+
opt_tys = blk.optional_positionals.map {|type| conv_type(type.type) }
|
380
|
+
rest_ty = blk.rest_positionals
|
381
|
+
rest_ty = conv_type(rest_ty.type) if rest_ty
|
382
|
+
opt_kw_tys = blk.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
383
|
+
req_kw_tys = blk.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
384
|
+
rest_kw_ty = blk.rest_keywords
|
385
|
+
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
391
386
|
|
392
|
-
ret_ty = conv_type(
|
387
|
+
ret_ty = conv_type(blk.return_type)
|
393
388
|
|
394
|
-
|
389
|
+
{
|
390
|
+
required_block: rbs_block.required,
|
391
|
+
lead_tys: lead_tys,
|
392
|
+
opt_tys: opt_tys,
|
393
|
+
rest_ty: rest_ty,
|
394
|
+
req_kw_tys: req_kw_tys,
|
395
|
+
opt_kw_tys: opt_kw_tys,
|
396
|
+
rest_kw_ty: rest_kw_ty,
|
397
|
+
blk: blk,
|
398
|
+
ret_ty: ret_ty,
|
399
|
+
}
|
395
400
|
end
|
396
401
|
|
397
402
|
def conv_type(ty)
|
@@ -630,7 +635,13 @@ module TypeProf
|
|
630
635
|
kw_tys = []
|
631
636
|
req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
|
632
637
|
opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
|
633
|
-
|
638
|
+
if rest_kw_ty
|
639
|
+
ty = conv_type(rest_kw_ty)
|
640
|
+
kw_rest_ty = Type.gen_hash do |h|
|
641
|
+
k_ty = Type::Instance.new(Type::Builtin[:sym])
|
642
|
+
h[k_ty] = ty
|
643
|
+
end
|
644
|
+
end
|
634
645
|
|
635
646
|
blks = conv_block(blk)
|
636
647
|
|
@@ -643,13 +654,36 @@ module TypeProf
|
|
643
654
|
|
644
655
|
def conv_block(blk)
|
645
656
|
return [Type.nil] unless blk
|
646
|
-
|
657
|
+
|
658
|
+
required_block = blk[:required_block]
|
659
|
+
lead_tys = blk[:lead_tys]
|
660
|
+
opt_tys = blk[:opt_tys]
|
661
|
+
rest_ty = blk[:rest_ty]
|
662
|
+
req_kw_tys = blk[:req_kw_tys]
|
663
|
+
opt_kw_tys = blk[:opt_kw_tys]
|
664
|
+
rest_kw_ty = blk[:rest_kw_ty]
|
665
|
+
ret_ty = blk[:ret_ty]
|
666
|
+
|
647
667
|
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
648
668
|
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
649
|
-
|
669
|
+
rest_ty = conv_type(rest_ty) if rest_ty
|
670
|
+
kw_tys = []
|
671
|
+
req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
|
672
|
+
opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
|
673
|
+
if rest_kw_ty
|
674
|
+
ty = conv_type(rest_kw_ty)
|
675
|
+
kw_rest_ty = Type.gen_hash do |h|
|
676
|
+
k_ty = Type::Instance.new(Type::Builtin[:sym])
|
677
|
+
h[k_ty] = ty
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
msig = MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, Type.nil)
|
682
|
+
|
650
683
|
ret_ty = conv_type(ret_ty)
|
684
|
+
|
651
685
|
ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
|
652
|
-
ret << Type.nil unless
|
686
|
+
ret << Type.nil unless required_block
|
653
687
|
ret
|
654
688
|
end
|
655
689
|
|
@@ -694,7 +728,7 @@ module TypeProf
|
|
694
728
|
end
|
695
729
|
when :union
|
696
730
|
tys = ty[1]
|
697
|
-
Type::Union.
|
731
|
+
Type::Union.create(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support
|
698
732
|
when :var
|
699
733
|
Type::Var.new(ty[1])
|
700
734
|
when :proc
|
data/lib/typeprof/type.rb
CHANGED
@@ -102,34 +102,43 @@ module TypeProf
|
|
102
102
|
|
103
103
|
ty1, ty2 = self, other
|
104
104
|
|
105
|
-
|
106
|
-
|
105
|
+
case
|
106
|
+
when ty1.is_a?(Union)
|
107
|
+
ty1_types = ty1.types
|
108
|
+
ty1_elems = ty1.elems
|
109
|
+
when ty1.is_a?(Array) || ty1.is_a?(Hash)
|
110
|
+
ty1_types = Utils::Set[]
|
111
|
+
ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems}
|
112
|
+
else
|
113
|
+
ty1_types = ty1_elems = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
case
|
117
|
+
when ty2.is_a?(Union)
|
118
|
+
ty2_types = ty2.types
|
119
|
+
ty2_elems = ty2.elems
|
120
|
+
when ty2.is_a?(Array) || ty2.is_a?(Hash)
|
121
|
+
ty2_types = Utils::Set[]
|
122
|
+
ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems}
|
123
|
+
else
|
124
|
+
ty2_types = ty2_elems = nil
|
125
|
+
end
|
107
126
|
|
108
|
-
if
|
109
|
-
ty =
|
110
|
-
all_elems =
|
111
|
-
|
127
|
+
if ty1_types && ty2_types
|
128
|
+
ty = ty1_types.sum(ty2_types)
|
129
|
+
all_elems = ty1_elems.dup || {}
|
130
|
+
ty2_elems&.each do |key, elems|
|
112
131
|
all_elems[key] = union_elems(all_elems[key], elems)
|
113
132
|
end
|
114
133
|
all_elems = nil if all_elems.empty?
|
115
134
|
|
116
|
-
Type::Union.
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
else
|
122
|
-
Type::Union.new(Utils::Set[ty1, ty2], nil).normalize
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private def container_to_union(ty)
|
128
|
-
case ty
|
129
|
-
when Type::Array, Type::Hash
|
130
|
-
Type::Union.new(Utils::Set[], { [ty.class, ty.base_type] => ty.elems })
|
135
|
+
Type::Union.create(ty, all_elems)
|
136
|
+
elsif ty1_types
|
137
|
+
Type::Union.create(ty1_types.add(ty2), ty1_elems)
|
138
|
+
elsif ty2_types
|
139
|
+
Type::Union.create(ty2_types.add(ty1), ty2_elems)
|
131
140
|
else
|
132
|
-
|
141
|
+
Type::Union.create(Utils::Set[ty1, ty2], nil)
|
133
142
|
end
|
134
143
|
end
|
135
144
|
|
@@ -207,6 +216,37 @@ module TypeProf
|
|
207
216
|
|
208
217
|
|
209
218
|
class Union < Type
|
219
|
+
def self.create(tys, elems)
|
220
|
+
if tys.size == 1 && !elems
|
221
|
+
tys.each {|ty| return ty }
|
222
|
+
elsif tys.size == 0
|
223
|
+
if elems && elems.size == 1
|
224
|
+
(container_kind, base_type), nelems = elems.first
|
225
|
+
# container_kind = Type::Array or Type::Hash
|
226
|
+
container_kind.new(nelems, base_type)
|
227
|
+
else
|
228
|
+
new(tys, elems)
|
229
|
+
end
|
230
|
+
else
|
231
|
+
class_instances = []
|
232
|
+
non_class_instances = []
|
233
|
+
degenerated = false
|
234
|
+
tys.each do |ty|
|
235
|
+
if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class
|
236
|
+
class_instances << ty
|
237
|
+
degenerated = true if ty.include_subclasses
|
238
|
+
else
|
239
|
+
non_class_instances << ty
|
240
|
+
end
|
241
|
+
end
|
242
|
+
if (Config.options[:union_width_limit] >= 2 && class_instances.size >= Config.options[:union_width_limit]) || (degenerated && class_instances.size >= 2)
|
243
|
+
create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems)
|
244
|
+
else
|
245
|
+
new(tys, elems)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
210
250
|
def initialize(tys, elems)
|
211
251
|
raise unless tys.is_a?(Utils::Set)
|
212
252
|
@types = tys # Set
|
@@ -243,22 +283,6 @@ module TypeProf
|
|
243
283
|
|
244
284
|
attr_reader :types, :elems
|
245
285
|
|
246
|
-
def normalize
|
247
|
-
if @types.size == 1 && !@elems
|
248
|
-
@types.each {|ty| return ty }
|
249
|
-
elsif @types.size == 0
|
250
|
-
if @elems && @elems.size == 1
|
251
|
-
(container_kind, base_type), elems = @elems.first
|
252
|
-
# container_kind = Type::Array or Type::Hash
|
253
|
-
container_kind.new(elems, base_type)
|
254
|
-
else
|
255
|
-
self
|
256
|
-
end
|
257
|
-
else
|
258
|
-
self
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
286
|
def each_child(&blk) # local
|
263
287
|
@types.each(&blk)
|
264
288
|
raise if @elems
|
@@ -343,7 +367,7 @@ module TypeProf
|
|
343
367
|
end
|
344
368
|
elems = nil if elems.empty?
|
345
369
|
|
346
|
-
Type::Union.
|
370
|
+
Type::Union.create(tys, elems)
|
347
371
|
end
|
348
372
|
|
349
373
|
def localize(env, alloc_site, depth)
|
@@ -357,7 +381,7 @@ module TypeProf
|
|
357
381
|
env, ty = ty.localize(env, alloc_site, depth - 1)
|
358
382
|
tys = tys.add(ty)
|
359
383
|
end
|
360
|
-
ty = Union.
|
384
|
+
ty = Union.create(tys, nil)
|
361
385
|
return env, ty
|
362
386
|
end
|
363
387
|
|
@@ -381,7 +405,7 @@ module TypeProf
|
|
381
405
|
elems = @elems&.to_h do |(container_kind, base_type), elems|
|
382
406
|
[[container_kind, base_type], elems.substitute(subst, depth - 1)]
|
383
407
|
end
|
384
|
-
ty = Union.
|
408
|
+
ty = Union.create(tys, elems)
|
385
409
|
unions.each do |ty0|
|
386
410
|
ty = ty.union(ty0)
|
387
411
|
end
|
@@ -484,7 +508,7 @@ module TypeProf
|
|
484
508
|
end
|
485
509
|
|
486
510
|
def method_dispatch_info
|
487
|
-
[self, true]
|
511
|
+
[self, true, false]
|
488
512
|
end
|
489
513
|
|
490
514
|
def consistent?(other)
|
@@ -513,15 +537,40 @@ module TypeProf
|
|
513
537
|
end
|
514
538
|
|
515
539
|
class Instance < Type
|
516
|
-
def initialize(klass)
|
540
|
+
def initialize(klass, include_subclasses=false)
|
517
541
|
raise unless klass
|
518
542
|
raise if klass == Type.any
|
519
543
|
raise if klass.is_a?(Type::Instance)
|
520
544
|
raise if klass.is_a?(Type::Union)
|
521
545
|
@klass = klass
|
546
|
+
@include_subclasses = include_subclasses
|
547
|
+
end
|
548
|
+
|
549
|
+
def self.new_degenerate(instances)
|
550
|
+
klass = instances.first.klass
|
551
|
+
ancestors = []
|
552
|
+
ancestor_idxs = {}
|
553
|
+
while klass != :__root__
|
554
|
+
ancestor_idxs[klass] = ancestors.size
|
555
|
+
ancestors << klass
|
556
|
+
klass = klass.superclass
|
557
|
+
end
|
558
|
+
common_superclass = nil
|
559
|
+
instances[1..].each do |instance|
|
560
|
+
klass = instance.klass
|
561
|
+
while !ancestor_idxs[klass]
|
562
|
+
klass = klass.superclass
|
563
|
+
end
|
564
|
+
common_superclass = klass
|
565
|
+
ancestor_idxs[klass].times do |i|
|
566
|
+
ancestor_idxs.delete(ancestors[i])
|
567
|
+
ancestors[i] = nil
|
568
|
+
end
|
569
|
+
end
|
570
|
+
new(common_superclass, true)
|
522
571
|
end
|
523
572
|
|
524
|
-
attr_reader :klass
|
573
|
+
attr_reader :klass, :include_subclasses
|
525
574
|
|
526
575
|
def inspect
|
527
576
|
"I[#{ @klass.inspect }]"
|
@@ -533,12 +582,12 @@ module TypeProf
|
|
533
582
|
when Type::Builtin[:true] then "true"
|
534
583
|
when Type::Builtin[:false] then "false"
|
535
584
|
else
|
536
|
-
scratch.get_class_name(@klass)
|
585
|
+
scratch.get_class_name(@klass) + (@include_subclasses ? "" : "")
|
537
586
|
end
|
538
587
|
end
|
539
588
|
|
540
589
|
def method_dispatch_info
|
541
|
-
[@klass, false]
|
590
|
+
[@klass, false, @include_subclasses]
|
542
591
|
end
|
543
592
|
|
544
593
|
def consistent?(other)
|
@@ -847,6 +896,7 @@ module TypeProf
|
|
847
896
|
end
|
848
897
|
if Config.options[:show_parameter_names]
|
849
898
|
farg_names = farg_names.map {|name| name == :type ? :type_ : name } # XXX: workaround of RBS parser bug
|
899
|
+
farg_names = farg_names.map {|name| name.is_a?(Integer) ? "noname_#{ name }" : name }
|
850
900
|
fargs = fargs.zip(farg_names).map {|farg, name| name ? "#{ farg } #{ name }" : farg }
|
851
901
|
end
|
852
902
|
fargs = fargs.empty? ? "" : "(#{ fargs.join(", ") })"
|
data/lib/typeprof/version.rb
CHANGED
data/smoke/alias2.rb
CHANGED
data/smoke/array3.rb
CHANGED
data/smoke/attr-module.rb
CHANGED
@@ -10,18 +10,15 @@ end
|
|
10
10
|
Foo.foo = 42
|
11
11
|
Bar.new.foo = "str"
|
12
12
|
|
13
|
-
# XXX: the output may be improved
|
14
|
-
|
15
13
|
__END__
|
16
14
|
# Classes
|
17
15
|
module Foo
|
18
16
|
self.@foo: Integer
|
19
17
|
|
20
|
-
attr_accessor foo:
|
18
|
+
attr_accessor foo: String
|
21
19
|
attr_accessor self.foo: Integer
|
22
20
|
end
|
23
21
|
|
24
22
|
class Bar
|
25
23
|
include Foo
|
26
|
-
@foo: String
|
27
24
|
end
|
data/smoke/attr-vis.rb
CHANGED
data/smoke/attr.rb
CHANGED
data/smoke/huge_union.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
class C0; end
|
2
|
+
class C1 < C0; def foo(n); end; end
|
3
|
+
class C2 < C0; def foo(n); end; end
|
4
|
+
class C3 < C0; def foo(n); end; end
|
5
|
+
class C4 < C0; def foo(n); end; end
|
6
|
+
class C5 < C0; def foo(n); end; end
|
7
|
+
class C6 < C0; def foo(n); end; end
|
8
|
+
class C7 < C0; def foo(n); end; end
|
9
|
+
class C8 < C0; def foo(n); end; end
|
10
|
+
class C9 < C0; def foo(n); end; end
|
11
|
+
class C10 < C0; def foo(n); end; end
|
12
|
+
class C11 < C0; def foo(n); end; end
|
13
|
+
class C12 < C0; def foo(n); end; end
|
14
|
+
|
15
|
+
def dispatch_foo(n)
|
16
|
+
n.foo("str")
|
17
|
+
end
|
18
|
+
|
19
|
+
dispatch_foo(C1.new)
|
20
|
+
dispatch_foo(C2.new)
|
21
|
+
dispatch_foo(C3.new)
|
22
|
+
dispatch_foo(C4.new)
|
23
|
+
dispatch_foo(C5.new)
|
24
|
+
dispatch_foo(C6.new)
|
25
|
+
dispatch_foo(C7.new)
|
26
|
+
dispatch_foo(C8.new)
|
27
|
+
dispatch_foo(C9.new)
|
28
|
+
dispatch_foo(C10.new)
|
29
|
+
|
30
|
+
__END__
|
31
|
+
# Classes
|
32
|
+
class Object
|
33
|
+
private
|
34
|
+
def dispatch_foo: (C0 n) -> nil
|
35
|
+
end
|
36
|
+
|
37
|
+
class C0
|
38
|
+
end
|
39
|
+
|
40
|
+
class C1 < C0
|
41
|
+
def foo: (String n) -> nil
|
42
|
+
end
|
43
|
+
|
44
|
+
class C2 < C0
|
45
|
+
def foo: (String n) -> nil
|
46
|
+
end
|
47
|
+
|
48
|
+
class C3 < C0
|
49
|
+
def foo: (String n) -> nil
|
50
|
+
end
|
51
|
+
|
52
|
+
class C4 < C0
|
53
|
+
def foo: (String n) -> nil
|
54
|
+
end
|
55
|
+
|
56
|
+
class C5 < C0
|
57
|
+
def foo: (String n) -> nil
|
58
|
+
end
|
59
|
+
|
60
|
+
class C6 < C0
|
61
|
+
def foo: (String n) -> nil
|
62
|
+
end
|
63
|
+
|
64
|
+
class C7 < C0
|
65
|
+
def foo: (String n) -> nil
|
66
|
+
end
|
67
|
+
|
68
|
+
class C8 < C0
|
69
|
+
def foo: (String n) -> nil
|
70
|
+
end
|
71
|
+
|
72
|
+
class C9 < C0
|
73
|
+
def foo: (String n) -> nil
|
74
|
+
end
|
75
|
+
|
76
|
+
class C10 < C0
|
77
|
+
def foo: (String n) -> nil
|
78
|
+
end
|
79
|
+
|
80
|
+
class C11 < C0
|
81
|
+
def foo: (String n) -> nil
|
82
|
+
end
|
83
|
+
|
84
|
+
class C12 < C0
|
85
|
+
def foo: (String n) -> nil
|
86
|
+
end
|
data/smoke/initialize.rb
CHANGED
data/smoke/ivar2.rb
CHANGED
data/smoke/ivar3.rb
CHANGED
data/smoke/kwrest.rb
CHANGED
data/smoke/kwrest.rbs
CHANGED
data/smoke/method_missing.rb
CHANGED
data/smoke/noname.rb
ADDED
data/smoke/proc6.rb
ADDED
data/smoke/proc7.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class Foo
|
2
|
+
def id(&blk)
|
3
|
+
blk
|
4
|
+
end
|
5
|
+
|
6
|
+
def check(v)
|
7
|
+
rand < 0.5 ? v : [v]
|
8
|
+
end
|
9
|
+
|
10
|
+
def foo
|
11
|
+
check(id {}).call # cause "undefined method: [^-> nil?]#call"
|
12
|
+
end
|
13
|
+
|
14
|
+
def foo1
|
15
|
+
id { }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
__END__
|
20
|
+
# Errors
|
21
|
+
smoke/proc7.rb:11: [error] undefined method: nil#call
|
22
|
+
smoke/proc7.rb:11: [error] undefined method: [(^(unknown) -> bot | untyped)?]#call
|
23
|
+
smoke/proc7.rb:11: [error] undefined method: nil#call
|
24
|
+
smoke/proc7.rb:11: [error] undefined method: [(^-> nil | untyped)?]#call
|
25
|
+
|
26
|
+
# Classes
|
27
|
+
class Foo
|
28
|
+
def id: ?{ -> nil } -> ^-> nil?
|
29
|
+
def check: ((^-> nil | untyped)? v) -> (([(^-> nil | untyped)?] | ^-> nil | untyped)?)
|
30
|
+
def foo: -> untyped?
|
31
|
+
def foo1: -> ^-> nil?
|
32
|
+
end
|
data/smoke/rbs-tyvar4.rb
CHANGED
data/smoke/require1.rb
ADDED
data/smoke/require2.rb
ADDED
data/smoke/struct5.rb
CHANGED
data/smoke/struct6.rb
CHANGED
data/smoke/struct7.rb
CHANGED
data/smoke/super3.rb
CHANGED
data/smoke/symbol-proc-attr.rb
CHANGED
data/smoke/symbol-proc-attr2.rb
CHANGED
data/typeprof.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typeprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yusuke Endoh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rbs
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.3.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.3.1
|
27
27
|
description: |
|
28
28
|
TypeProf performs a type analysis of non-annotated Ruby code.
|
29
29
|
|
@@ -216,6 +216,7 @@ files:
|
|
216
216
|
- smoke/hash3.rb
|
217
217
|
- smoke/hash4.rb
|
218
218
|
- smoke/hash5.rb
|
219
|
+
- smoke/huge_union.rb
|
219
220
|
- smoke/included.rb
|
220
221
|
- smoke/inheritance.rb
|
221
222
|
- smoke/inheritance2.rb
|
@@ -267,6 +268,7 @@ files:
|
|
267
268
|
- smoke/multiple-superclass.rb
|
268
269
|
- smoke/next1.rb
|
269
270
|
- smoke/next2.rb
|
271
|
+
- smoke/noname.rb
|
270
272
|
- smoke/object-send1.rb
|
271
273
|
- smoke/object-send2.rb
|
272
274
|
- smoke/object-send3.rb
|
@@ -290,6 +292,8 @@ files:
|
|
290
292
|
- smoke/proc3.rb
|
291
293
|
- smoke/proc4.rb
|
292
294
|
- smoke/proc5.rb
|
295
|
+
- smoke/proc6.rb
|
296
|
+
- smoke/proc7.rb
|
293
297
|
- smoke/public.rb
|
294
298
|
- smoke/range.rb
|
295
299
|
- smoke/rbs-alias.rb
|
@@ -332,6 +336,8 @@ files:
|
|
332
336
|
- smoke/redo1.rb
|
333
337
|
- smoke/redo2.rb
|
334
338
|
- smoke/req-keyword.rb
|
339
|
+
- smoke/require1.rb
|
340
|
+
- smoke/require2.rb
|
335
341
|
- smoke/rescue1.rb
|
336
342
|
- smoke/rescue2.rb
|
337
343
|
- smoke/rescue3.rb
|