typeprof 0.3.0 → 0.4.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 +1 -1
- data/doc/demo.md +398 -0
- data/doc/doc.ja.md +4 -0
- data/doc/doc.md +4 -0
- data/lib/typeprof.rb +8 -0
- data/lib/typeprof/analyzer.rb +229 -245
- data/lib/typeprof/arguments.rb +397 -0
- data/lib/typeprof/block.rb +133 -0
- data/lib/typeprof/builtin.rb +14 -10
- data/lib/typeprof/container-type.rb +94 -17
- data/lib/typeprof/export.rb +185 -108
- data/lib/typeprof/import.rb +76 -54
- data/lib/typeprof/iseq.rb +27 -2
- data/lib/typeprof/method.rb +87 -73
- data/lib/typeprof/type.rb +125 -309
- data/lib/typeprof/version.rb +1 -1
- data/smoke/arguments2.rb +1 -1
- data/smoke/array-each3.rb +1 -4
- data/smoke/array12.rb +1 -1
- data/smoke/array6.rb +1 -0
- data/smoke/block-ambiguous.rb +36 -0
- data/smoke/block-args1-rest.rb +62 -0
- data/smoke/block-args1.rb +59 -0
- data/smoke/block-args2-rest.rb +62 -0
- data/smoke/block-args2.rb +59 -0
- data/smoke/block-args3-rest.rb +73 -0
- data/smoke/block-args3.rb +70 -0
- data/smoke/block-blockarg.rb +27 -0
- data/smoke/block-kwarg.rb +52 -0
- data/smoke/block11.rb +1 -1
- data/smoke/block14.rb +17 -0
- data/smoke/block4.rb +2 -2
- data/smoke/block5.rb +1 -0
- data/smoke/block6.rb +1 -1
- data/smoke/block7.rb +0 -2
- data/smoke/block8.rb +2 -2
- data/smoke/block9.rb +1 -1
- data/smoke/blown.rb +1 -1
- data/smoke/class-hierarchy.rb +54 -0
- data/smoke/class-hierarchy2.rb +27 -0
- data/smoke/constant1.rb +11 -6
- data/smoke/constant2.rb +2 -0
- data/smoke/cvar.rb +1 -0
- data/smoke/demo10.rb +1 -1
- data/smoke/demo8.rb +2 -2
- data/smoke/demo9.rb +1 -3
- data/smoke/flow7.rb +1 -7
- data/smoke/flow8.rb +13 -0
- data/smoke/instance_eval.rb +1 -1
- data/smoke/int_times.rb +1 -1
- data/smoke/multiple-superclass.rb +4 -0
- data/smoke/next2.rb +1 -1
- data/smoke/optional3.rb +10 -0
- data/smoke/proc4.rb +1 -1
- data/smoke/rbs-proc1.rb +9 -0
- data/smoke/rbs-proc1.rbs +3 -0
- data/smoke/rbs-proc2.rb +20 -0
- data/smoke/rbs-proc2.rbs +3 -0
- data/smoke/rbs-proc3.rb +13 -0
- data/smoke/rbs-proc3.rbs +4 -0
- data/smoke/rbs-record.rb +17 -0
- data/smoke/rbs-record.rbs +4 -0
- data/smoke/rbs-tyvar3.rb +25 -0
- data/smoke/rbs-tyvar3.rbs +4 -0
- data/smoke/rest2.rb +1 -1
- data/smoke/rest5.rb +1 -1
- data/smoke/return.rb +1 -1
- data/smoke/singleton_method.rb +3 -0
- data/smoke/struct.rb +4 -3
- data/smoke/struct3.rb +14 -0
- data/smoke/symbol-proc.rb +24 -0
- metadata +31 -3
- data/smoke/variadic1.rb.notyet +0 -5
data/lib/typeprof/builtin.rb
CHANGED
|
@@ -59,14 +59,13 @@ module TypeProf
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def proc_call(recv, mid, aargs, ep, env, scratch, &ctn)
|
|
62
|
-
|
|
63
|
-
scratch.do_invoke_block(given_block, recv, aargs, ep, env, &ctn)
|
|
62
|
+
scratch.do_invoke_block(recv, aargs, ep, env, &ctn)
|
|
64
63
|
end
|
|
65
64
|
|
|
66
65
|
def object_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
|
|
67
66
|
ty = Type::Instance.new(recv)
|
|
68
67
|
if recv.type_params.size >= 1
|
|
69
|
-
ty = Type::Cell.new([Type.bot] * recv.type_params.size, ty)
|
|
68
|
+
ty = Type::Cell.new(Type::Cell::Elements.new([Type.bot] * recv.type_params.size), ty)
|
|
70
69
|
env, ty = scratch.localize_type(ty, env, ep, AllocationSite.new(ep).add_id(:object_s_new))
|
|
71
70
|
end
|
|
72
71
|
meths = scratch.get_method(recv, false, :initialize)
|
|
@@ -142,9 +141,8 @@ module TypeProf
|
|
|
142
141
|
ctn[type.any, ep, env]
|
|
143
142
|
return
|
|
144
143
|
end
|
|
145
|
-
naargs = ActualArguments.new([recv],
|
|
146
|
-
|
|
147
|
-
scratch.do_invoke_block(given_block, aargs.blk_ty, naargs, ep, env, replace_recv_ty: recv) do |_ret_ty, ep|
|
|
144
|
+
naargs = ActualArguments.new([recv], nil, {}, Type.nil)
|
|
145
|
+
scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: recv) do |_ret_ty, ep|
|
|
148
146
|
ctn[recv, ep, scratch.return_envs[ep]]
|
|
149
147
|
end
|
|
150
148
|
end
|
|
@@ -263,7 +261,7 @@ module TypeProf
|
|
|
263
261
|
|
|
264
262
|
ty = aargs.lead_tys.last
|
|
265
263
|
|
|
266
|
-
env = scratch.update_container_elem_types(env, ep, recv.id) do |elems|
|
|
264
|
+
env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems|
|
|
267
265
|
elems.update(idx, ty)
|
|
268
266
|
end
|
|
269
267
|
|
|
@@ -314,7 +312,7 @@ module TypeProf
|
|
|
314
312
|
return ctn[ty, ep, env]
|
|
315
313
|
end
|
|
316
314
|
|
|
317
|
-
env = scratch.update_container_elem_types(env, ep, recv.id) do |elems|
|
|
315
|
+
env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems|
|
|
318
316
|
elems.update(idx, ty)
|
|
319
317
|
end
|
|
320
318
|
|
|
@@ -486,8 +484,8 @@ module TypeProf
|
|
|
486
484
|
def self.setup_initial_global_env(scratch)
|
|
487
485
|
klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass
|
|
488
486
|
klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil)
|
|
489
|
-
scratch.add_constant(klass_obj, :Object, klass_obj)
|
|
490
|
-
scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj)
|
|
487
|
+
scratch.add_constant(klass_obj, :Object, klass_obj, nil)
|
|
488
|
+
scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj, nil)
|
|
491
489
|
|
|
492
490
|
Type::Builtin[:basic_obj] = klass_basic_obj
|
|
493
491
|
Type::Builtin[:obj] = klass_obj
|
|
@@ -533,6 +531,7 @@ module TypeProf
|
|
|
533
531
|
scratch.set_custom_method(klass_obj, :class, Builtin.method(:object_class))
|
|
534
532
|
scratch.set_custom_method(klass_obj, :send, Builtin.method(:object_send))
|
|
535
533
|
scratch.set_custom_method(klass_obj, :instance_eval, Builtin.method(:object_instance_eval))
|
|
534
|
+
scratch.set_custom_method(klass_obj, :proc, Builtin.method(:lambda))
|
|
536
535
|
|
|
537
536
|
scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include))
|
|
538
537
|
scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend))
|
|
@@ -554,6 +553,11 @@ module TypeProf
|
|
|
554
553
|
scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require))
|
|
555
554
|
scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative))
|
|
556
555
|
scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array))
|
|
556
|
+
|
|
557
|
+
# ENV: Hash[String, String]
|
|
558
|
+
str_ty = Type::Instance.new(Type::Builtin[:str])
|
|
559
|
+
env_ty = Type.gen_hash {|h| h[str_ty] = Type.optional(str_ty) }
|
|
560
|
+
scratch.add_constant(klass_obj, :ENV, env_ty, false)
|
|
557
561
|
end
|
|
558
562
|
end
|
|
559
563
|
end
|
|
@@ -22,7 +22,8 @@ module TypeProf
|
|
|
22
22
|
# The most basic container type for default type parameter class
|
|
23
23
|
class Cell < Type
|
|
24
24
|
def initialize(elems, base_type)
|
|
25
|
-
|
|
25
|
+
raise if !elems.is_a?(Cell::Elements)
|
|
26
|
+
@elems = elems # Cell::Elements
|
|
26
27
|
raise unless base_type
|
|
27
28
|
@base_type = base_type
|
|
28
29
|
end
|
|
@@ -34,22 +35,23 @@ module TypeProf
|
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
def screen_name(scratch)
|
|
37
|
-
|
|
38
|
+
str = @elems.screen_name(scratch)
|
|
39
|
+
if str.start_with?("*")
|
|
40
|
+
str = @base_type.screen_name(scratch) + str[1..]
|
|
41
|
+
end
|
|
42
|
+
str
|
|
38
43
|
end
|
|
39
44
|
|
|
40
45
|
def localize(env, alloc_site, depth)
|
|
41
46
|
return env, Type.any if depth <= 0
|
|
42
47
|
alloc_site = alloc_site.add_id(:cell)
|
|
43
|
-
elems = @elems.
|
|
44
|
-
|
|
45
|
-
elem
|
|
46
|
-
end
|
|
47
|
-
env.deploy_cell_type(alloc_site, elems, @base_type)
|
|
48
|
+
env, elems = @elems.localize(env, alloc_site, depth)
|
|
49
|
+
env.deploy_type(LocalCell, alloc_site, elems, @base_type)
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
def limit_size(limit)
|
|
51
53
|
return Type.any if limit <= 0
|
|
52
|
-
Cell.new(@elems.
|
|
54
|
+
Cell.new(@elems.limit_size(limit - 1), @base_type)
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def get_method(mid, scratch)
|
|
@@ -76,9 +78,81 @@ module TypeProf
|
|
|
76
78
|
|
|
77
79
|
def substitute(subst, depth)
|
|
78
80
|
return Type.any if depth <= 0
|
|
79
|
-
elems = @elems.
|
|
81
|
+
elems = @elems.substitute(subst, depth)
|
|
80
82
|
Cell.new(elems, @base_type)
|
|
81
83
|
end
|
|
84
|
+
|
|
85
|
+
class Elements
|
|
86
|
+
include Utils::StructuralEquality
|
|
87
|
+
|
|
88
|
+
def initialize(elems)
|
|
89
|
+
@elems = elems
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
attr_reader :elems
|
|
93
|
+
|
|
94
|
+
def to_local_type(id, base_ty)
|
|
95
|
+
Type::LocalCell.new(id, base_ty)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def globalize(env, visited, depth)
|
|
99
|
+
Elements.new(@elems.map {|ty| ty.globalize(env, visited, depth) })
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def localize(env, alloc_site, depth)
|
|
103
|
+
elems = @elems.map.with_index do |ty, i|
|
|
104
|
+
alloc_site2 = alloc_site.add_id(i)
|
|
105
|
+
env, ty = ty.localize(env, alloc_site2, depth)
|
|
106
|
+
ty
|
|
107
|
+
end
|
|
108
|
+
return env, Elements.new(elems)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def limit_size(limit)
|
|
112
|
+
Elements.new(@elems.map {|ty| ty.limit_size(limit) })
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def screen_name(scratch)
|
|
116
|
+
"*[#{ @elems.map {|ty| ty.screen_name(scratch) }.join(", ") }]"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def pretty_print(q)
|
|
120
|
+
q.group(9, "Elements[", "]") do
|
|
121
|
+
q.seplist(@elems) do |elem|
|
|
122
|
+
q.pp elem
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def consistent?(other, subst)
|
|
128
|
+
false if @elems.size != other.elems.size
|
|
129
|
+
@elems.zip(other.elems) do |ty0, ty1|
|
|
130
|
+
return false unless ty0.consistent?(ty1, subst)
|
|
131
|
+
end
|
|
132
|
+
return true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def substitute(subst, depth)
|
|
136
|
+
Elements.new(@elems.map {|ty| ty.substitute(subst, depth) })
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def [](idx)
|
|
140
|
+
@elems[idx]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def update(idx, ty)
|
|
144
|
+
Elements.new(Utils.array_update(@elems, idx, @elems[idx].union(ty)))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def union(other)
|
|
148
|
+
return self if self == other
|
|
149
|
+
elems = []
|
|
150
|
+
@elems.zip(other.elems) do |ty0, ty1|
|
|
151
|
+
elems << ty0.union(ty1)
|
|
152
|
+
end
|
|
153
|
+
Elements.new(elems)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
82
156
|
end
|
|
83
157
|
|
|
84
158
|
class LocalCell < Type
|
|
@@ -106,9 +180,9 @@ module TypeProf
|
|
|
106
180
|
visited[self] = true
|
|
107
181
|
elems = env.get_container_elem_types(@id)
|
|
108
182
|
if elems
|
|
109
|
-
elems = elems.
|
|
183
|
+
elems = elems.globalize(env, visited, depth - 1)
|
|
110
184
|
else
|
|
111
|
-
elems = [] # XXX
|
|
185
|
+
elems = Cell::Elements.new([]) # XXX
|
|
112
186
|
end
|
|
113
187
|
Cell.new(elems, @base_type)
|
|
114
188
|
end
|
|
@@ -151,7 +225,7 @@ module TypeProf
|
|
|
151
225
|
return env, Type.any if depth <= 0
|
|
152
226
|
alloc_site = alloc_site.add_id(:ary)
|
|
153
227
|
env, elems = @elems.localize(env, alloc_site, depth - 1)
|
|
154
|
-
env.
|
|
228
|
+
env.deploy_type(LocalArray, alloc_site, elems, @base_type)
|
|
155
229
|
end
|
|
156
230
|
|
|
157
231
|
def limit_size(limit)
|
|
@@ -196,8 +270,7 @@ module TypeProf
|
|
|
196
270
|
|
|
197
271
|
attr_reader :lead_tys, :rest_ty
|
|
198
272
|
|
|
199
|
-
def to_local_type(id)
|
|
200
|
-
base_ty = Type::Instance.new(Type::Builtin[:ary])
|
|
273
|
+
def to_local_type(id, base_ty)
|
|
201
274
|
Type::LocalArray.new(id, base_ty)
|
|
202
275
|
end
|
|
203
276
|
|
|
@@ -265,6 +338,11 @@ module TypeProf
|
|
|
265
338
|
@lead_tys.inject(@rest_ty) {|ty1, ty2| ty1.union(ty2) } #.union(Type.nil) # is this needed?
|
|
266
339
|
end
|
|
267
340
|
|
|
341
|
+
def squash_or_any
|
|
342
|
+
ty = squash
|
|
343
|
+
ty == Type.bot ? Type.any : ty
|
|
344
|
+
end
|
|
345
|
+
|
|
268
346
|
def [](idx)
|
|
269
347
|
if idx >= 0
|
|
270
348
|
if idx < @lead_tys.size
|
|
@@ -463,7 +541,7 @@ module TypeProf
|
|
|
463
541
|
return env, Type.any if depth <= 0
|
|
464
542
|
alloc_site = alloc_site.add_id(:hash)
|
|
465
543
|
env, elems = @elems.localize(env, alloc_site, depth - 1)
|
|
466
|
-
env.
|
|
544
|
+
env.deploy_type(LocalHash, alloc_site, elems, @base_type)
|
|
467
545
|
end
|
|
468
546
|
|
|
469
547
|
def limit_size(limit)
|
|
@@ -515,8 +593,7 @@ module TypeProf
|
|
|
515
593
|
|
|
516
594
|
attr_reader :map_tys
|
|
517
595
|
|
|
518
|
-
def to_local_type(id)
|
|
519
|
-
base_ty = Type::Instance.new(Type::Builtin[:hash])
|
|
596
|
+
def to_local_type(id, base_ty)
|
|
520
597
|
Type::LocalHash.new(id, base_ty)
|
|
521
598
|
end
|
|
522
599
|
|
data/lib/typeprof/export.rb
CHANGED
|
@@ -81,141 +81,148 @@ module TypeProf
|
|
|
81
81
|
class RubySignatureExporter
|
|
82
82
|
def initialize(
|
|
83
83
|
scratch,
|
|
84
|
-
class_defs, iseq_method_to_ctxs
|
|
84
|
+
class_defs, iseq_method_to_ctxs
|
|
85
85
|
)
|
|
86
86
|
@scratch = scratch
|
|
87
87
|
@class_defs = class_defs
|
|
88
88
|
@iseq_method_to_ctxs = iseq_method_to_ctxs
|
|
89
|
-
@sig_fargs = sig_fargs
|
|
90
|
-
@sig_ret = sig_ret
|
|
91
|
-
@yields = yields
|
|
92
89
|
end
|
|
93
90
|
|
|
94
|
-
def
|
|
95
|
-
|
|
91
|
+
def conv_class(namespace, class_def, inner_classes)
|
|
92
|
+
@scratch.namespace = namespace
|
|
96
93
|
|
|
97
|
-
|
|
94
|
+
if class_def.superclass
|
|
95
|
+
omit = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
|
96
|
+
superclass = omit ? nil : @scratch.get_class_name(@class_defs[class_def.superclass].klass_obj)
|
|
97
|
+
end
|
|
98
98
|
|
|
99
|
-
@
|
|
100
|
-
included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
|
|
101
|
-
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
|
102
|
-
mod_def.name
|
|
103
|
-
end
|
|
99
|
+
@scratch.namespace = class_def.name
|
|
104
100
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
consts = {}
|
|
102
|
+
class_def.consts.each do |name, (ty, absolute_path)|
|
|
103
|
+
next if ty.is_a?(Type::Class)
|
|
104
|
+
next if !absolute_path || Config.check_dir_filter(absolute_path) == :exclude
|
|
105
|
+
consts[name] = ty.screen_name(@scratch)
|
|
106
|
+
end
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
method_name =
|
|
139
|
-
|
|
140
|
-
method_name
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
method_name, sigs = mdef.rbs_source
|
|
153
|
-
explicit_methods[method_name] = sigs
|
|
108
|
+
included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
|
|
109
|
+
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
|
110
|
+
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
extended_mods = class_def.modules[true].filter_map do |mod_def, absolute_paths|
|
|
114
|
+
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
|
115
|
+
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
explicit_methods = {}
|
|
119
|
+
iseq_methods = {}
|
|
120
|
+
attr_methods = {}
|
|
121
|
+
ivars = class_def.ivars.dump
|
|
122
|
+
cvars = class_def.cvars.dump
|
|
123
|
+
|
|
124
|
+
class_def.methods.each do |(singleton, mid), mdefs|
|
|
125
|
+
mdefs.each do |mdef|
|
|
126
|
+
case mdef
|
|
127
|
+
when ISeqMethodDef
|
|
128
|
+
ctxs = @iseq_method_to_ctxs[mdef]
|
|
129
|
+
next unless ctxs
|
|
130
|
+
|
|
131
|
+
ctxs.each do |ctx|
|
|
132
|
+
next if mid != ctx.mid
|
|
133
|
+
next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
|
134
|
+
|
|
135
|
+
method_name = ctx.mid
|
|
136
|
+
method_name = "self.#{ method_name }" if singleton
|
|
137
|
+
|
|
138
|
+
iseq_methods[method_name] ||= []
|
|
139
|
+
iseq_methods[method_name] << @scratch.show_method_signature(ctx)
|
|
140
|
+
end
|
|
141
|
+
when AttrMethodDef
|
|
142
|
+
next if Config.check_dir_filter(mdef.absolute_path) == :exclude
|
|
143
|
+
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
|
144
|
+
method_name = mid
|
|
145
|
+
method_name = "self.#{ mid }" if singleton
|
|
146
|
+
method_name = [method_name, :"@#{ mid }" != mdef.ivar]
|
|
147
|
+
if attr_methods[method_name]
|
|
148
|
+
if attr_methods[method_name][0] != mdef.kind
|
|
149
|
+
attr_methods[method_name][0] = :accessor
|
|
154
150
|
end
|
|
151
|
+
else
|
|
152
|
+
entry = ivars[[singleton, mdef.ivar]]
|
|
153
|
+
ty = entry ? entry.type : Type.any
|
|
154
|
+
attr_methods[method_name] = [mdef.kind, ty.screen_name(@scratch)]
|
|
155
|
+
end
|
|
156
|
+
when TypedMethodDef
|
|
157
|
+
if mdef.rbs_source
|
|
158
|
+
method_name, sigs = mdef.rbs_source
|
|
159
|
+
explicit_methods[method_name] = sigs
|
|
155
160
|
end
|
|
156
161
|
end
|
|
157
162
|
end
|
|
163
|
+
end
|
|
158
164
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
cvars = cvars.map do |var, entry|
|
|
169
|
-
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
|
170
|
-
[var, entry.type.screen_name(@scratch), entry.rbs_declared]
|
|
171
|
-
end
|
|
165
|
+
ivars = ivars.map do |(singleton, var), entry|
|
|
166
|
+
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
|
167
|
+
ty = entry.type
|
|
168
|
+
next unless var.to_s.start_with?("@")
|
|
169
|
+
var = "self.#{ var }" if singleton
|
|
170
|
+
next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
|
|
171
|
+
[var, ty.screen_name(@scratch), entry.rbs_declared]
|
|
172
|
+
end.compact
|
|
172
173
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
cvars = cvars.map do |var, entry|
|
|
175
|
+
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
|
176
|
+
[var, entry.type.screen_name(@scratch), entry.rbs_declared]
|
|
177
|
+
end
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
|
|
180
|
+
return nil if consts.empty? && included_mods.empty? && extended_mods.empty? && ivars.empty? && cvars.empty? && iseq_methods.empty? && attr_methods.empty? && inner_classes.empty?
|
|
181
|
+
end
|
|
179
182
|
|
|
180
|
-
|
|
181
|
-
omit = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
|
182
|
-
superclass = omit ? "" : " < #{ @class_defs[class_def.superclass].name }"
|
|
183
|
-
end
|
|
183
|
+
@scratch.namespace = nil
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
ivars
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
185
|
+
ClassData.new(
|
|
186
|
+
kind: class_def.kind,
|
|
187
|
+
name: class_def.name,
|
|
188
|
+
superclass: superclass,
|
|
189
|
+
consts: consts,
|
|
190
|
+
included_mods: included_mods,
|
|
191
|
+
extended_mods: extended_mods,
|
|
192
|
+
ivars: ivars,
|
|
193
|
+
cvars: cvars,
|
|
194
|
+
attr_methods: attr_methods,
|
|
195
|
+
explicit_methods: explicit_methods,
|
|
196
|
+
iseq_methods: iseq_methods,
|
|
197
|
+
inner_classes: inner_classes,
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
ClassData = Struct.new(:kind, :name, :superclass, :consts, :included_mods, :extended_mods, :ivars, :cvars, :attr_methods, :explicit_methods, :iseq_methods, :inner_classes, keyword_init: true)
|
|
202
|
+
|
|
203
|
+
def show(stat_eps, output)
|
|
204
|
+
# make the class hierarchy
|
|
205
|
+
root = {}
|
|
206
|
+
@class_defs.each_value do |class_def|
|
|
207
|
+
h = root
|
|
208
|
+
class_def.name.each do |name|
|
|
209
|
+
h = h[name] ||= {}
|
|
210
210
|
end
|
|
211
|
-
|
|
211
|
+
h[:class_def] = class_def
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
+
hierarchy = build_class_hierarchy([], root)
|
|
215
|
+
|
|
216
|
+
output.puts "# Classes" # and Modules
|
|
217
|
+
|
|
218
|
+
show_class_hierarchy(0, hierarchy, output, true)
|
|
219
|
+
|
|
214
220
|
if ENV["TP_STAT"]
|
|
215
221
|
output.puts ""
|
|
216
222
|
output.puts "# TypeProf statistics:"
|
|
217
223
|
output.puts "# %d execution points" % stat_eps.size
|
|
218
224
|
end
|
|
225
|
+
|
|
219
226
|
if ENV["TP_COVERAGE"]
|
|
220
227
|
coverage = {}
|
|
221
228
|
stat_eps.each do |ep|
|
|
@@ -227,5 +234,75 @@ module TypeProf
|
|
|
227
234
|
File.binwrite("typeprof-analysis-coverage.dump", Marshal.dump(coverage))
|
|
228
235
|
end
|
|
229
236
|
end
|
|
237
|
+
|
|
238
|
+
def build_class_hierarchy(namespace, hierarchy)
|
|
239
|
+
hierarchy.map do |name, h|
|
|
240
|
+
class_def = h.delete(:class_def)
|
|
241
|
+
class_data = conv_class(namespace, class_def, build_class_hierarchy(namespace + [name], h))
|
|
242
|
+
class_data
|
|
243
|
+
end.compact
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def show_class_hierarchy(depth, hierarchy, output, first)
|
|
247
|
+
hierarchy.each do |class_data|
|
|
248
|
+
output.puts unless first
|
|
249
|
+
first = false
|
|
250
|
+
|
|
251
|
+
show_class_data(depth, class_data, output)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def show_const(namespace, path)
|
|
256
|
+
return path.last.to_s if namespace == path
|
|
257
|
+
i = 0
|
|
258
|
+
i += 1 while namespace[i] && namespace[i] == path[i]
|
|
259
|
+
path[i..].join("::")
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def show_class_data(depth, class_data, output)
|
|
263
|
+
indent = " " * depth
|
|
264
|
+
name = class_data.name.last
|
|
265
|
+
superclass = " < " + class_data.superclass if class_data.superclass
|
|
266
|
+
output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
|
|
267
|
+
first = true
|
|
268
|
+
class_data.consts.each do |name, ty|
|
|
269
|
+
output.puts indent + " #{ name } : #{ ty }"
|
|
270
|
+
first = false
|
|
271
|
+
end
|
|
272
|
+
class_data.included_mods.sort.each do |mod|
|
|
273
|
+
output.puts indent + " include #{ mod }"
|
|
274
|
+
first = false
|
|
275
|
+
end
|
|
276
|
+
class_data.extended_mods.sort.each do |mod|
|
|
277
|
+
output.puts indent + " extend #{ mod }"
|
|
278
|
+
first = false
|
|
279
|
+
end
|
|
280
|
+
class_data.ivars.each do |var, ty, rbs_declared|
|
|
281
|
+
s = rbs_declared ? "# " : " "
|
|
282
|
+
output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
|
|
283
|
+
first = false
|
|
284
|
+
end
|
|
285
|
+
class_data.cvars.each do |var, ty, rbs_declared|
|
|
286
|
+
s = rbs_declared ? "# " : " "
|
|
287
|
+
output.puts indent + s + "#{ var } : #{ ty }"
|
|
288
|
+
first = false
|
|
289
|
+
end
|
|
290
|
+
class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
|
|
291
|
+
output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" } : #{ ty }"
|
|
292
|
+
first = false
|
|
293
|
+
end
|
|
294
|
+
class_data.explicit_methods.each do |method_name, sigs|
|
|
295
|
+
sigs = sigs.sort.join("\n" + indent + "#" + " " * (method_name.size + 6) + "| ")
|
|
296
|
+
output.puts indent + "# def #{ method_name } : #{ sigs }"
|
|
297
|
+
first = false
|
|
298
|
+
end
|
|
299
|
+
class_data.iseq_methods.each do |method_name, sigs|
|
|
300
|
+
sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
|
|
301
|
+
output.puts indent + " def #{ method_name } : #{ sigs }"
|
|
302
|
+
first = false
|
|
303
|
+
end
|
|
304
|
+
show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
|
|
305
|
+
output.puts indent + "end"
|
|
306
|
+
end
|
|
230
307
|
end
|
|
231
308
|
end
|