typeprof 0.9.2 → 0.14.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/.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 +201 -104
- data/lib/typeprof/block.rb +39 -4
- data/lib/typeprof/builtin.rb +217 -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 +116 -41
- 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/break4.rb +17 -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/flow11.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 +1 -0
- data/smoke/manual-rbs3.rb +1 -0
- 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 +1 -1
- 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 +25 -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
|