class Argtrace::TypeLib

Store of signatures

Constants

CLASS_NAME_PATTERN
NORMAL_METHOD_NAME_PATTERN
OPERATOR_METHOD_NAME_PATTERN

Public Class Methods

new() click to toggle source
# File lib/argtrace/typelib.rb, line 12
def initialize
  @lib = Hash.new{|hklass, klass|
    hklass[klass] = Hash.new{|hmethod, method_id|
      hmethod[method_id] = [nil, nil]
    }
  }
  @api_class_cache = {}
  @api_symbol_cache = {}
end

Public Instance Methods

api_class?(klass) click to toggle source
# File lib/argtrace/typelib.rb, line 23
def api_class?(klass)
  unless @api_class_cache.key?(klass)
    if /\A(#{CLASS_NAME_PATTERN})(::#{CLASS_NAME_PATTERN})*\z/ =~ klass.to_s
      @api_class_cache[klass] = true
    else
      # this must not be interface class
      @api_class_cache[klass] = false
    end
  end
  return @api_class_cache[klass]
end
api_method?(method_id) click to toggle source
# File lib/argtrace/typelib.rb, line 37
def api_method?(method_id)
  unless @api_symbol_cache.key?(method_id)
    if /\A((#{NORMAL_METHOD_NAME_PATTERN})|(#{OPERATOR_METHOD_NAME_PATTERN}))\z/ =~ method_id.to_s
      @api_symbol_cache[method_id] = true
    else
      # this must not be interface method
      @api_symbol_cache[method_id] = false
    end
  end
  return @api_symbol_cache[method_id]
end
discard_noise_from_signature(signature) click to toggle source

remove non-api class from type signature

# File lib/argtrace/typelib.rb, line 74
def discard_noise_from_signature(signature)
  signature.params.each do |param|
    if param.mode == :block
      discard_noise_from_signature(param.type)
    else
      discard_noise_from_typeunion(param.type)
    end
  end
  discard_noise_from_typeunion(signature.return_type)
end
discard_noise_from_typeunion(typeunion) click to toggle source
# File lib/argtrace/typelib.rb, line 85
def discard_noise_from_typeunion(typeunion)
  return unless typeunion
  typeunion.union.delete_if{|type| noise_type?(type)}
end
learn(signature) click to toggle source

add signature into type library

# File lib/argtrace/typelib.rb, line 107
def learn(signature)
  sig = ready_signature(signature)
  if sig
    discard_noise_from_signature(signature)
    sig.merge(signature.params, signature.return_type)
  else
    # skip
    # $stderr.puts [:skip, signature].inspect
  end
end
lib() click to toggle source

class => { method_id => [normal_method_signature, singleton_method_signature] }

# File lib/argtrace/typelib.rb, line 8
def lib
  @lib
end
noise_type?(type) click to toggle source
# File lib/argtrace/typelib.rb, line 90
def noise_type?(type)
  if type.data.is_a?(Symbol)
    return false
  end
  if type.data.is_a?(Array)
    if type.subdata == nil
      return false
    end
    return !api_class?(type.subdata)
  end
  if type.data.is_a?(Class)
    return !api_class?(type.data)
  end
  raise "Unexpected type data : #{type}"
end
ready_signature(signature) click to toggle source
# File lib/argtrace/typelib.rb, line 49
def ready_signature(signature)
  return nil unless api_class?(signature.defined_class)
  return nil unless api_method?(signature.method_id)

  # DEBUG:
  # if not @lib.key?(signature.defined_class)
  #   p [signature.defined_class, signature.method_id, signature.defined_class.to_s, signature.method_id.to_s]
  # elsif not @lib[signature.defined_class].key?(signature.method_id)
  #   p [signature.defined_class, signature.method_id, signature.defined_class.to_s, signature.method_id.to_s]
  # end

  pair = @lib[signature.defined_class][signature.method_id]
  index = signature.is_singleton_method ? 1 : 0
  unless pair[index]
    sig = Signature.new
    sig.defined_class = signature.defined_class
    sig.method_id = signature.method_id
    sig.is_singleton_method = signature.is_singleton_method
    sig.return_type = nil
    pair[index] = sig
  end
  return pair[index]
end
to_rbs() click to toggle source
# File lib/argtrace/typelib.rb, line 118
def to_rbs
  # TODO: should I output class inheritance info ?
  # TODO: private/public
  # TODO: attr_reader/attr_writer/attr_accessor
  mod_root = OutputModule.new

  # DEBUG:
  # $stderr.puts @lib.inspect

  @lib.keys.sort_by{|x| x.to_s}.each do |klass|
    klass_methods = @lib[klass]

    # output instance method first, and then output singleton method.
    [0, 1].each do |instance_or_singleton|
      klass_methods.keys.sort.each do |method_id|
        sig = klass_methods[method_id][instance_or_singleton]
        next unless sig

        begin
          mod_root.add_signature(sig)
        rescue => e
          $stderr.puts "----- argtrace bug -----"
          $stderr.puts "#{klass}::#{method_id} (#{sig})"
          $stderr.puts e.full_message
          $stderr.puts "------------------------"
          raise
        end
      end
    end
  end

  mod_root.to_rbs
end