typeprof 0.9.1 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -1
- data/Gemfile.lock +6 -5
- data/doc/demo.md +2 -2
- data/doc/todo.md +133 -0
- data/lib/typeprof/analyzer.rb +163 -77
- data/lib/typeprof/block.rb +39 -4
- data/lib/typeprof/builtin.rb +195 -70
- data/lib/typeprof/cli.rb +7 -0
- data/lib/typeprof/config.rb +30 -14
- data/lib/typeprof/container-type.rb +24 -0
- data/lib/typeprof/export.rb +134 -74
- data/lib/typeprof/import.rb +87 -39
- data/lib/typeprof/iseq.rb +23 -4
- data/lib/typeprof/method.rb +29 -7
- data/lib/typeprof/type.rb +75 -13
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +4 -4
- data/smoke/alias2.rb +3 -1
- data/smoke/arguments.rb +2 -2
- data/smoke/arguments2.rb +5 -5
- data/smoke/array-each.rb +1 -1
- data/smoke/array-each3.rb +1 -1
- data/smoke/array-map.rb +1 -1
- data/smoke/array-map2.rb +1 -1
- data/smoke/array-map3.rb +3 -3
- data/smoke/array-mul.rb +2 -2
- data/smoke/array-plus1.rb +1 -1
- data/smoke/array-plus2.rb +1 -0
- data/smoke/array-range-aref.rb +11 -11
- data/smoke/array-replace.rb +1 -1
- data/smoke/array1.rb +5 -5
- data/smoke/array10.rb +1 -1
- data/smoke/array11.rb +1 -1
- data/smoke/array12.rb +1 -1
- data/smoke/array14.rb +1 -1
- data/smoke/array15.rb +1 -1
- data/smoke/array2.rb +2 -2
- data/smoke/array3.rb +1 -0
- data/smoke/array6.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +1 -1
- data/smoke/attr-module.rb +1 -0
- data/smoke/attr-vis.rb +43 -0
- data/smoke/attr-vis.rbs +4 -0
- data/smoke/attr.rb +2 -2
- data/smoke/block-ambiguous.rb +4 -4
- data/smoke/block-args1-rest.rb +6 -5
- data/smoke/block-args1.rb +5 -5
- data/smoke/block-args2-rest.rb +6 -5
- data/smoke/block-args2.rb +5 -5
- data/smoke/block-args3-rest.rb +7 -6
- data/smoke/block-args3.rb +6 -6
- data/smoke/block-blockarg.rb +3 -3
- data/smoke/block-kwarg.rb +4 -4
- data/smoke/block1.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/block11.rb +2 -2
- data/smoke/block2.rb +1 -1
- data/smoke/block3.rb +1 -1
- data/smoke/block5.rb +1 -0
- data/smoke/block_given.rb +37 -0
- data/smoke/class_eval.rb +22 -0
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/constant2.rb +3 -2
- data/smoke/context-sensitive1.rb +1 -1
- data/smoke/cvar.rb +3 -2
- data/smoke/define_method.rb +2 -2
- data/smoke/define_method3.rb +1 -0
- data/smoke/define_method4.rb +1 -1
- data/smoke/define_method6.rb +19 -0
- data/smoke/define_method7.rb +18 -0
- data/smoke/demo.rb +6 -6
- data/smoke/demo1.rb +1 -1
- data/smoke/demo11.rb +1 -1
- data/smoke/demo2.rb +1 -1
- data/smoke/demo3.rb +1 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +2 -1
- data/smoke/demo7.rb +1 -1
- data/smoke/demo9.rb +1 -0
- data/smoke/dummy-execution1.rb +1 -1
- data/smoke/dummy-execution2.rb +1 -1
- data/smoke/dummy_element.rb +1 -1
- data/smoke/ensure1.rb +1 -1
- data/smoke/enum_for.rb +15 -0
- data/smoke/enum_for2.rb +17 -0
- data/smoke/extended.rb +38 -0
- data/smoke/fib.rb +2 -2
- data/smoke/flow1.rb +1 -1
- data/smoke/flow10.rb +17 -0
- data/smoke/flow2.rb +1 -1
- data/smoke/flow3.rb +1 -1
- data/smoke/flow5.rb +1 -1
- data/smoke/flow6.rb +1 -1
- data/smoke/flow7.rb +1 -1
- data/smoke/flow8.rb +1 -1
- data/smoke/flow9.rb +1 -1
- data/smoke/function.rb +1 -1
- data/smoke/gvar.rb +1 -1
- data/smoke/gvar2.rb +1 -1
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/included.rb +38 -0
- data/smoke/inheritance.rb +4 -4
- data/smoke/inherited.rb +26 -0
- data/smoke/initialize.rb +3 -2
- data/smoke/instance_eval.rb +2 -2
- data/smoke/instance_eval4.rb +12 -0
- data/smoke/int_times.rb +1 -1
- data/smoke/integer.rb +1 -1
- data/smoke/ivar.rb +3 -2
- data/smoke/ivar2.rb +2 -2
- data/smoke/ivar3.rb +2 -1
- data/smoke/ivar4.rb +1 -0
- data/smoke/kernel-class.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/kwrest.rb +1 -0
- data/smoke/kwsplat1.rb +2 -2
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/manual-rbs.rb +2 -1
- data/smoke/manual-rbs3.rb +1 -0
- data/smoke/method_in_branch.rb +1 -1
- data/smoke/method_missing.rb +4 -3
- data/smoke/module3.rb +1 -1
- data/smoke/module4.rb +1 -0
- data/smoke/module5.rb +1 -1
- data/smoke/module_function1.rb +3 -2
- data/smoke/module_function2.rb +3 -2
- data/smoke/multiple-include.rb +1 -0
- data/smoke/next1.rb +1 -1
- data/smoke/object-send1.rb +3 -3
- data/smoke/optional1.rb +1 -1
- data/smoke/optional2.rb +1 -1
- data/smoke/optional3.rb +1 -1
- data/smoke/parameterizedd-self.rb +2 -1
- data/smoke/prepend1.rb +33 -0
- data/smoke/prepend2.rb +10 -0
- data/smoke/prepend2.rbs +9 -0
- data/smoke/primitive_method.rb +19 -0
- data/smoke/proc4.rb +1 -1
- data/smoke/public.rb +4 -0
- data/smoke/range.rb +1 -1
- data/smoke/rbs-attr.rb +2 -2
- data/smoke/rbs-proc2.rb +1 -1
- data/smoke/rbs-proc3.rb +1 -1
- data/smoke/rbs-tyvar4.rb +3 -2
- data/smoke/rbs-tyvar6.rb +3 -3
- data/smoke/redo1.rb +1 -1
- data/smoke/redo2.rb +1 -1
- data/smoke/rescue1.rb +1 -1
- data/smoke/rescue2.rb +1 -1
- data/smoke/rescue3.rb +1 -0
- data/smoke/rescue4.rb +1 -1
- data/smoke/respond_to.rb +1 -1
- data/smoke/rest1.rb +2 -2
- data/smoke/rest2.rb +1 -1
- data/smoke/rest3.rb +6 -6
- data/smoke/rest4.rb +2 -2
- data/smoke/rest5.rb +1 -1
- data/smoke/rest6.rb +1 -1
- data/smoke/retry1.rb +2 -2
- data/smoke/simple.rb +12 -0
- data/smoke/step.rb +3 -3
- data/smoke/struct-keyword_init.rb +6 -16
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +1 -1
- data/smoke/struct3.rb +1 -1
- data/smoke/struct4.rb +1 -1
- data/smoke/struct5.rb +2 -2
- data/smoke/struct6.rb +2 -2
- data/smoke/struct7.rb +1 -1
- data/smoke/super1.rb +4 -4
- data/smoke/super3.rb +3 -2
- data/smoke/super4.rb +7 -5
- data/smoke/super5.rb +6 -4
- data/smoke/symbol-proc-attr.rb +1 -1
- data/smoke/tap1.rb +2 -2
- data/smoke/toplevel.rb +1 -1
- data/smoke/type_var.rb +3 -3
- data/smoke/user-demo.rb +1 -1
- data/smoke/wrong-extend.rb +1 -0
- data/smoke/wrong-include.rb +1 -0
- data/smoke/wrong-include2.rb +1 -1
- data/testbed/goodcheck-Gemfile.lock +1 -1
- data/typeprof.gemspec +1 -1
- metadata +24 -5
data/lib/typeprof/cli.rb
CHANGED
@@ -20,6 +20,7 @@ module TypeProf
|
|
20
20
|
options = {}
|
21
21
|
dir_filter = nil
|
22
22
|
gem_rbs_features = []
|
23
|
+
gem_repo_dirs = []
|
23
24
|
show_version = false
|
24
25
|
max_sec = max_iter = nil
|
25
26
|
|
@@ -31,6 +32,7 @@ module TypeProf
|
|
31
32
|
opt.on("--version", "Display typeprof version") { show_version = true }
|
32
33
|
opt.on("-I DIR", "Add DIR to the load/require path") {|v| $LOAD_PATH << v }
|
33
34
|
opt.on("-r FEATURE", "Require RBS of the FEATURE gem") {|v| gem_rbs_features << v }
|
35
|
+
opt.on("--repo DIR", "Add DIR to the RBS repository") {|v| gem_repo_dirs << v }
|
34
36
|
|
35
37
|
opt.separator ""
|
36
38
|
opt.separator "Analysis output options:"
|
@@ -46,8 +48,12 @@ module TypeProf
|
|
46
48
|
dir_filter ||= ConfigData::DEFAULT_DIR_FILTER
|
47
49
|
dir_filter << [:exclude, File.expand_path(dir)]
|
48
50
|
end
|
51
|
+
opt.on("--exclude-untyped", "Exclude (comment out) all entries including untyped") {|v| options[:exclude_untyped] = v }
|
52
|
+
opt.on("--[no-]show-typeprof-version", "Display TypeProf version in a header") {|v| options[:show_typeprof_version] = v }
|
49
53
|
opt.on("--[no-]show-errors", "Display possible errors found during the analysis") {|v| options[:show_errors] = v }
|
50
54
|
opt.on("--[no-]show-untyped", "Display \"Foo | untyped\" instead of \"Foo\"") {|v| options[:show_untyped] = v }
|
55
|
+
opt.on("--[no-]show-parameter-names", "Display parameter names for methods") {|v| options[:show_parameter_names] = v }
|
56
|
+
opt.on("--[no-]show-source-locations", "Display definition source locations for methods") {|v| options[:show_source_locations] = v }
|
51
57
|
|
52
58
|
opt.separator ""
|
53
59
|
opt.separator "Analysis limit options:"
|
@@ -85,6 +91,7 @@ module TypeProf
|
|
85
91
|
rbs_files: rbs_files,
|
86
92
|
output: output,
|
87
93
|
gem_rbs_features: gem_rbs_features,
|
94
|
+
gem_repo_dirs: gem_repo_dirs,
|
88
95
|
verbose: verbose,
|
89
96
|
dir_filter: dir_filter,
|
90
97
|
max_sec: max_sec,
|
data/lib/typeprof/config.rb
CHANGED
@@ -6,6 +6,7 @@ module TypeProf
|
|
6
6
|
:rbs_files,
|
7
7
|
:output,
|
8
8
|
:gem_rbs_features,
|
9
|
+
:gem_repo_dirs,
|
9
10
|
:verbose,
|
10
11
|
:dir_filter,
|
11
12
|
:max_iter,
|
@@ -14,17 +15,29 @@ module TypeProf
|
|
14
15
|
keyword_init: true
|
15
16
|
)
|
16
17
|
|
18
|
+
class TypeProfError < StandardError
|
19
|
+
def report(output)
|
20
|
+
output.puts "# Analysis Error"
|
21
|
+
output.puts message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
17
25
|
class ConfigData
|
18
26
|
def initialize(**opt)
|
19
27
|
opt[:output] ||= $stdout
|
20
28
|
opt[:gem_rbs_features] ||= []
|
29
|
+
opt[:gem_repo_dirs] ||= []
|
21
30
|
opt[:dir_filter] ||= DEFAULT_DIR_FILTER
|
22
31
|
opt[:verbose] ||= 0
|
23
32
|
opt[:options] ||= {}
|
24
33
|
opt[:options] = {
|
34
|
+
exclude_untyped: false,
|
35
|
+
show_typeprof_version: true,
|
25
36
|
show_indicator: true,
|
26
37
|
show_untyped: false,
|
27
38
|
show_errors: false,
|
39
|
+
show_parameter_names: true,
|
40
|
+
show_source_locations: false,
|
28
41
|
stub_execution: true,
|
29
42
|
type_depth_limit: 5,
|
30
43
|
stackprof: nil,
|
@@ -67,9 +80,19 @@ module TypeProf
|
|
67
80
|
Import.import_library(scratch, feature)
|
68
81
|
end
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
rbs_files = []
|
84
|
+
rbs_codes = []
|
85
|
+
Config.rbs_files.each do |rbs|
|
86
|
+
if rbs.is_a?(Array) # [String name, String content]
|
87
|
+
rbs_codes << rbs
|
88
|
+
else
|
89
|
+
rbs_files << rbs
|
90
|
+
end
|
91
|
+
end
|
92
|
+
Import.import_rbs_files(scratch, rbs_files)
|
93
|
+
rbs_codes.each do |name, content|
|
94
|
+
Import.import_rbs_code(scratch, name, content)
|
95
|
+
end
|
73
96
|
|
74
97
|
Config.rb_files.each do |rb|
|
75
98
|
if rb.is_a?(Array) # [String name, String content]
|
@@ -77,17 +100,7 @@ module TypeProf
|
|
77
100
|
else
|
78
101
|
iseq = ISeq.compile(rb)
|
79
102
|
end
|
80
|
-
|
81
|
-
scratch.merge_env(ep, env)
|
82
|
-
scratch.add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
|
83
|
-
end
|
84
|
-
|
85
|
-
Config.rbs_files.each do |rbs|
|
86
|
-
if rbs.is_a?(Array) # [String name, String content]
|
87
|
-
Import.import_rbs_code(scratch, *rbs)
|
88
|
-
else
|
89
|
-
Import.import_rbs_file(scratch, rbs)
|
90
|
-
end
|
103
|
+
scratch.add_entrypoint(iseq)
|
91
104
|
end
|
92
105
|
|
93
106
|
result = scratch.type_profile
|
@@ -100,6 +113,9 @@ module TypeProf
|
|
100
113
|
end
|
101
114
|
end
|
102
115
|
|
116
|
+
rescue TypeProfError => exc
|
117
|
+
exc.report(Config.output)
|
118
|
+
|
103
119
|
ensure
|
104
120
|
if Config.options[:stackprof] && defined?(StackProf)
|
105
121
|
StackProf.stop
|
@@ -45,6 +45,12 @@ module TypeProf
|
|
45
45
|
Type::Cell.new(Type::Cell::Elements.new([Type.bot] * klass.type_params.size), base_type)
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
def include_untyped?(scratch)
|
50
|
+
return true if @base_type.include_untyped?(scratch)
|
51
|
+
return true if @elems.include_untyped?(scratch)
|
52
|
+
false
|
53
|
+
end
|
48
54
|
end
|
49
55
|
|
50
56
|
# The most basic container type for default type parameter class
|
@@ -196,6 +202,10 @@ module TypeProf
|
|
196
202
|
end
|
197
203
|
Elements.new(elems)
|
198
204
|
end
|
205
|
+
|
206
|
+
def include_untyped?(scratch)
|
207
|
+
return @elems.any? {|ty| ty.include_untyped?(scratch) }
|
208
|
+
end
|
199
209
|
end
|
200
210
|
end
|
201
211
|
|
@@ -531,6 +541,12 @@ module TypeProf
|
|
531
541
|
return rest_ary_ty, following_tys
|
532
542
|
end
|
533
543
|
end
|
544
|
+
|
545
|
+
def include_untyped?(scratch)
|
546
|
+
return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) }
|
547
|
+
return true if @rest_ty.include_untyped?(scratch)
|
548
|
+
false
|
549
|
+
end
|
534
550
|
end
|
535
551
|
end
|
536
552
|
|
@@ -790,6 +806,14 @@ module TypeProf
|
|
790
806
|
end
|
791
807
|
kw_tys
|
792
808
|
end
|
809
|
+
|
810
|
+
def include_untyped?(scratch)
|
811
|
+
@map_tys.each do |key, val|
|
812
|
+
return true if key.include_untyped?(scratch)
|
813
|
+
return true if val.include_untyped?(scratch)
|
814
|
+
end
|
815
|
+
false
|
816
|
+
end
|
793
817
|
end
|
794
818
|
end
|
795
819
|
|
data/lib/typeprof/export.rb
CHANGED
@@ -26,6 +26,10 @@ module TypeProf
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def show_message(terminated, output)
|
29
|
+
if Config.options[:show_typeprof_version]
|
30
|
+
output.puts "# TypeProf #{ VERSION }"
|
31
|
+
output.puts
|
32
|
+
end
|
29
33
|
if terminated
|
30
34
|
output.puts "# CAUTION: Type profiling was terminated prematurely because of the limitation"
|
31
35
|
output.puts
|
@@ -94,6 +98,10 @@ module TypeProf
|
|
94
98
|
if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
|
95
99
|
omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
96
100
|
superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
|
101
|
+
type_args = class_def.klass_obj.superclass_type_args
|
102
|
+
if type_args && !type_args.empty?
|
103
|
+
superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]"
|
104
|
+
end
|
97
105
|
end
|
98
106
|
|
99
107
|
@scratch.namespace = class_def.name
|
@@ -105,19 +113,20 @@ module TypeProf
|
|
105
113
|
consts[name] = ty.screen_name(@scratch)
|
106
114
|
end
|
107
115
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
+
modules = class_def.modules.to_h do |kind, mods|
|
117
|
+
mods = mods.to_h do |singleton, mods|
|
118
|
+
mods = mods.filter_map do |mod_def, _type_args, absolute_paths|
|
119
|
+
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
120
|
+
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
121
|
+
end
|
122
|
+
[singleton, mods]
|
123
|
+
end
|
124
|
+
[kind, mods]
|
116
125
|
end
|
117
126
|
|
118
|
-
|
119
|
-
|
120
|
-
|
127
|
+
visibilities = {}
|
128
|
+
source_locations = {}
|
129
|
+
methods = {}
|
121
130
|
ivars = class_def.ivars.dump
|
122
131
|
cvars = class_def.cvars.dump
|
123
132
|
|
@@ -128,36 +137,53 @@ module TypeProf
|
|
128
137
|
ctxs = @iseq_method_to_ctxs[mdef]
|
129
138
|
next unless ctxs
|
130
139
|
|
131
|
-
ctxs.
|
132
|
-
next if mid != ctx.mid
|
133
|
-
next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
140
|
+
ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
|
134
141
|
|
135
|
-
|
136
|
-
method_name = "self.#{ method_name }" if singleton
|
142
|
+
next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
137
143
|
|
138
|
-
|
139
|
-
|
140
|
-
|
144
|
+
method_name = mid
|
145
|
+
method_name = "self.#{ method_name }" if singleton
|
146
|
+
|
147
|
+
key = [:iseq, method_name]
|
148
|
+
visibilities[key] ||= mdef.pub_meth
|
149
|
+
source_locations[key] ||= ctx.iseq.source_location(0)
|
150
|
+
(methods[key] ||= []) << @scratch.show_method_signature(ctx)
|
151
|
+
when AliasMethodDef
|
152
|
+
alias_name, orig_name = mid, mdef.orig_mid
|
153
|
+
if singleton
|
154
|
+
alias_name = "self.#{ alias_name }"
|
155
|
+
orig_name = "self.#{ orig_name }"
|
141
156
|
end
|
157
|
+
key = [:alias, alias_name]
|
158
|
+
visibilities[key] ||= mdef.pub_meth
|
159
|
+
source_locations[key] ||= mdef.def_ep&.source_location
|
160
|
+
methods[key] = orig_name
|
142
161
|
when AttrMethodDef
|
143
|
-
next if !mdef.
|
162
|
+
next if !mdef.def_ep
|
163
|
+
absolute_path = mdef.def_ep.ctx.iseq.absolute_path
|
164
|
+
next if !absolute_path || Config.check_dir_filter(absolute_path) == :exclude
|
144
165
|
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
145
166
|
method_name = mid
|
146
167
|
method_name = "self.#{ mid }" if singleton
|
147
168
|
method_name = [method_name, :"@#{ mid }" != mdef.ivar]
|
148
|
-
|
149
|
-
|
150
|
-
|
169
|
+
key = [:attr, method_name]
|
170
|
+
visibilities[key] ||= mdef.pub_meth
|
171
|
+
source_locations[key] ||= mdef.def_ep.source_location
|
172
|
+
if methods[key]
|
173
|
+
if methods[key][0] != mdef.kind
|
174
|
+
methods[key][0] = :accessor
|
151
175
|
end
|
152
176
|
else
|
153
177
|
entry = ivars[[singleton, mdef.ivar]]
|
154
178
|
ty = entry ? entry.type : Type.any
|
155
|
-
|
179
|
+
methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
|
156
180
|
end
|
157
181
|
when TypedMethodDef
|
158
182
|
if mdef.rbs_source
|
159
183
|
method_name, sigs = mdef.rbs_source
|
160
|
-
|
184
|
+
key = [:rbs, method_name]
|
185
|
+
methods[key] = sigs
|
186
|
+
visibilities[key] ||= mdef.pub_meth
|
161
187
|
end
|
162
188
|
end
|
163
189
|
end
|
@@ -168,7 +194,7 @@ module TypeProf
|
|
168
194
|
ty = entry.type
|
169
195
|
next unless var.to_s.start_with?("@")
|
170
196
|
var = "self.#{ var }" if singleton
|
171
|
-
next if
|
197
|
+
next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]]
|
172
198
|
next if entry.rbs_declared
|
173
199
|
[var, ty.screen_name(@scratch)]
|
174
200
|
end.compact
|
@@ -180,7 +206,9 @@ module TypeProf
|
|
180
206
|
end.compact
|
181
207
|
|
182
208
|
if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
|
183
|
-
|
209
|
+
if methods.keys.all? {|type,| type == :rbs }
|
210
|
+
return nil if consts.empty? && modules[:before][true].empty? && modules[:before][false].empty? && modules[:after][true].empty? && modules[:after][false].empty? && ivars.empty? && cvars.empty? && inner_classes.empty?
|
211
|
+
end
|
184
212
|
end
|
185
213
|
|
186
214
|
@scratch.namespace = nil
|
@@ -190,18 +218,17 @@ module TypeProf
|
|
190
218
|
name: class_def.name,
|
191
219
|
superclass: superclass,
|
192
220
|
consts: consts,
|
193
|
-
|
194
|
-
extended_mods: extended_mods,
|
221
|
+
modules: modules,
|
195
222
|
ivars: ivars,
|
196
223
|
cvars: cvars,
|
197
|
-
|
198
|
-
|
199
|
-
|
224
|
+
methods: methods,
|
225
|
+
visibilities: visibilities,
|
226
|
+
source_locations: source_locations,
|
200
227
|
inner_classes: inner_classes,
|
201
228
|
)
|
202
229
|
end
|
203
230
|
|
204
|
-
ClassData = Struct.new(:kind, :name, :superclass, :consts, :
|
231
|
+
ClassData = Struct.new(:kind, :name, :superclass, :consts, :modules, :ivars, :cvars, :methods, :visibilities, :source_locations, :inner_classes, keyword_init: true)
|
205
232
|
|
206
233
|
def show(stat_eps, output)
|
207
234
|
# make the class hierarchy
|
@@ -218,7 +245,16 @@ module TypeProf
|
|
218
245
|
|
219
246
|
output.puts "# Classes" # and Modules
|
220
247
|
|
221
|
-
|
248
|
+
prev_nil = true
|
249
|
+
show_class_hierarchy(0, hierarchy).each do |line|
|
250
|
+
if line == nil
|
251
|
+
output.puts line unless prev_nil
|
252
|
+
prev_nil = true
|
253
|
+
else
|
254
|
+
output.puts line
|
255
|
+
prev_nil = false
|
256
|
+
end
|
257
|
+
end
|
222
258
|
|
223
259
|
if ENV["TP_STAT"]
|
224
260
|
output.puts ""
|
@@ -246,13 +282,13 @@ module TypeProf
|
|
246
282
|
end.compact
|
247
283
|
end
|
248
284
|
|
249
|
-
def show_class_hierarchy(depth, hierarchy
|
285
|
+
def show_class_hierarchy(depth, hierarchy)
|
286
|
+
lines = []
|
250
287
|
hierarchy.each do |class_data|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
show_class_data(depth, class_data, output)
|
288
|
+
lines << nil
|
289
|
+
lines.concat show_class_data(depth, class_data)
|
255
290
|
end
|
291
|
+
lines
|
256
292
|
end
|
257
293
|
|
258
294
|
def show_const(namespace, path)
|
@@ -262,53 +298,77 @@ module TypeProf
|
|
262
298
|
path[i..].join("::")
|
263
299
|
end
|
264
300
|
|
265
|
-
def show_class_data(depth, class_data
|
301
|
+
def show_class_data(depth, class_data)
|
266
302
|
indent = " " * depth
|
267
303
|
name = class_data.name.last
|
268
304
|
superclass = " < " + class_data.superclass if class_data.superclass
|
269
|
-
|
270
|
-
|
305
|
+
first_line = indent + "#{ class_data.kind } #{ name }#{ superclass }"
|
306
|
+
lines = []
|
271
307
|
class_data.consts.each do |name, ty|
|
272
|
-
|
273
|
-
first = false
|
274
|
-
end
|
275
|
-
class_data.included_mods.sort.each do |mod|
|
276
|
-
output.puts indent + " include #{ mod }"
|
277
|
-
first = false
|
308
|
+
lines << (indent + " #{ name }: #{ ty }")
|
278
309
|
end
|
279
|
-
class_data.
|
280
|
-
|
281
|
-
|
310
|
+
class_data.modules.each do |kind, mods|
|
311
|
+
mods.each do |singleton, mods|
|
312
|
+
case
|
313
|
+
when kind == :before && singleton then directive = nil
|
314
|
+
when kind == :before && !singleton then directive = "prepend"
|
315
|
+
when kind == :after && singleton then directive = "extend"
|
316
|
+
when kind == :after && !singleton then directive = "include"
|
317
|
+
end
|
318
|
+
mods.each do |mod|
|
319
|
+
lines << (indent + " #{ directive } #{ mod }") if directive
|
320
|
+
end
|
321
|
+
end
|
282
322
|
end
|
283
323
|
class_data.ivars.each do |var, ty|
|
284
|
-
|
285
|
-
first = false
|
324
|
+
lines << (indent + " #{ var }: #{ ty }") unless var.start_with?("_")
|
286
325
|
end
|
287
326
|
class_data.cvars.each do |var, ty|
|
288
|
-
|
289
|
-
first = false
|
327
|
+
lines << (indent + " #{ var }: #{ ty }")
|
290
328
|
end
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
329
|
+
lines << nil
|
330
|
+
prev_vis = true
|
331
|
+
class_data.methods.each do |key, arg|
|
332
|
+
vis = class_data.visibilities[key]
|
333
|
+
if prev_vis != vis
|
334
|
+
lines << nil
|
335
|
+
lines << (indent + " #{ vis ? "public" : "private" }")
|
336
|
+
prev_vis = vis
|
337
|
+
end
|
338
|
+
source_location = class_data.source_locations[key]
|
339
|
+
if Config.options[:show_source_locations] && source_location
|
340
|
+
lines << nil
|
341
|
+
lines << (indent + " # #{ source_location }")
|
342
|
+
end
|
343
|
+
type, (method_name, hidden) = key
|
344
|
+
case type
|
345
|
+
when :attr
|
346
|
+
kind, ty, untyped = *arg
|
347
|
+
exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
|
348
|
+
lines << (indent + "#{ exclude } attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
|
349
|
+
when :rbs
|
350
|
+
sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ")
|
351
|
+
lines << (indent + "# def #{ method_name }: #{ sigs }")
|
352
|
+
when :iseq
|
353
|
+
sigs = []
|
354
|
+
untyped = false
|
355
|
+
arg.each do |sig, untyped0|
|
356
|
+
sigs << sig
|
357
|
+
untyped ||= untyped0
|
358
|
+
end
|
359
|
+
sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
|
360
|
+
exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
|
361
|
+
lines << (indent + "#{ exclude } def #{ method_name }: #{ sigs }")
|
362
|
+
when :alias
|
363
|
+
orig_name = arg
|
364
|
+
lines << (indent + " alias #{ method_name } #{ orig_name }")
|
306
365
|
end
|
307
|
-
output.puts indent + " def #{ method_name }: #{ sigs }"
|
308
|
-
first = false
|
309
366
|
end
|
310
|
-
show_class_hierarchy(depth + 1, class_data.inner_classes
|
311
|
-
|
367
|
+
lines.concat show_class_hierarchy(depth + 1, class_data.inner_classes)
|
368
|
+
lines.shift until lines.empty? || lines.first
|
369
|
+
lines.pop until lines.empty? || lines.last
|
370
|
+
lines.unshift first_line
|
371
|
+
lines << (indent + "end")
|
312
372
|
end
|
313
373
|
end
|
314
374
|
end
|