typeprof 0.21.11 → 0.30.1

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +178 -0
  7. data/lib/typeprof/cli.rb +3 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +259 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +433 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +339 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +366 -0
  31. data/lib/typeprof/core/graph/box.rb +998 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +225 -0
  35. data/lib/typeprof/core/service.rb +514 -0
  36. data/lib/typeprof/core/type.rb +352 -0
  37. data/lib/typeprof/core/util.rb +81 -0
  38. data/lib/typeprof/core.rb +31 -0
  39. data/lib/typeprof/diagnostic.rb +35 -0
  40. data/lib/typeprof/lsp/messages.rb +415 -0
  41. data/lib/typeprof/lsp/server.rb +203 -0
  42. data/lib/typeprof/lsp/text.rb +69 -0
  43. data/lib/typeprof/lsp/util.rb +51 -0
  44. data/lib/typeprof/lsp.rb +4 -907
  45. data/lib/typeprof/version.rb +1 -1
  46. data/lib/typeprof.rb +4 -18
  47. data/typeprof.gemspec +5 -7
  48. metadata +47 -33
  49. data/.github/dependabot.yml +0 -6
  50. data/.github/workflows/main.yml +0 -39
  51. data/.gitignore +0 -9
  52. data/Gemfile +0 -17
  53. data/Gemfile.lock +0 -41
  54. data/Rakefile +0 -10
  55. data/exe/typeprof +0 -10
  56. data/lib/typeprof/analyzer.rb +0 -2598
  57. data/lib/typeprof/arguments.rb +0 -414
  58. data/lib/typeprof/block.rb +0 -176
  59. data/lib/typeprof/builtin.rb +0 -893
  60. data/lib/typeprof/code-range.rb +0 -177
  61. data/lib/typeprof/config.rb +0 -158
  62. data/lib/typeprof/container-type.rb +0 -912
  63. data/lib/typeprof/export.rb +0 -589
  64. data/lib/typeprof/import.rb +0 -852
  65. data/lib/typeprof/insns-def.rb +0 -65
  66. data/lib/typeprof/iseq.rb +0 -864
  67. data/lib/typeprof/method.rb +0 -355
  68. data/lib/typeprof/type.rb +0 -1140
  69. data/lib/typeprof/utils.rb +0 -212
  70. data/tools/coverage.rb +0 -14
  71. data/tools/setup-insns-def.rb +0 -30
  72. data/typeprof-lsp +0 -3
@@ -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