typeprof 0.14.1 → 0.15.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/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
|