typeprof 0.21.11 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) 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 +180 -0
  7. data/lib/typeprof/cli.rb +2 -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 +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -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 +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -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 +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. 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