Module: Mirrors

Extended by:
Mirrors
Included in:
Mirrors
Defined in:
lib/mirrors.rb,
lib/mirrors/invoke.rb,
lib/mirrors/mirror.rb,
lib/mirrors/class_mirror.rb,
lib/mirrors/field_mirror.rb,
lib/mirrors/index/marker.rb,
lib/mirrors/index/indexer.rb,
lib/mirrors/method_mirror.rb,
lib/mirrors/object_mirror.rb,
lib/mirrors/package_mirror.rb,
lib/mirrors/package_inference.rb,
lib/mirrors/visitors/iseq_visitor.rb,
lib/mirrors/visitors/disasm_visitor.rb,
lib/mirrors/visitors/references_visitor.rb,
lib/mirrors/field_mirror/constant_mirror.rb,
lib/mirrors/field_mirror/class_variable_mirror.rb,
lib/mirrors/field_mirror/instance_variable_mirror.rb,
lib/mirrors/package_inference/class_to_file_resolver.rb

Defined Under Namespace

Modules: Index, PackageInference Classes: ClassMirror, ClassVariableMirror, ConstantMirror, DisasmVisitor, FieldMirror, ISeqVisitor, InstanceVariableMirror, Marker, MethodMirror, Mirror, ObjectMirror, PackageMirror, ReferencesVisitor

Constant Summary collapse

ProjectRootNotFound =
Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.class_singleton_invoke(receiver, msg) ⇒ Object



23
24
25
# 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) ⇒ Object



27
28
29
# 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) ⇒ Object



31
32
33
# 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) ⇒ Object



35
36
37
# 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) ⇒ Object



15
16
17
# 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) ⇒ Object



19
20
21
# File 'lib/mirrors/invoke.rb', line 19

def self.module_instance_method(msg)
  @unbound_module_instance_methods[msg] ||= Module.instance_method(msg)
end

Instance Method Details

#classesArray<ClassMirror>

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

Returns:



55
56
57
# File 'lib/mirrors.rb', line 55

def classes
  instances_of(Class).sort! { |a, b| a.name <=> b.name }
end

#implementations_of(str) ⇒ Array<MethodMirror>

Query the system for implementors of a particular message

Parameters:

  • the (String)

    message name

Returns:



78
79
80
81
82
83
84
85
86
# 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) ⇒ Array<ObjectMirror>

Query the system for objects that are direct instances of the given class.

Parameters:

Returns:

  • (Array<ObjectMirror>)

    a list of appropriate mirrors for the requested objects



63
64
65
# File 'lib/mirrors.rb', line 63

def instances_of(klass)
  mirrors(ObjectSpace.each_object(klass).select { |obj| obj.class == klass })
end

#modulesArray<ClassMirror>

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

Returns:



47
48
49
# File 'lib/mirrors.rb', line 47

def modules
  instances_of(Module).sort! { |a, b| a.name <=> b.name }
end

#object_by_id(id) ⇒ ObjectMirror, NilClass

Ask the system to find the object with the given object id

Parameters:

  • object (Numeric)

    id

Returns:



70
71
72
73
# File 'lib/mirrors.rb', line 70

def object_by_id(id)
  obj = ObjectSpace._id2ref(id)
  obj ? reflect(obj) : nil
end

#packagesObject



32
33
34
35
36
37
38
39
40
41
# 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_rootObject



22
23
24
25
26
27
28
29
30
# 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) ⇒ Object



88
89
90
91
92
93
94
95
96
97
# 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) ⇒ Mirror

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.

Parameters:

  • (Object)

Returns:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# 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