module Mirrors

Constants

ProjectRootNotFound

Public Class Methods

class_singleton_invoke(receiver, msg) click to toggle source
# File lib/mirrors/invoke.rb, line 23
def self.class_singleton_invoke(receiver, msg)
  class_singleton_method(msg).bind(receiver).call
end
class_singleton_method(msg) click to toggle source
# File lib/mirrors/invoke.rb, line 27
def self.class_singleton_method(msg)
  @unbound_class_singleton_methods[msg] ||= Class.method(msg).unbind
end
kernel_instance_invoke(receiver, msg) click to toggle source
# File lib/mirrors/invoke.rb, line 31
def self.kernel_instance_invoke(receiver, msg)
  kernel_instance_method(msg).bind(receiver).call
end
kernel_instance_method(msg) click to toggle source
# File lib/mirrors/invoke.rb, line 35
def self.kernel_instance_method(msg)
  @unbound_kernel_instance_methods[msg] ||= Kernel.instance_method(msg)
end
module_instance_invoke(receiver, msg) click to toggle source
# File lib/mirrors/invoke.rb, line 15
def self.module_instance_invoke(receiver, msg)
  module_instance_method(msg).bind(receiver).call
end
module_instance_method(msg) click to toggle source
# File lib/mirrors/invoke.rb, line 19
def self.module_instance_method(msg)
  @unbound_module_instance_methods[msg] ||= Module.instance_method(msg)
end

Public Instance Methods

classes() click to toggle source

This method can be used to query the system for known classes. It is not guaranteed that all possible classes are returned.

@return [Array<ClassMirror>] a list of class mirrors

# File lib/mirrors.rb, line 55
def classes
  instances_of(Class).sort! { |a, b| a.name <=> b.name }
end
implementations_of(str) click to toggle source

Query the system for implementors of a particular message @param [String] the message name @return [Array<MethodMirror>] the implementing methods

# File lib/mirrors.rb, line 78
def implementations_of(str)
  methods = ObjectSpace.each_object(Module).collect do |m|
    ims = m.instance_methods(false).collect { |s| m.instance_method(s) }
    cms = m.methods(false).collect { |s| m.method(s) }
    ims + cms
  end.flatten

  mirrors(methods.select { |m| m.name.to_s == str.to_s })
end
instances_of(klass) click to toggle source

Query the system for objects that are direct instances of the given class. @param [Class] @return [Array<ObjectMirror>] a list of appropriate mirrors for the requested objects

# File lib/mirrors.rb, line 63
def instances_of(klass)
  mirrors(ObjectSpace.each_object(klass).select { |obj| obj.class == klass })
end
modules() click to toggle source

This method can be used to query the system for known modules. It is not guaranteed that all possible modules are returned.

@return [Array<ClassMirror>] a list of class mirrors

# File lib/mirrors.rb, line 47
def modules
  instances_of(Module).sort! { |a, b| a.name <=> b.name }
end
object_by_id(id) click to toggle source

Ask the system to find the object with the given object id @param [Numeric] object id @return [ObjectMirror, NilClass] the object mirror or nil

# File lib/mirrors.rb, line 70
def object_by_id(id)
  obj = ObjectSpace._id2ref(id)
  obj ? reflect(obj) : nil
end
packages() click to toggle source
# File lib/mirrors.rb, line 32
def packages
  packages = {}
  # Object is the top-level.
  Object.constants.each do |const|
    pkg = PackageInference.infer_from_toplevel(const)
    packages[pkg] = true
  end
  toplevel_packages = packages.keys.map { |pkg| pkg.sub(/:.*/, '') }.sort
  package_mirrors(toplevel_packages)
end
project_root() click to toggle source
# File lib/mirrors.rb, line 22
def project_root
  if defined?(Bundler)
    return File.expand_path(Bundler.root)
  end
  if Dir.exist?('.git')
    return File.expand_path(Dir.pwd)
  end
  raise ProjectRootNotFound
end
references_to(str) click to toggle source
# File lib/mirrors.rb, line 88
def references_to(str)
  filtered = {}
  Mirrors.classes.each do |klass|
    klass.methods.each do |m|
      refs = m.references.select { |marker| marker.message.match(str) }
      filtered[m] = refs unless refs.empty?
    end
  end
  filtered
end
reflect(obj) click to toggle source

Create a mirror for a given object in the system under observation. This is the factory method for all mirror instances, interning and cache invalidation will be added here.

@param [Object] @return [Mirror]

# File lib/mirrors.rb, line 105
def reflect(obj)
  klass = basic_class(obj)
  mirror =
    if klass == FieldMirror::Field || klass == Symbol
      case obj.name.to_s
      when /^@@/
        intern_field_mirror(ClassVariableMirror.new(obj))
      when /^@/
        # instance variables not interned as they are not guaranteed to be
        # present in all instances
        InstanceVariableMirror.new(obj)
      else
        intern_field_mirror(ConstantMirror.new(obj))
      end
    elsif klass == Method || klass == UnboundMethod
      intern_method_mirror(MethodMirror.new(obj))
    elsif klass == Class || klass == Module
      intern_class_mirror(ClassMirror.new(obj))
    else
      # TODO: revisit if ObjectMirror delivers value
      ObjectMirror.new(obj)
    end
  raise "badness" unless mirror.is_a?(Mirror)
  mirror
end

Private Instance Methods

basic_class(obj) click to toggle source

find the class of obj

# File lib/mirrors.rb, line 134
def basic_class(obj)
  Mirrors.kernel_instance_invoke(obj, :class)
end
basic_class_name(klass) click to toggle source

find the class name of obj

# File lib/mirrors.rb, line 139
def basic_class_name(klass)
  Mirrors.module_instance_invoke(obj, :name)
end
intern_class_mirror(mirror) click to toggle source
# File lib/mirrors.rb, line 143
def intern_class_mirror(mirror)
  interned = @class_mirrors[mirror.name] ||= mirror
end
intern_field_mirror(mirror) click to toggle source
# File lib/mirrors.rb, line 151
def intern_field_mirror(mirror)
  mirror.defining_class.intern_field_mirror(mirror)
end
intern_method_mirror(mirror) click to toggle source
# File lib/mirrors.rb, line 147
def intern_method_mirror(mirror)
  mirror.defining_class.intern_method_mirror(mirror)
end
mirrors(list) click to toggle source
# File lib/mirrors.rb, line 155
def mirrors(list)
  list.map { |e| reflect(e) }
end
package_mirrors(list) click to toggle source
# File lib/mirrors.rb, line 159
def package_mirrors(list)
  list.map { |e| PackageMirror.reflect(e) }
end