123456789_123456789_123456789_123456789_123456789_

Module: TypeProf

Constant Summary

  • INSN_TABLE =
    # File 'lib/typeprof/insns-def.rb', line 1
    {:nop=>[],
    :getlocal=>["lindex_t", "rb_num_t"],
    :setlocal=>["lindex_t", "rb_num_t"],
    :getblockparam=>["lindex_t", "rb_num_t"],
    :setblockparam=>["lindex_t", "rb_num_t"],
    :getblockparamproxy=>["lindex_t", "rb_num_t"],
    :getspecial=>["rb_num_t", "rb_num_t"],
    :setspecial=>["rb_num_t"],
    :getinstancevariable=>["ID", "IVC"],
    :setinstancevariable=>["ID", "IVC"],
    :getclassvariable=>["ID"],
    :setclassvariable=>["ID"],
    :getconstant=>["ID"],
    :setconstant=>["ID"],
    :getglobal=>["GENTRY"],
    :setglobal=>["GENTRY"],
    :putnil=>[],
    :putself=>[],
    :putobject=>["VALUE"],
    :putspecialobject=>["rb_num_t"],
    :putstring=>["VALUE"],
    :concatstrings=>["rb_num_t"],
    :tostring=>[],
    :objtostring=>[],
    :anytostring=>[],
    :freezestring=>["VALUE"],
    :toregexp=>["rb_num_t", "rb_num_t"],
    :intern=>[],
    :newarray=>["rb_num_t"],
    :newarraykwsplat=>["rb_num_t"],
    :duparray=>["VALUE"],
    :duphash=>["VALUE"],
    :expandarray=>["rb_num_t", "rb_num_t"],
    :concatarray=>[],
    :splatarray=>["VALUE"],
    :newhash=>["rb_num_t"],
    :newrange=>["rb_num_t"],
    :pop=>[],
    :dup=>[],
    :dupn=>["rb_num_t"],
    :swap=>[],
    :reverse=>["rb_num_t"],
    :topn=>["rb_num_t"],
    :setn=>["rb_num_t"],
    :adjuststack=>["rb_num_t"],
    :defined=>["rb_num_t", "VALUE", "VALUE"],
    :checkmatch=>["rb_num_t"],
    :checkkeyword=>["lindex_t", "lindex_t"],
    :checktype=>["rb_num_t"],
    :defineclass=>["ID", "ISEQ", "rb_num_t"],
    :definemethod=>["ID", "ISEQ"],
    :definesmethod=>["ID", "ISEQ"],
    :send=>["CALL_DATA", "ISEQ"],
    :invokesuper=>["CALL_DATA", "ISEQ"],
    :invokeblock=>["CALL_DATA"],
    :leave=>[],
    :throw=>["rb_num_t"],
    :jump=>["OFFSET"],
    :branchif=>["OFFSET"],
    :branchunless=>["OFFSET"],
    :branchnil=>["OFFSET"],
    :once=>["ISEQ", "ISE"],
    :invokebuiltin=>["RB_BUILTIN"]}
  • VERSION =
    # File 'lib/typeprof/version.rb', line 2
    "0.21.3"

Class Method Summary

Class Method Details

.analyze(config, cancel_token = nil)

[ GitHub ]

  
# File 'lib/typeprof/config.rb', line 79

def self.analyze(config, cancel_token = nil)
  # Deploy the config to the TypeProf::Config (Note: This is thread local)
  Config.set_current(config)

  if Config.current.options[:stackprof]
    require "stackprof"
    out = "typeprof-stackprof-#{ Config.current.options[:stackprof] }.dump"
    StackProf.start(mode: Config.current.options[:stackprof], out: out, raw: true)
  end

  scratch = Scratch.new
  Builtin.setup_initial_global_env(scratch)

  Config.current.gem_rbs_features.each do |feature|
    Import.import_library(scratch, feature)
  end

  rbs_files = []
  rbs_codes = []
  Config.current.rbs_files.each do |rbs|
    if rbs.is_a?(Array) # [String name, String content]
      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

  def_code_range_table = nil
  caller_code_range_table = nil
  Config.current.rb_files.each do |rb|
    if rb.is_a?(Array) # [String name, String content]
      iseq, def_tbl, caller_tbl = ISeq.compile_str(*rb.reverse)
      def_code_range_table ||= def_tbl
      caller_code_range_table ||= caller_tbl
    else
      iseq = rb
    end
    scratch.add_entrypoint(iseq)
  end

  result = scratch.type_profile(cancel_token)

  if Config.current.options[:lsp]
    return scratch.report_lsp, def_code_range_table, caller_code_range_table
  end

  if Config.current.output.respond_to?(:write)
    scratch.report(result, Config.current.output)
  else
    open(Config.current.output, "w") do |output|
      scratch.report(result, output)
    end
  end

rescue TypeProfError => exc
  exc.report(Config.current.output)

  return nil
ensure
  if Config.current.options[:stackprof] && defined?(StackProf)
    StackProf.stop
    StackProf.results
  end
end

.start_lsp_server(config)

[ GitHub ]

  
# File 'lib/typeprof/lsp.rb', line 6

def self.start_lsp_server(config)
  if config.lsp_options[:stdio]
    $stdin.binmode
    $stdout.binmode
    reader = LSP::Reader.new($stdin)
    writer = LSP::Writer.new($stdout)
    # pipe all builtin print output to stderr to avoid conflicting with lsp
    $stdout = $stderr
    TypeProf::LSP::Server.new(config, reader, writer).run
  else
    Socket.tcp_server_sockets("localhost", config.lsp_options[:port]) do |servs|
      serv = servs[0].local_address
      $stdout << JSON.generate({
        host: serv.ip_address,
        port: serv.ip_port,
        pid: $$,
      })
      $stdout.flush

      $stdout = $stderr

      Socket.accept_loop(servs) do |sock|
        sock.set_encoding("UTF-8")
        begin
          reader = LSP::Reader.new(sock)
          writer = LSP::Writer.new(sock)
          TypeProf::LSP::Server.new(config, reader, writer).run
        ensure
          sock.close
        end
        exit
      end
    end
  end
end

.starting_state(iseq)

[ GitHub ]

  
# File 'lib/typeprof/config.rb', line 148

def self.starting_state(iseq)
  cref = CRef.new(:bottom, Type::Builtin[:obj], false) # object
  recv = Type::Instance.new(Type::Builtin[:obj])
  ctx = Context.new(iseq, cref, nil)
  ep = ExecutionPoint.new(ctx, 0, nil)
  locals = [Type.nil] * iseq.locals.size
  env = Env.new(StaticEnv.new(recv, Type.nil, false, false), locals, [], Utils::HashWrapper.new({}))

  return ep, env
end