typeprof 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +1 -1
- data/doc/doc.ja.md +5 -0
- data/doc/doc.md +9 -5
- data/lib/typeprof/analyzer.rb +97 -69
- data/lib/typeprof/builtin.rb +96 -92
- data/lib/typeprof/cli.rb +42 -4
- data/lib/typeprof/export.rb +36 -20
- data/lib/typeprof/import.rb +406 -365
- data/lib/typeprof/iseq.rb +1 -1
- data/lib/typeprof/method.rb +34 -33
- data/lib/typeprof/type.rb +1 -4
- data/run.sh +1 -1
- data/smoke/block13.rb +9 -0
- data/smoke/block13.rbs +3 -0
- data/smoke/class.rb +2 -0
- data/smoke/constant1.rb +3 -0
- data/smoke/demo5.rb +3 -0
- data/smoke/gvar.rb +1 -1
- data/smoke/gvar2.rb +17 -0
- data/smoke/gvar2.rbs +1 -0
- data/smoke/inheritance2.rb +6 -0
- data/smoke/ivar3.rb +16 -0
- data/smoke/ivar3.rbs +3 -0
- data/smoke/manual-rbs2.rb +1 -1
- data/smoke/manual-rbs3.rb +12 -0
- data/smoke/manual-rbs3.rbs +3 -0
- data/smoke/module4.rb +3 -0
- data/smoke/multiple-superclass.rb +8 -0
- data/smoke/rbs-alias.rb +9 -0
- data/smoke/rbs-alias.rbs +4 -0
- data/smoke/rbs-attr.rb +26 -0
- data/smoke/rbs-attr.rbs +5 -0
- data/smoke/rbs-vars.rb +39 -0
- data/smoke/rbs-vars.rbs +7 -0
- data/smoke/struct.rb +3 -0
- data/smoke/super1.rb +18 -0
- data/smoke/union-recv.rb +6 -0
- data/tools/setup-insns-def.rb +1 -1
- data/tools/stackprof-wrapper.rb +1 -1
- data/typeprof.gemspec +10 -4
- metadata +26 -7
data/lib/typeprof/builtin.rb
CHANGED
@@ -147,7 +147,7 @@ module TypeProf
|
|
147
147
|
|
148
148
|
def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
|
149
149
|
arg = aargs.lead_tys[0]
|
150
|
-
scratch.include_module(recv, arg)
|
150
|
+
scratch.include_module(recv, arg, ep.ctx.iseq.absolute_path)
|
151
151
|
ctn[recv, ep, env]
|
152
152
|
end
|
153
153
|
|
@@ -155,7 +155,7 @@ module TypeProf
|
|
155
155
|
arg = aargs.lead_tys[0]
|
156
156
|
arg.each_child do |arg|
|
157
157
|
if arg.is_a?(Type::Class)
|
158
|
-
scratch.extend_module(recv, arg)
|
158
|
+
scratch.extend_module(recv, arg, ep.ctx.iseq.absolute_path)
|
159
159
|
end
|
160
160
|
end
|
161
161
|
ctn[recv, ep, env]
|
@@ -180,7 +180,7 @@ module TypeProf
|
|
180
180
|
aargs.lead_tys.each do |aarg|
|
181
181
|
sym = get_sym("attr_accessor", aarg, ep, scratch) or next
|
182
182
|
cref = ep.ctx.cref
|
183
|
-
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :accessor)
|
183
|
+
scratch.add_attr_method(cref.klass, ep.ctx.iseq.absolute_path, sym, :"@#{ sym }", :accessor)
|
184
184
|
end
|
185
185
|
ctn[Type.nil, ep, env]
|
186
186
|
end
|
@@ -189,7 +189,7 @@ module TypeProf
|
|
189
189
|
aargs.lead_tys.each do |aarg|
|
190
190
|
sym = get_sym("attr_reader", aarg, ep, scratch) or next
|
191
191
|
cref = ep.ctx.cref
|
192
|
-
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :reader)
|
192
|
+
scratch.add_attr_method(cref.klass, ep.ctx.iseq.absolute_path, sym, :"@#{ sym }", :reader)
|
193
193
|
end
|
194
194
|
ctn[Type.nil, ep, env]
|
195
195
|
end
|
@@ -198,7 +198,7 @@ module TypeProf
|
|
198
198
|
aargs.lead_tys.each do |aarg|
|
199
199
|
sym = get_sym("attr_writer", aarg, ep, scratch) or next
|
200
200
|
cref = ep.ctx.cref
|
201
|
-
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :writer)
|
201
|
+
scratch.add_attr_method(cref.klass, ep.ctx.iseq.absolute_path, sym, :"@#{ sym }", :writer)
|
202
202
|
end
|
203
203
|
ctn[Type.nil, ep, env]
|
204
204
|
end
|
@@ -283,8 +283,6 @@ module TypeProf
|
|
283
283
|
return
|
284
284
|
end
|
285
285
|
idx = aargs.lead_tys.first
|
286
|
-
#idx = scratch.globalize_type(idx, env, ep)
|
287
|
-
# XXX: recv may be a union
|
288
286
|
recv.each_child do |recv|
|
289
287
|
if recv.is_a?(Type::LocalHash)
|
290
288
|
ty = scratch.get_hash_elem_type(env, ep, recv.id, idx)
|
@@ -358,21 +356,21 @@ module TypeProf
|
|
358
356
|
fields = aargs.lead_tys.map {|ty| get_sym("Struct.new", ty, ep, scratch) }.compact
|
359
357
|
struct_klass = scratch.new_struct(ep)
|
360
358
|
|
361
|
-
scratch.
|
362
|
-
scratch.
|
359
|
+
scratch.set_singleton_custom_method(struct_klass, :new, Builtin.method(:struct_i_new))
|
360
|
+
scratch.set_singleton_custom_method(struct_klass, :[], Builtin.method(:struct_i_new))
|
363
361
|
fields.each do |field|
|
364
|
-
scratch.add_attr_method(struct_klass, field, field, :accessor)
|
362
|
+
scratch.add_attr_method(struct_klass, ep.ctx.iseq.absolute_path, field, field, :accessor)
|
365
363
|
end
|
366
364
|
fields = fields.map {|field| Type::Symbol.new(field, Type::Instance.new(Type::Builtin[:sym])) }
|
367
365
|
base_ty = Type::Instance.new(Type::Builtin[:ary])
|
368
366
|
fields = Type::Array.new(Type::Array::Elements.new(fields), base_ty)
|
369
367
|
scratch.set_instance_variable(Type::Instance.new(struct_klass), :_members, fields, ep, env)
|
370
|
-
#
|
368
|
+
#set_singleton_custom_method(struct_klass, :members, Builtin.method(:...))
|
371
369
|
|
372
370
|
ctn[struct_klass, ep, env]
|
373
371
|
end
|
374
372
|
|
375
|
-
def file_load(path, ep, env, scratch, &ctn)
|
373
|
+
def self.file_load(path, ep, env, scratch, &ctn)
|
376
374
|
iseq = ISeq.compile(path)
|
377
375
|
callee_ep, callee_env = CLI.starting_state(iseq)
|
378
376
|
scratch.merge_env(callee_ep, callee_env)
|
@@ -383,51 +381,60 @@ module TypeProf
|
|
383
381
|
end
|
384
382
|
end
|
385
383
|
|
384
|
+
def self.file_require(feature, scratch)
|
385
|
+
return :done, :false if scratch.loaded_features[feature]
|
386
|
+
scratch.loaded_features[feature] = true
|
387
|
+
|
388
|
+
# XXX: dynamic RBS load is really needed?? Another idea:
|
389
|
+
#
|
390
|
+
# * RBS should be loaded in advance of analysis
|
391
|
+
# * require "some_gem/foo" should be ignored
|
392
|
+
# * require "app/foo" should always load .rb file (in this case, app/foo.rb)
|
393
|
+
return :done, :true if Import.import_library(scratch, feature)
|
394
|
+
|
395
|
+
# Try to analyze the source code of the gem
|
396
|
+
begin
|
397
|
+
gem feature
|
398
|
+
rescue Gem::MissingSpecError, Gem::LoadError
|
399
|
+
end
|
400
|
+
|
401
|
+
begin
|
402
|
+
filetype, path = $LOAD_PATH.resolve_feature_path(feature)
|
403
|
+
if filetype == :rb
|
404
|
+
return :do, path if File.readable?(path)
|
405
|
+
|
406
|
+
return :error, "failed to load: #{ path }"
|
407
|
+
else
|
408
|
+
return :error, "cannot load a .so file: #{ path }"
|
409
|
+
end
|
410
|
+
rescue LoadError
|
411
|
+
return :error, "failed to require: #{ feature }"
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
386
415
|
def kernel_require(recv, mid, aargs, ep, env, scratch, &ctn)
|
387
416
|
raise NotImplementedError if aargs.lead_tys.size != 1
|
388
417
|
feature = aargs.lead_tys.first
|
389
418
|
if feature.is_a?(Type::Literal)
|
390
419
|
feature = feature.lit
|
391
420
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
# * require "app/foo" should always load .rb file (in this case, app/foo.rb)
|
404
|
-
if RubySignatureImporter.import_library(scratch, feature)
|
405
|
-
result = Type::Instance.new(Type::Builtin[:true])
|
406
|
-
return ctn[result, ep, env]
|
407
|
-
end
|
408
|
-
|
409
|
-
begin
|
410
|
-
gem feature
|
411
|
-
rescue Gem::MissingSpecError, Gem::LoadError
|
412
|
-
end
|
413
|
-
filetype, path = $LOAD_PATH.resolve_feature_path(feature)
|
414
|
-
if filetype == :rb
|
415
|
-
# TODO: if there is RBS file for the library, do not read the source code
|
416
|
-
return file_load(path, ep, env, scratch, &ctn) if File.readable?(path)
|
417
|
-
|
418
|
-
scratch.warn(ep, "failed to load: #{ path }")
|
419
|
-
else
|
420
|
-
scratch.warn(ep, "cannot load a .so file: #{ path }")
|
421
|
-
end
|
422
|
-
rescue LoadError
|
423
|
-
scratch.warn(ep, "failed to require: #{ feature }")
|
421
|
+
action, arg = Builtin.file_require(feature, scratch)
|
422
|
+
case action
|
423
|
+
when :do
|
424
|
+
Builtin.file_load(arg, ep, env, scratch, &ctn)
|
425
|
+
when :done
|
426
|
+
result = Type::Instance.new(Type::Builtin[arg])
|
427
|
+
ctn[result, ep, env]
|
428
|
+
when :error
|
429
|
+
scratch.warn(ep, arg)
|
430
|
+
result = Type::Instance.new(Type.bool)
|
431
|
+
ctn[result, ep, env]
|
424
432
|
end
|
425
433
|
else
|
426
434
|
scratch.warn(ep, "require target cannot be identified statically")
|
435
|
+
result = Type::Instance.new(Type.bool)
|
436
|
+
ctn[result, ep, env]
|
427
437
|
end
|
428
|
-
|
429
|
-
result = Type::Instance.new(Type::Builtin[:true])
|
430
|
-
ctn[result, ep, env]
|
431
438
|
end
|
432
439
|
|
433
440
|
def kernel_require_relative(recv, mid, aargs, ep, env, scratch, &ctn)
|
@@ -443,7 +450,7 @@ module TypeProf
|
|
443
450
|
scratch.loaded_features[feature] = true
|
444
451
|
|
445
452
|
path = File.join(File.dirname(ep.ctx.iseq.path), feature) + ".rb" # XXX
|
446
|
-
return file_load(path, ep, env, scratch, &ctn) if File.readable?(path)
|
453
|
+
return Builtin.file_load(path, ep, env, scratch, &ctn) if File.readable?(path)
|
447
454
|
|
448
455
|
scratch.warn(ep, "failed to load: #{ path }")
|
449
456
|
else
|
@@ -473,20 +480,17 @@ module TypeProf
|
|
473
480
|
end
|
474
481
|
|
475
482
|
def self.setup_initial_global_env(scratch)
|
476
|
-
|
483
|
+
klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass
|
484
|
+
klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil)
|
477
485
|
scratch.add_constant(klass_obj, "Object", klass_obj)
|
478
|
-
|
479
|
-
klass_false = scratch.new_class(klass_obj, :FalseClass, [], klass_obj) # ???
|
480
|
-
klass_nil = scratch.new_class(klass_obj, :NilClass, [], klass_obj) # ???
|
486
|
+
scratch.add_constant(klass_obj, "BasicObject", klass_basic_obj)
|
481
487
|
|
488
|
+
Type::Builtin[:basic_obj] = klass_basic_obj
|
482
489
|
Type::Builtin[:obj] = klass_obj
|
483
|
-
Type::Builtin[:true] = klass_true
|
484
|
-
Type::Builtin[:false] = klass_false
|
485
|
-
Type::Builtin[:nil] = klass_nil
|
486
490
|
|
487
|
-
|
491
|
+
Import.import_builtin(scratch)
|
488
492
|
|
489
|
-
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj)
|
493
|
+
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
|
490
494
|
Type::Builtin[:int] = scratch.get_constant(klass_obj, :Integer)
|
491
495
|
Type::Builtin[:float] = scratch.get_constant(klass_obj, :Float)
|
492
496
|
Type::Builtin[:rational] = scratch.get_constant(klass_obj, :Rational)
|
@@ -511,41 +515,41 @@ module TypeProf
|
|
511
515
|
klass_proc = Type::Builtin[:proc]
|
512
516
|
klass_module = Type::Builtin[:module]
|
513
517
|
|
514
|
-
scratch.
|
515
|
-
scratch.
|
516
|
-
scratch.
|
517
|
-
scratch.
|
518
|
-
scratch.
|
519
|
-
scratch.
|
520
|
-
scratch.
|
521
|
-
scratch.
|
522
|
-
scratch.
|
523
|
-
scratch.
|
524
|
-
scratch.
|
525
|
-
scratch.
|
526
|
-
scratch.
|
527
|
-
scratch.
|
528
|
-
|
529
|
-
scratch.
|
530
|
-
scratch.
|
531
|
-
scratch.
|
532
|
-
|
533
|
-
scratch.
|
534
|
-
scratch.
|
535
|
-
|
536
|
-
scratch.
|
537
|
-
scratch.
|
538
|
-
scratch.
|
539
|
-
|
540
|
-
scratch.
|
541
|
-
scratch.
|
542
|
-
|
543
|
-
scratch.
|
544
|
-
scratch.
|
545
|
-
|
546
|
-
scratch.
|
547
|
-
scratch.
|
548
|
-
scratch.
|
518
|
+
scratch.set_custom_method(klass_vmcore, :"core#set_method_alias", Builtin.method(:vmcore_set_method_alias))
|
519
|
+
scratch.set_custom_method(klass_vmcore, :"core#undef_method", Builtin.method(:vmcore_undef_method))
|
520
|
+
scratch.set_custom_method(klass_vmcore, :"core#hash_merge_kwd", Builtin.method(:vmcore_hash_merge_kwd))
|
521
|
+
scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda))
|
522
|
+
scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new))
|
523
|
+
scratch.set_singleton_custom_method(klass_obj, :"attr_accessor", Builtin.method(:module_attr_accessor))
|
524
|
+
scratch.set_singleton_custom_method(klass_obj, :"attr_reader", Builtin.method(:module_attr_reader))
|
525
|
+
scratch.set_singleton_custom_method(klass_obj, :"attr_writer", Builtin.method(:module_attr_writer))
|
526
|
+
scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p))
|
527
|
+
scratch.set_custom_method(klass_obj, :is_a?, Builtin.method(:object_is_a?))
|
528
|
+
scratch.set_custom_method(klass_obj, :respond_to?, Builtin.method(:object_respond_to?))
|
529
|
+
scratch.set_custom_method(klass_obj, :class, Builtin.method(:object_class))
|
530
|
+
scratch.set_custom_method(klass_obj, :send, Builtin.method(:object_send))
|
531
|
+
scratch.set_custom_method(klass_obj, :instance_eval, Builtin.method(:object_instance_eval))
|
532
|
+
|
533
|
+
scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include))
|
534
|
+
scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend))
|
535
|
+
scratch.set_custom_method(klass_module, :module_function, Builtin.method(:module_module_function))
|
536
|
+
|
537
|
+
scratch.set_custom_method(klass_proc, :[], Builtin.method(:proc_call))
|
538
|
+
scratch.set_custom_method(klass_proc, :call, Builtin.method(:proc_call))
|
539
|
+
|
540
|
+
scratch.set_custom_method(klass_ary, :[], Builtin.method(:array_aref))
|
541
|
+
scratch.set_custom_method(klass_ary, :[]=, Builtin.method(:array_aset))
|
542
|
+
scratch.set_custom_method(klass_ary, :pop, Builtin.method(:array_pop))
|
543
|
+
|
544
|
+
scratch.set_custom_method(klass_hash, :[], Builtin.method(:hash_aref))
|
545
|
+
scratch.set_custom_method(klass_hash, :[]=, Builtin.method(:hash_aset))
|
546
|
+
|
547
|
+
scratch.set_custom_method(klass_struct, :initialize, Builtin.method(:struct_initialize))
|
548
|
+
scratch.set_singleton_custom_method(klass_struct, :new, Builtin.method(:struct_s_new))
|
549
|
+
|
550
|
+
scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require))
|
551
|
+
scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative))
|
552
|
+
scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array))
|
549
553
|
|
550
554
|
fargs, ret_ty = FormalArguments.new([], [], nil, [], nil, nil, Type.any), Type.any
|
551
555
|
scratch.add_method(klass_obj, :initialize, false, TypedMethodDef.new([[fargs, ret_ty]], nil))
|
data/lib/typeprof/cli.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
require "optparse"
|
2
|
+
require "rbconfig"
|
2
3
|
|
3
4
|
module TypeProf
|
4
5
|
class CLI
|
6
|
+
DEFAULT_DIR_FILTER = [
|
7
|
+
[:include],
|
8
|
+
[:exclude, RbConfig::CONFIG["prefix"]],
|
9
|
+
[:exclude, Gem.dir],
|
10
|
+
[:exclude, Gem.user_dir],
|
11
|
+
]
|
12
|
+
|
5
13
|
def initialize(argv)
|
6
14
|
opt = OptionParser.new
|
7
15
|
|
@@ -18,10 +26,28 @@ module TypeProf
|
|
18
26
|
pedantic_output: false,
|
19
27
|
show_errors: false,
|
20
28
|
}
|
29
|
+
@dir_filter = nil
|
30
|
+
@rbs_features_to_load = []
|
21
31
|
|
22
32
|
opt.on("-o OUTFILE") {|v| @output = v }
|
23
|
-
opt.on("-q", "--quiet") {
|
24
|
-
opt.on("-v", "--verbose") {
|
33
|
+
opt.on("-q", "--quiet") { @verbose = 0 }
|
34
|
+
opt.on("-v", "--verbose") { @verbose = 2 }
|
35
|
+
opt.on("-I DIR") {|v| $LOAD_PATH << v }
|
36
|
+
opt.on("-r FEATURE") {|v| @rbs_features_to_load << v }
|
37
|
+
|
38
|
+
opt.on("--include-dir DIR") do |dir|
|
39
|
+
# When `--include-dir` option is specified as the first directory option,
|
40
|
+
# typeprof will exclude any files by default unless a file path matches the explicit option
|
41
|
+
@dir_filter ||= [[:exclude]]
|
42
|
+
@dir_filter << [:include, File.expand_path(dir)]
|
43
|
+
end
|
44
|
+
opt.on("--exclude-dir DIR") do |dir|
|
45
|
+
# When `--exclude-dir` option is specified as the first directory option,
|
46
|
+
# typeprof will include any files by default, except Ruby's install directory and Gem directories
|
47
|
+
@dir_filter ||= DEFAULT_DIR_FILTER
|
48
|
+
@dir_filter << [:exclude, File.expand_path(dir)]
|
49
|
+
end
|
50
|
+
|
25
51
|
opt.on("-f OPTION") do |v|
|
26
52
|
key, args = v.split("=", 2)
|
27
53
|
case key
|
@@ -40,6 +66,7 @@ module TypeProf
|
|
40
66
|
|
41
67
|
opt.parse!(argv)
|
42
68
|
|
69
|
+
@dir_filter ||= DEFAULT_DIR_FILTER
|
43
70
|
@rb_files = []
|
44
71
|
@rbs_files = []
|
45
72
|
argv.each do |path|
|
@@ -59,13 +86,24 @@ module TypeProf
|
|
59
86
|
exit
|
60
87
|
end
|
61
88
|
|
62
|
-
attr_reader :verbose, :options, :
|
89
|
+
attr_reader :verbose, :options, :dir_filter
|
63
90
|
attr_accessor :output
|
64
91
|
|
92
|
+
def check_dir_filter(path)
|
93
|
+
@dir_filter.reverse_each do |cond, dir|
|
94
|
+
return cond unless dir
|
95
|
+
return cond if path.start_with?(dir)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
65
99
|
def run
|
66
100
|
scratch = Scratch.new
|
67
101
|
Builtin.setup_initial_global_env(scratch)
|
68
102
|
|
103
|
+
@rbs_features_to_load.each do |feature|
|
104
|
+
Import.import_library(scratch, feature)
|
105
|
+
end
|
106
|
+
|
69
107
|
prologue_ctx = Context.new(nil, nil, nil)
|
70
108
|
prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
|
71
109
|
prologue_env = Env.new(StaticEnv.new(:top, Type.nil, false), [], [], Utils::HashWrapper.new({}))
|
@@ -82,7 +120,7 @@ module TypeProf
|
|
82
120
|
end
|
83
121
|
|
84
122
|
@rbs_files.each do |path|
|
85
|
-
|
123
|
+
Import.import_rbs_file(scratch, path)
|
86
124
|
end
|
87
125
|
|
88
126
|
result = scratch.type_profile
|
data/lib/typeprof/export.rb
CHANGED
@@ -31,13 +31,13 @@ module TypeProf
|
|
31
31
|
|
32
32
|
output.puts "# Errors"
|
33
33
|
errors.each do |ep, msg|
|
34
|
-
if ENV["
|
34
|
+
if ENV["TP_DETAIL"]
|
35
35
|
backtrace = filter_backtrace(generate_analysis_trace(ep, {}, backward_edge))
|
36
36
|
else
|
37
37
|
backtrace = [ep]
|
38
38
|
end
|
39
39
|
loc, *backtrace = backtrace.map do |ep|
|
40
|
-
ep
|
40
|
+
ep&.source_location
|
41
41
|
end
|
42
42
|
output.puts "#{ loc }: #{ msg }"
|
43
43
|
backtrace.each do |loc|
|
@@ -57,13 +57,15 @@ module TypeProf
|
|
57
57
|
output.puts
|
58
58
|
end
|
59
59
|
|
60
|
-
def show_gvars(scratch,
|
60
|
+
def show_gvars(scratch, gvars, output)
|
61
61
|
# A signature for global variables is not supported in RBS
|
62
|
-
return if
|
62
|
+
return if gvars.dump.empty?
|
63
63
|
|
64
64
|
output.puts "# Global variables"
|
65
|
-
|
66
|
-
|
65
|
+
gvars.dump.each do |gvar_name, entry|
|
66
|
+
next if entry.type == Type.bot
|
67
|
+
s = entry.rbs_declared ? "#" : ""
|
68
|
+
output.puts s + "#{ gvar_name } : #{ entry.type.screen_name(scratch) }"
|
67
69
|
end
|
68
70
|
output.puts
|
69
71
|
end
|
@@ -88,14 +90,18 @@ module TypeProf
|
|
88
90
|
stat_classes = {}
|
89
91
|
stat_methods = {}
|
90
92
|
first = true
|
93
|
+
|
91
94
|
@class_defs.each_value do |class_def|
|
92
|
-
included_mods = class_def.modules[false].filter_map do |
|
93
|
-
|
95
|
+
included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
|
96
|
+
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
97
|
+
mod_def.name
|
94
98
|
end
|
95
99
|
|
96
100
|
explicit_methods = {}
|
97
101
|
iseq_methods = {}
|
98
102
|
attr_methods = {}
|
103
|
+
ivars = class_def.ivars.dump
|
104
|
+
cvars = class_def.cvars.dump
|
99
105
|
class_def.methods.each do |(singleton, mid), mdefs|
|
100
106
|
mdefs.each do |mdef|
|
101
107
|
case mdef
|
@@ -105,6 +111,7 @@ module TypeProf
|
|
105
111
|
|
106
112
|
ctxs.each do |ctx|
|
107
113
|
next if mid != ctx.mid
|
114
|
+
next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
|
108
115
|
|
109
116
|
method_name = ctx.mid
|
110
117
|
method_name = "self.#{ method_name }" if singleton
|
@@ -116,6 +123,7 @@ module TypeProf
|
|
116
123
|
iseq_methods[method_name] << @scratch.show_signature(fargs, @yields[ctx], ret_tys)
|
117
124
|
end
|
118
125
|
when AttrMethodDef
|
126
|
+
next if Config.check_dir_filter(mdef.absolute_path) == :exclude
|
119
127
|
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
120
128
|
method_name = mid
|
121
129
|
method_name = "self.#{ mid }" if singleton
|
@@ -125,7 +133,8 @@ module TypeProf
|
|
125
133
|
attr_methods[method_name][0] = :accessor
|
126
134
|
end
|
127
135
|
else
|
128
|
-
|
136
|
+
entry = ivars[[singleton, mdef.ivar]]
|
137
|
+
ty = entry ? entry.type : Type.any
|
129
138
|
attr_methods[method_name] = [mdef.kind, ty.screen_name(@scratch)]
|
130
139
|
end
|
131
140
|
when TypedMethodDef
|
@@ -137,36 +146,43 @@ module TypeProf
|
|
137
146
|
end
|
138
147
|
end
|
139
148
|
|
140
|
-
ivars =
|
149
|
+
ivars = ivars.map do |(singleton, var), entry|
|
150
|
+
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
151
|
+
ty = entry.type
|
141
152
|
next unless var.to_s.start_with?("@")
|
142
153
|
var = "self.#{ var }" if singleton
|
143
154
|
next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
|
144
|
-
[var, ty.screen_name(@scratch)]
|
155
|
+
[var, ty.screen_name(@scratch), entry.rbs_declared]
|
145
156
|
end.compact
|
146
157
|
|
147
|
-
cvars =
|
148
|
-
|
158
|
+
cvars = cvars.map do |var, entry|
|
159
|
+
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
160
|
+
[var, entry.type.screen_name(@scratch), entry.rbs_declared]
|
149
161
|
end
|
150
162
|
|
151
|
-
|
163
|
+
if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
|
164
|
+
next if included_mods.empty? && ivars.empty? && cvars.empty? && iseq_methods.empty? && attr_methods.empty?
|
165
|
+
end
|
152
166
|
|
153
167
|
output.puts unless first
|
154
168
|
first = false
|
155
169
|
|
156
170
|
if class_def.superclass
|
157
|
-
|
158
|
-
superclass =
|
171
|
+
omit = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
172
|
+
superclass = omit ? "" : " < #{ @class_defs[class_def.superclass].name }"
|
159
173
|
end
|
160
174
|
|
161
175
|
output.puts "#{ class_def.kind } #{ class_def.name }#{ superclass }"
|
162
176
|
included_mods.sort.each do |ty|
|
163
177
|
output.puts " include #{ ty }"
|
164
178
|
end
|
165
|
-
ivars.each do |var, ty|
|
166
|
-
|
179
|
+
ivars.each do |var, ty, rbs_declared|
|
180
|
+
s = rbs_declared ? "# " : " "
|
181
|
+
output.puts s + "#{ var } : #{ ty }" unless var.start_with?("_")
|
167
182
|
end
|
168
|
-
cvars.each do |var, ty|
|
169
|
-
|
183
|
+
cvars.each do |var, ty, rbs_declared|
|
184
|
+
s = rbs_declared ? "# " : " "
|
185
|
+
output.puts s + "#{ var } : #{ ty }"
|
170
186
|
end
|
171
187
|
attr_methods.each do |(method_name, hidden), (kind, ty)|
|
172
188
|
output.puts " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" } : #{ ty }"
|