typeprof 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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 }"
|