def self.analyze(config)
if TypeProf.const_defined?(:Config)
TypeProf.send(:remove_const, :Config)
end
TypeProf.const_set(:Config, config)
if Config.options[:stackprof]
require "stackprof"
out = "typeprof-stackprof-#{ Config.options[:stackprof] }.dump"
StackProf.start(mode: Config.options[:stackprof], out: out, raw: true)
end
scratch = Scratch.new
Builtin.setup_initial_global_env(scratch)
Config.gem_rbs_features.each do |feature|
Import.import_library(scratch, feature)
end
prologue_ctx = Context.new(nil, nil, nil)
prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
Config.rb_files.each do |rb|
if rb.is_a?(Array)
iseq = ISeq.compile_str(*rb.reverse)
else
iseq = ISeq.compile(rb)
end
ep, env = TypeProf.starting_state(iseq)
scratch.merge_env(ep, env)
scratch.add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
end
rbs_files = []
rbs_codes = []
Config.rbs_files.each do |rbs|
if rbs.is_a?(Array)
rbs_codes << rbs
else
rbs_files << rbs
end
end
Import.import_rbs_files(scratch, rbs_files)
rbs_codes.each do |name, content|
Import.import_rbs_code(scratch, name, content)
end
result = scratch.type_profile
if Config.output.respond_to?(:write)
scratch.report(result, Config.output)
else
open(Config.output, "w") do |output|
scratch.report(result, output)
end
end
rescue TypeProfError => exc
exc.report(Config.output)
ensure
if Config.options[:stackprof] && defined?(StackProf)
StackProf.stop
StackProf.results
end
end