typeprof 0.21.11 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -31
- data/bin/typeprof +5 -0
- data/doc/doc.ja.md +134 -0
- data/doc/doc.md +136 -0
- data/lib/typeprof/cli/cli.rb +180 -0
- data/lib/typeprof/cli.rb +2 -133
- data/lib/typeprof/code_range.rb +112 -0
- data/lib/typeprof/core/ast/base.rb +263 -0
- data/lib/typeprof/core/ast/call.rb +251 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +432 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +335 -0
- data/lib/typeprof/core/ast/misc.rb +263 -0
- data/lib/typeprof/core/ast/module.rb +123 -0
- data/lib/typeprof/core/ast/pattern.rb +140 -0
- data/lib/typeprof/core/ast/sig_decl.rb +471 -0
- data/lib/typeprof/core/ast/sig_type.rb +663 -0
- data/lib/typeprof/core/ast/value.rb +319 -0
- data/lib/typeprof/core/ast/variable.rb +315 -0
- data/lib/typeprof/core/ast.rb +472 -0
- data/lib/typeprof/core/builtin.rb +146 -0
- data/lib/typeprof/core/env/method.rb +137 -0
- data/lib/typeprof/core/env/method_entity.rb +55 -0
- data/lib/typeprof/core/env/module_entity.rb +408 -0
- data/lib/typeprof/core/env/static_read.rb +155 -0
- data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
- data/lib/typeprof/core/env/value_entity.rb +32 -0
- data/lib/typeprof/core/env.rb +360 -0
- data/lib/typeprof/core/graph/box.rb +991 -0
- data/lib/typeprof/core/graph/change_set.rb +224 -0
- data/lib/typeprof/core/graph/filter.rb +155 -0
- data/lib/typeprof/core/graph/vertex.rb +222 -0
- data/lib/typeprof/core/graph.rb +3 -0
- data/lib/typeprof/core/service.rb +522 -0
- data/lib/typeprof/core/type.rb +348 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +32 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +430 -0
- data/lib/typeprof/lsp/server.rb +177 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +61 -0
- data/lib/typeprof/lsp.rb +4 -907
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +4 -18
- data/typeprof.gemspec +5 -7
- metadata +48 -35
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/main.yml +0 -39
- data/.gitignore +0 -9
- data/Gemfile +0 -17
- data/Gemfile.lock +0 -41
- data/Rakefile +0 -10
- data/exe/typeprof +0 -10
- data/lib/typeprof/analyzer.rb +0 -2598
- data/lib/typeprof/arguments.rb +0 -414
- data/lib/typeprof/block.rb +0 -176
- data/lib/typeprof/builtin.rb +0 -893
- data/lib/typeprof/code-range.rb +0 -177
- data/lib/typeprof/config.rb +0 -158
- data/lib/typeprof/container-type.rb +0 -912
- data/lib/typeprof/export.rb +0 -589
- data/lib/typeprof/import.rb +0 -852
- data/lib/typeprof/insns-def.rb +0 -65
- data/lib/typeprof/iseq.rb +0 -864
- data/lib/typeprof/method.rb +0 -355
- data/lib/typeprof/type.rb +0 -1140
- data/lib/typeprof/utils.rb +0 -212
- data/tools/coverage.rb +0 -14
- data/tools/setup-insns-def.rb +0 -30
- data/typeprof-lsp +0 -3
data/lib/typeprof/export.rb
DELETED
@@ -1,589 +0,0 @@
|
|
1
|
-
module TypeProf
|
2
|
-
module Reporters
|
3
|
-
module_function
|
4
|
-
|
5
|
-
def generate_analysis_trace(state, visited, backward_edge)
|
6
|
-
return nil if visited[state]
|
7
|
-
visited[state] = true
|
8
|
-
prev_states = backward_edges[state]
|
9
|
-
if prev_states
|
10
|
-
prev_states.each_key do |pstate|
|
11
|
-
trace = generate_analysis_trace(pstate, visited, backward_edge)
|
12
|
-
return [state] + trace if trace
|
13
|
-
end
|
14
|
-
nil
|
15
|
-
else
|
16
|
-
[]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def filter_backtrace(trace)
|
21
|
-
ntrace = [trace.first]
|
22
|
-
trace.each_cons(2) do |ep1, ep2|
|
23
|
-
ntrace << ep2 if ep1.ctx != ep2.ctx
|
24
|
-
end
|
25
|
-
ntrace
|
26
|
-
end
|
27
|
-
|
28
|
-
def show_message(terminated, output)
|
29
|
-
if Config.current.options[:show_typeprof_version]
|
30
|
-
output.puts "# TypeProf #{ VERSION }"
|
31
|
-
output.puts
|
32
|
-
end
|
33
|
-
if terminated
|
34
|
-
output.puts "# CAUTION: Type profiling was terminated prematurely because of the limitation"
|
35
|
-
output.puts
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def show_error(errors, backward_edge, output)
|
40
|
-
return if errors.empty?
|
41
|
-
return unless Config.current.options[:show_errors]
|
42
|
-
|
43
|
-
output.puts "# Errors"
|
44
|
-
errors.each do |ep, msg|
|
45
|
-
if ENV["TP_DETAIL"]
|
46
|
-
backtrace = filter_backtrace(generate_analysis_trace(ep, {}, backward_edge))
|
47
|
-
else
|
48
|
-
backtrace = [ep]
|
49
|
-
end
|
50
|
-
loc, *backtrace = backtrace.map do |ep|
|
51
|
-
ep&.source_location
|
52
|
-
end
|
53
|
-
output.puts "#{ loc }: #{ msg }"
|
54
|
-
backtrace.each do |loc|
|
55
|
-
output.puts " from #{ loc }"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
output.puts
|
59
|
-
end
|
60
|
-
|
61
|
-
def show_reveal_types(scratch, reveal_types, output)
|
62
|
-
return if reveal_types.empty?
|
63
|
-
|
64
|
-
output.puts "# Revealed types"
|
65
|
-
reveal_types.each do |source_location, ty|
|
66
|
-
output.puts "# #{ source_location } #=> #{ ty.screen_name(scratch) }"
|
67
|
-
end
|
68
|
-
output.puts
|
69
|
-
end
|
70
|
-
|
71
|
-
def show_gvars(scratch, gvars, output)
|
72
|
-
gvars = gvars.dump.filter_map do |gvar_name, entry|
|
73
|
-
if entry.type != Type.bot && !entry.rbs_declared
|
74
|
-
[gvar_name, entry]
|
75
|
-
end
|
76
|
-
end
|
77
|
-
# A signature for global variables is not supported in RBS
|
78
|
-
return if gvars.empty?
|
79
|
-
|
80
|
-
output.puts "# Global variables"
|
81
|
-
gvars.each do |gvar_name, entry|
|
82
|
-
output.puts "#{ gvar_name }: #{ entry.type.screen_name(scratch) }"
|
83
|
-
end
|
84
|
-
output.puts
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
class RubySignatureExporter
|
89
|
-
def initialize(
|
90
|
-
scratch,
|
91
|
-
class_defs, iseq_method_to_ctxs
|
92
|
-
)
|
93
|
-
@scratch = scratch
|
94
|
-
@class_defs = class_defs
|
95
|
-
@iseq_method_to_ctxs = iseq_method_to_ctxs
|
96
|
-
end
|
97
|
-
|
98
|
-
def conv_class(namespace, class_def, inner_classes)
|
99
|
-
@scratch.namespace = namespace
|
100
|
-
|
101
|
-
if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
|
102
|
-
omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
103
|
-
superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
|
104
|
-
type_args = class_def.klass_obj.superclass_type_args
|
105
|
-
if type_args && !type_args.empty?
|
106
|
-
superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
@scratch.namespace = class_def.name
|
111
|
-
|
112
|
-
consts = {}
|
113
|
-
class_def.consts.each do |name, (ty, loc)|
|
114
|
-
next unless loc
|
115
|
-
next if ty.is_a?(Type::Class)
|
116
|
-
next if Config.current.check_dir_filter(loc[0]) == :exclude
|
117
|
-
consts[name] = ty.screen_name(@scratch)
|
118
|
-
end
|
119
|
-
|
120
|
-
modules = class_def.modules.to_h do |kind, mods|
|
121
|
-
mods = mods.to_h do |singleton, mods|
|
122
|
-
mods = mods.filter_map do |mod_def, _type_args, absolute_paths|
|
123
|
-
next if absolute_paths.all? {|path| !path || Config.current.check_dir_filter(path) == :exclude }
|
124
|
-
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
125
|
-
end
|
126
|
-
[singleton, mods]
|
127
|
-
end
|
128
|
-
[kind, mods]
|
129
|
-
end
|
130
|
-
|
131
|
-
visibilities = {}
|
132
|
-
source_locations = {}
|
133
|
-
methods = {}
|
134
|
-
ivars = class_def.ivars.dump
|
135
|
-
cvars = class_def.cvars.dump
|
136
|
-
|
137
|
-
class_def.methods.each do |(singleton, mid), mdefs|
|
138
|
-
mdefs.each do |mdef|
|
139
|
-
case mdef
|
140
|
-
when ISeqMethodDef
|
141
|
-
ctxs = @iseq_method_to_ctxs[mdef]
|
142
|
-
next unless ctxs
|
143
|
-
|
144
|
-
ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
|
145
|
-
|
146
|
-
next if Config.current.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
147
|
-
|
148
|
-
method_name = mid
|
149
|
-
method_name = "self.#{ method_name }" if singleton
|
150
|
-
|
151
|
-
key = [:iseq, method_name]
|
152
|
-
visibilities[key] ||= mdef.pub_meth
|
153
|
-
source_locations[key] ||= ctx.iseq.source_location(0)
|
154
|
-
(methods[key] ||= []) << @scratch.show_method_signature(ctx)
|
155
|
-
when AliasMethodDef
|
156
|
-
next if mdef.def_ep && Config.current.check_dir_filter(mdef.def_ep.source_location) == :exclude
|
157
|
-
alias_name, orig_name = mid, mdef.orig_mid
|
158
|
-
if singleton
|
159
|
-
alias_name = "self.#{ alias_name }"
|
160
|
-
orig_name = "self.#{ orig_name }"
|
161
|
-
end
|
162
|
-
key = [:alias, alias_name]
|
163
|
-
visibilities[key] ||= mdef.pub_meth
|
164
|
-
source_locations[key] ||= mdef.def_ep&.source_location
|
165
|
-
methods[key] = orig_name
|
166
|
-
when ExecutedAttrMethodDef
|
167
|
-
absolute_path = mdef.def_ep.ctx.iseq.absolute_path
|
168
|
-
next if !absolute_path || Config.current.check_dir_filter(absolute_path) == :exclude
|
169
|
-
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
170
|
-
method_name = mid
|
171
|
-
method_name = "self.#{ mid }" if singleton
|
172
|
-
method_name = [method_name, :"@#{ mid }" != mdef.ivar]
|
173
|
-
key = [:attr, method_name]
|
174
|
-
visibilities[key] ||= mdef.pub_meth
|
175
|
-
source_locations[key] ||= mdef.def_ep.source_location
|
176
|
-
if methods[key]
|
177
|
-
if methods[key][0] != mdef.kind
|
178
|
-
methods[key][0] = :accessor
|
179
|
-
end
|
180
|
-
else
|
181
|
-
entry = ivars[[singleton, mdef.ivar]]
|
182
|
-
ty = entry ? entry.type : Type.any
|
183
|
-
methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
|
184
|
-
end
|
185
|
-
when TypedMethodDef
|
186
|
-
if mdef.rbs_source
|
187
|
-
method_name, sigs = mdef.rbs_source
|
188
|
-
key = [:rbs, method_name]
|
189
|
-
methods[key] = sigs
|
190
|
-
visibilities[key] ||= mdef.pub_meth
|
191
|
-
source_locations[key] ||= mdef.iseq&.source_location(0)
|
192
|
-
end
|
193
|
-
when TypedAttrMethodDef
|
194
|
-
if mdef.rbs_source
|
195
|
-
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
196
|
-
method_name = mid
|
197
|
-
method_name = [method_name, :"@#{ mid }" != mdef.ivar]
|
198
|
-
key = [:rbs_attr, method_name]
|
199
|
-
visibilities[key] ||= mdef.pub_meth
|
200
|
-
if methods[key]
|
201
|
-
if methods[key][0] != mdef.kind
|
202
|
-
methods[key][0] = :accessor
|
203
|
-
end
|
204
|
-
else
|
205
|
-
entry = ivars[[singleton, mdef.ivar]]
|
206
|
-
ty = entry ? entry.type : Type.any
|
207
|
-
methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
superclass_ivars = {}
|
215
|
-
while (superclass_def = (superclass_def || class_def).superclass)
|
216
|
-
superclass_ivars.merge!(superclass_def.ivars.dump)
|
217
|
-
end
|
218
|
-
|
219
|
-
ivars = ivars.map do |(singleton, var), entry|
|
220
|
-
next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude }
|
221
|
-
ty = entry.type
|
222
|
-
next unless var.to_s.start_with?("@")
|
223
|
-
|
224
|
-
if (_, existing = superclass_ivars.find {|((s, v), _)| s == singleton && v == var })
|
225
|
-
existing_types = existing.type.is_a?(Type::Union) ? existing.type.types : [existing.type]
|
226
|
-
entry_types = entry.type.is_a?(Type::Union) ? entry.type.types : [entry.type]
|
227
|
-
if entry_types.all? { |t| existing_types.include?(t) }
|
228
|
-
# This type is a subset of the parent type
|
229
|
-
next
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
var = "self.#{ var }" if singleton
|
234
|
-
next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]]
|
235
|
-
next if entry.rbs_declared
|
236
|
-
[var, ty.screen_name(@scratch)]
|
237
|
-
end.compact
|
238
|
-
|
239
|
-
cvars = cvars.map do |var, entry|
|
240
|
-
next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude }
|
241
|
-
next if entry.rbs_declared
|
242
|
-
[var, entry.type.screen_name(@scratch)]
|
243
|
-
end.compact
|
244
|
-
|
245
|
-
if !class_def.absolute_path || Config.current.check_dir_filter(class_def.absolute_path) == :exclude
|
246
|
-
if methods.keys.all? {|type,| type == :rbs }
|
247
|
-
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?
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
@scratch.namespace = nil
|
252
|
-
|
253
|
-
ClassData.new(
|
254
|
-
kind: class_def.kind,
|
255
|
-
name: class_def.name,
|
256
|
-
superclass: superclass,
|
257
|
-
consts: consts,
|
258
|
-
modules: modules,
|
259
|
-
ivars: ivars,
|
260
|
-
cvars: cvars,
|
261
|
-
methods: methods,
|
262
|
-
visibilities: visibilities,
|
263
|
-
source_locations: source_locations,
|
264
|
-
inner_classes: inner_classes,
|
265
|
-
)
|
266
|
-
end
|
267
|
-
|
268
|
-
def conv_class_lsp(namespace, class_def)
|
269
|
-
@scratch.namespace = namespace
|
270
|
-
|
271
|
-
if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
|
272
|
-
omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
273
|
-
superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
|
274
|
-
type_args = class_def.klass_obj.superclass_type_args
|
275
|
-
if type_args && !type_args.empty?
|
276
|
-
superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]"
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
@scratch.namespace = class_def.name
|
281
|
-
|
282
|
-
consts = {}
|
283
|
-
class_def.consts.each do |name, (ty, loc)|
|
284
|
-
next unless loc
|
285
|
-
next if ty.is_a?(Type::Class)
|
286
|
-
next if Config.current.check_dir_filter(loc[0]) == :exclude
|
287
|
-
consts[name] = ty.screen_name(@scratch)
|
288
|
-
end
|
289
|
-
|
290
|
-
modules = class_def.modules.to_h do |kind, mods|
|
291
|
-
mods = mods.to_h do |singleton, mods|
|
292
|
-
mods = mods.filter_map do |mod_def, _type_args, absolute_paths|
|
293
|
-
next if absolute_paths.all? {|path| !path || Config.current.check_dir_filter(path) == :exclude }
|
294
|
-
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
295
|
-
end
|
296
|
-
[singleton, mods]
|
297
|
-
end
|
298
|
-
[kind, mods]
|
299
|
-
end
|
300
|
-
|
301
|
-
visibilities = {}
|
302
|
-
source_locations = {}
|
303
|
-
methods = {}
|
304
|
-
ivars = class_def.ivars.dump
|
305
|
-
cvars = class_def.cvars.dump
|
306
|
-
|
307
|
-
class_def.methods.each do |(singleton, mid), mdefs|
|
308
|
-
mdefs.each do |mdef|
|
309
|
-
case mdef
|
310
|
-
when ISeqMethodDef
|
311
|
-
ctxs = @iseq_method_to_ctxs[mdef]
|
312
|
-
next unless ctxs
|
313
|
-
|
314
|
-
ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
|
315
|
-
|
316
|
-
next if Config.current.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
317
|
-
|
318
|
-
method_name = mid
|
319
|
-
method_name = "self.#{ method_name }" if singleton
|
320
|
-
|
321
|
-
key = [:iseq, method_name]
|
322
|
-
visibilities[key] ||= mdef.pub_meth
|
323
|
-
source_locations[key] ||= [ctx.iseq.source_location(0)]
|
324
|
-
sig = @scratch.show_method_signature(ctx)
|
325
|
-
(methods[key] ||= []) << sig if sig
|
326
|
-
when AliasMethodDef
|
327
|
-
alias_name, orig_name = mid, mdef.orig_mid
|
328
|
-
if singleton
|
329
|
-
alias_name = "self.#{ alias_name }"
|
330
|
-
orig_name = "self.#{ orig_name }"
|
331
|
-
end
|
332
|
-
key = [:alias, alias_name]
|
333
|
-
visibilities[key] ||= mdef.pub_meth
|
334
|
-
source_locations[key] ||= [mdef.def_ep&.source_location]
|
335
|
-
methods[key] = orig_name
|
336
|
-
when ExecutedAttrMethodDef
|
337
|
-
next if !mdef.def_ep
|
338
|
-
absolute_path = mdef.def_ep.ctx.iseq.absolute_path
|
339
|
-
next if !absolute_path || Config.current.check_dir_filter(absolute_path) == :exclude
|
340
|
-
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
341
|
-
method_name = mid
|
342
|
-
method_name = "self.#{ mid }" if singleton
|
343
|
-
method_name = [method_name, :"@#{ mid }" != mdef.ivar]
|
344
|
-
key = [:attr, method_name]
|
345
|
-
visibilities[key] ||= mdef.pub_meth
|
346
|
-
source_locations[key] ||= [mdef.def_ep.source_location]
|
347
|
-
if methods[key]
|
348
|
-
if methods[key][0] != mdef.kind
|
349
|
-
methods[key][0] = :accessor
|
350
|
-
end
|
351
|
-
else
|
352
|
-
entry = ivars[[singleton, mdef.ivar]]
|
353
|
-
ty = entry ? entry.type : Type.any
|
354
|
-
methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
|
355
|
-
end
|
356
|
-
when TypedMethodDef
|
357
|
-
if mdef.rbs_source
|
358
|
-
method_name, sigs, rbs_code_range = mdef.rbs_source
|
359
|
-
key = [:rbs, method_name]
|
360
|
-
methods[key] = sigs
|
361
|
-
visibilities[key] ||= mdef.pub_meth
|
362
|
-
source_locations[key] ||= [mdef.iseq&.source_location(0), rbs_code_range]
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
ivars = ivars.map do |(singleton, var), entry|
|
369
|
-
next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude }
|
370
|
-
ty = entry.type
|
371
|
-
next unless var.to_s.start_with?("@")
|
372
|
-
var = "self.#{ var }" if singleton
|
373
|
-
next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]]
|
374
|
-
next if entry.rbs_declared
|
375
|
-
[var, ty.screen_name(@scratch)]
|
376
|
-
end.compact
|
377
|
-
|
378
|
-
cvars = cvars.map do |var, entry|
|
379
|
-
next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude }
|
380
|
-
next if entry.rbs_declared
|
381
|
-
[var, entry.type.screen_name(@scratch)]
|
382
|
-
end.compact
|
383
|
-
|
384
|
-
if !class_def.absolute_path || Config.current.check_dir_filter(class_def.absolute_path) == :exclude
|
385
|
-
if methods.keys.all? {|type,| type == :rbs }
|
386
|
-
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?
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
@scratch.namespace = nil
|
391
|
-
|
392
|
-
ClassData.new(
|
393
|
-
kind: class_def.kind,
|
394
|
-
name: class_def.name,
|
395
|
-
superclass: superclass,
|
396
|
-
consts: consts,
|
397
|
-
modules: modules,
|
398
|
-
ivars: ivars,
|
399
|
-
cvars: cvars,
|
400
|
-
methods: methods,
|
401
|
-
visibilities: visibilities,
|
402
|
-
source_locations: source_locations,
|
403
|
-
)
|
404
|
-
end
|
405
|
-
|
406
|
-
ClassData = Struct.new(:kind, :name, :superclass, :consts, :modules, :ivars, :cvars, :methods, :visibilities, :source_locations, :inner_classes, keyword_init: true)
|
407
|
-
|
408
|
-
def show_lsp
|
409
|
-
res = []
|
410
|
-
@class_defs.each_value do |class_def|
|
411
|
-
class_data = conv_class_lsp([], class_def)
|
412
|
-
next unless class_data
|
413
|
-
class_data.methods.each do |key, arg|
|
414
|
-
source_location, rbs_code_range = class_data.source_locations[key]
|
415
|
-
type, (method_name, hidden) = key
|
416
|
-
case type
|
417
|
-
when :attr, :rbs_attr
|
418
|
-
kind, ty, untyped = *arg
|
419
|
-
line = "attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }"
|
420
|
-
when :rbs
|
421
|
-
sigs = arg.sort.join(" | ")
|
422
|
-
line = "# def #{ method_name }: #{ sigs }"
|
423
|
-
when :iseq
|
424
|
-
sigs = []
|
425
|
-
untyped = false
|
426
|
-
arg.each do |sig, untyped0|
|
427
|
-
sigs << sig
|
428
|
-
untyped ||= untyped0
|
429
|
-
end
|
430
|
-
sigs = sigs.sort.join(" | ")
|
431
|
-
line = "def #{ method_name }: #{ sigs }"
|
432
|
-
when :alias
|
433
|
-
orig_name = arg
|
434
|
-
line = "alias #{ method_name } #{ orig_name }"
|
435
|
-
end
|
436
|
-
if source_location =~ /:(\d+)$/
|
437
|
-
res << [$`, $1.to_i, line, rbs_code_range, class_data.kind, class_data.name]
|
438
|
-
end
|
439
|
-
end
|
440
|
-
end
|
441
|
-
res
|
442
|
-
end
|
443
|
-
|
444
|
-
def show(stat_eps, output)
|
445
|
-
# make the class hierarchy
|
446
|
-
root = {}
|
447
|
-
@class_defs.each_value do |class_def|
|
448
|
-
h = root
|
449
|
-
class_def.name.each do |name|
|
450
|
-
h = h[name] ||= {}
|
451
|
-
end
|
452
|
-
h[:class_def] = class_def
|
453
|
-
end
|
454
|
-
|
455
|
-
hierarchy = build_class_hierarchy([], root)
|
456
|
-
|
457
|
-
output.puts "# Classes" # and Modules
|
458
|
-
|
459
|
-
prev_nil = true
|
460
|
-
show_class_hierarchy(0, hierarchy).each do |line|
|
461
|
-
if line == nil
|
462
|
-
output.puts line unless prev_nil
|
463
|
-
prev_nil = true
|
464
|
-
else
|
465
|
-
output.puts line
|
466
|
-
prev_nil = false
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
if ENV["TP_STAT"]
|
471
|
-
output.puts ""
|
472
|
-
output.puts "# TypeProf statistics:"
|
473
|
-
output.puts "# %d execution points" % stat_eps.size
|
474
|
-
end
|
475
|
-
|
476
|
-
if ENV["TP_COVERAGE"]
|
477
|
-
coverage = {}
|
478
|
-
stat_eps.each do |ep|
|
479
|
-
path = ep.ctx.iseq.path
|
480
|
-
lineno = ep.ctx.iseq.insns[ep.pc].lineno - 1
|
481
|
-
(coverage[path] ||= [])[lineno] ||= 0
|
482
|
-
(coverage[path] ||= [])[lineno] += 1
|
483
|
-
end
|
484
|
-
File.binwrite("typeprof-analysis-coverage.dump", Marshal.dump(coverage))
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
def build_class_hierarchy(namespace, hierarchy)
|
489
|
-
hierarchy.map do |name, h|
|
490
|
-
class_def = h.delete(:class_def)
|
491
|
-
class_data = conv_class(namespace, class_def, build_class_hierarchy(namespace + [name], h))
|
492
|
-
class_data
|
493
|
-
end.compact
|
494
|
-
end
|
495
|
-
|
496
|
-
def show_class_hierarchy(depth, hierarchy)
|
497
|
-
lines = []
|
498
|
-
hierarchy.each do |class_data|
|
499
|
-
lines << nil
|
500
|
-
lines.concat show_class_data(depth, class_data)
|
501
|
-
end
|
502
|
-
lines
|
503
|
-
end
|
504
|
-
|
505
|
-
def show_const(namespace, path)
|
506
|
-
return path.last.to_s if namespace == path
|
507
|
-
i = 0
|
508
|
-
i += 1 while namespace[i] && namespace[i] == path[i]
|
509
|
-
path[i..].join("::")
|
510
|
-
end
|
511
|
-
|
512
|
-
def show_class_data(depth, class_data)
|
513
|
-
indent = " " * depth
|
514
|
-
name = class_data.name.last
|
515
|
-
superclass = " < " + class_data.superclass if class_data.superclass
|
516
|
-
first_line = indent + "#{ class_data.kind } #{ name }#{ superclass }"
|
517
|
-
lines = []
|
518
|
-
class_data.consts.each do |name, ty|
|
519
|
-
lines << (indent + " #{ name }: #{ ty }")
|
520
|
-
end
|
521
|
-
class_data.modules.each do |kind, mods|
|
522
|
-
mods.each do |singleton, mods|
|
523
|
-
case
|
524
|
-
when kind == :before && singleton then directive = nil
|
525
|
-
when kind == :before && !singleton then directive = "prepend"
|
526
|
-
when kind == :after && singleton then directive = "extend"
|
527
|
-
when kind == :after && !singleton then directive = "include"
|
528
|
-
end
|
529
|
-
mods.each do |mod|
|
530
|
-
lines << (indent + " #{ directive } #{ mod }") if directive
|
531
|
-
end
|
532
|
-
end
|
533
|
-
end
|
534
|
-
class_data.ivars.each do |var, ty|
|
535
|
-
lines << (indent + " #{ var }: #{ ty }") unless var.start_with?("_")
|
536
|
-
end
|
537
|
-
class_data.cvars.each do |var, ty|
|
538
|
-
lines << (indent + " #{ var }: #{ ty }")
|
539
|
-
end
|
540
|
-
lines << nil
|
541
|
-
prev_vis = true
|
542
|
-
class_data.methods.each do |key, arg|
|
543
|
-
vis = class_data.visibilities[key]
|
544
|
-
if prev_vis != vis
|
545
|
-
lines << nil
|
546
|
-
lines << (indent + " #{ vis ? "public" : "private" }")
|
547
|
-
prev_vis = vis
|
548
|
-
end
|
549
|
-
source_location = class_data.source_locations[key]
|
550
|
-
if Config.current.options[:show_source_locations] && source_location
|
551
|
-
lines << nil
|
552
|
-
lines << (indent + " # #{ source_location }")
|
553
|
-
end
|
554
|
-
type, (method_name, hidden) = key
|
555
|
-
case type
|
556
|
-
when :rbs_attr
|
557
|
-
kind, ty, untyped = *arg
|
558
|
-
lines << (indent + "# attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
|
559
|
-
when :attr
|
560
|
-
kind, ty, untyped = *arg
|
561
|
-
exclude = Config.current.options[:exclude_untyped] && untyped ? "#" : " " # XXX
|
562
|
-
lines << (indent + "#{ exclude } attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
|
563
|
-
when :rbs
|
564
|
-
arg = arg.map { |a| a.split("\n").join("\n" + indent + "#" + " " * (method_name.size + 5)) }
|
565
|
-
sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ")
|
566
|
-
lines << (indent + "# def #{ method_name }: #{ sigs }")
|
567
|
-
when :iseq
|
568
|
-
sigs = []
|
569
|
-
untyped = false
|
570
|
-
arg.each do |sig, untyped0|
|
571
|
-
sigs << sig
|
572
|
-
untyped ||= untyped0
|
573
|
-
end
|
574
|
-
sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
|
575
|
-
exclude = Config.current.options[:exclude_untyped] && untyped ? "#" : " " # XXX
|
576
|
-
lines << (indent + "#{ exclude } def #{ method_name }: #{ sigs }")
|
577
|
-
when :alias
|
578
|
-
orig_name = arg
|
579
|
-
lines << (indent + " alias #{ method_name } #{ orig_name }")
|
580
|
-
end
|
581
|
-
end
|
582
|
-
lines.concat show_class_hierarchy(depth + 1, class_data.inner_classes)
|
583
|
-
lines.shift until lines.empty? || lines.first
|
584
|
-
lines.pop until lines.empty? || lines.last
|
585
|
-
lines.unshift first_line
|
586
|
-
lines << (indent + "end")
|
587
|
-
end
|
588
|
-
end
|
589
|
-
end
|