Class: Mirrors::ClassMirror

Inherits:
ObjectMirror show all
Defined in:
lib/mirrors/class_mirror.rb

Overview

A specific mirror for a class, that includes all the capabilites and information we can gather about classes.

Constant Summary collapse

MODULE_INSPECT =

to work around overridden ‘name` methods

Module.instance_method(:inspect)

Instance Method Summary collapse

Methods inherited from ObjectMirror

#target_class, #variables

Methods inherited from Mirror

#mirrors?, #reflectee, #subject_id

Constructor Details

#initialize(obj) ⇒ ClassMirror

Returns a new instance of ClassMirror.



5
6
7
8
9
# File 'lib/mirrors/class_mirror.rb', line 5

def initialize(obj)
  super(obj)
  @field_mirrors = {}
  @method_mirrors = {}
end

Instance Method Details

#ancestorsArray<ClassMirror>

The list of ancestors

Returns:



87
88
89
# File 'lib/mirrors/class_mirror.rb', line 87

def ancestors
  mirrors(@subject.ancestors)
end

#class_instance_variablesArray<FieldMirror>

The known class variables.

Returns:

See Also:

  • #instance_variables


33
34
35
# File 'lib/mirrors/class_mirror.rb', line 33

def class_instance_variables
  field_mirrors(@subject.instance_variables)
end

#class_variablesArray<FieldMirror>

The known class variables.

Returns:

See Also:

  • #instance_variables


26
27
28
# File 'lib/mirrors/class_mirror.rb', line 26

def class_variables
  field_mirrors(@subject.class_variables)
end

#constant(str) ⇒ ClassMirror?

Searches for the named constant in the mirrored namespace. May include a colon (::) separated constant path. This may trigger an autoload!

Returns:

  • (ClassMirror, nil)

    the requested constant, or nil



104
105
106
107
108
109
110
111
# File 'lib/mirrors/class_mirror.rb', line 104

def constant(str)
  path = str.to_s.split("::")
  c = path[0..-2].inject(@subject) { |klass, s| klass.const_get(s) }
  field_mirror (c || @subject), path.last
rescue NameError => e
  p e
  nil
end

#constantsArray<FieldMirror>

The constants defined within this class. This includes nested classes and modules, but also all other kinds of constants.

Returns:



95
96
97
# File 'lib/mirrors/class_mirror.rb', line 95

def constants
  field_mirrors(@subject.constants)
end

#demodulized_nameObject



185
186
187
# File 'lib/mirrors/class_mirror.rb', line 185

def demodulized_name
  name.split('::').last
end

#fieldsObject



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

def fields
  [constants, class_variables, class_instance_variables, instance_variables].flatten
end

#intern_field_mirror(mirror) ⇒ Object



193
194
195
# File 'lib/mirrors/class_mirror.rb', line 193

def intern_field_mirror(mirror)
  @field_mirrors[mirror.name] ||= mirror
end

#intern_method_mirror(mirror) ⇒ Object



189
190
191
# File 'lib/mirrors/class_mirror.rb', line 189

def intern_method_mirror(mirror)
  @method_mirrors[mirror.name] ||= mirror
end

#is_classObject



11
12
13
# File 'lib/mirrors/class_mirror.rb', line 11

def is_class
  @subject.is_a?(Class)
end

#method(name) ⇒ MethodMirror?

The instance method of this class or any of its superclasses that has the specified selector

Returns:

  • (MethodMirror, nil)

    the method or nil, if none was found



171
172
173
# File 'lib/mirrors/class_mirror.rb', line 171

def method(name)
  Mirrors.reflect @subject.instance_method(name)
end

#methodsArray<MethodMirror>

The instance methods of this class. To get to the class methods, ask the #singleton_class for its methods.

Returns:



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/mirrors/class_mirror.rb', line 149

def methods
  pub_names  = @subject.public_instance_methods(false)
  prot_names = @subject.protected_instance_methods(false)
  priv_names = @subject.private_instance_methods(false)

  mirrors = []
  pub_names.sort.each do |n|
    mirrors << Mirrors.reflect(@subject.instance_method(n))
  end
  prot_names.sort.each do |n|
    mirrors << Mirrors.reflect(@subject.instance_method(n))
  end
  priv_names.sort.each do |n|
    mirrors << Mirrors.reflect(@subject.instance_method(n))
  end
  mirrors
end

#mixinsArray<ClassMirror>

The mixins included in the ancestors of this class.

Returns:



66
67
68
# File 'lib/mirrors/class_mirror.rb', line 66

def mixins
  mirrors(@subject.ancestors.reject { |m| m.is_a?(Class) })
end

#nameObject



177
178
179
180
181
182
183
# File 'lib/mirrors/class_mirror.rb', line 177

def name
  MODULE_INSPECT.bind(@subject).call
rescue
  puts @subject.inspect
  puts @subject.class
  raise
end

#nested_class_countObject



141
142
143
# File 'lib/mirrors/class_mirror.rb', line 141

def nested_class_count
  nested_classes.count
end

#nested_classesArray<ClassMirror>

The classes nested within the subject. Should not trigger autloads!

Returns:



131
132
133
134
135
136
137
138
139
# File 'lib/mirrors/class_mirror.rb', line 131

def nested_classes
  nc = @subject.constants.collect do |c|
    # do not trigger autoloads
    if @subject.const_defined?(c) && !@subject.autoload?(c)
      @subject.const_get(c)
    end
  end
  mirrors(nc.compact.select { |c| c.is_a?(Module) }.sort_by(&:name))
end

#nestingArray<ClassMirror>

The full nesting.

Returns:



116
117
118
119
120
121
122
123
124
125
# File 'lib/mirrors/class_mirror.rb', line 116

def nesting
  ary = []
  @subject.name.split('::').inject(Object) do |klass, str|
    ary << klass.const_get(str)
    ary.last
  end
  ary.reverse
rescue NameError
  [@subject]
end

#packageObject



15
16
17
# File 'lib/mirrors/class_mirror.rb', line 15

def package
  # TODO(burke)
end

#singleton_classClassMirror

The singleton class of this class

Returns:



52
53
54
# File 'lib/mirrors/class_mirror.rb', line 52

def singleton_class
  Mirrors.reflect(@subject.singleton_class)
end

#singleton_class?true, false

Predicate to determine whether the subject is a singleton class

Returns:

  • (true, false)


59
60
61
# File 'lib/mirrors/class_mirror.rb', line 59

def singleton_class?
  name.match(/^\#<Class:.*>$/)
end

#source_filesArray<String,File>

The source files this class is defined and/or extended in.

Returns:

  • (Array<String,File>)


40
41
42
43
44
45
46
47
# File 'lib/mirrors/class_mirror.rb', line 40

def source_files
  locations = @subject.instance_methods(false).collect do |name|
    method = @subject.instance_method(name)
    sl = method.source_location
    sl.first if sl
  end
  locations.compact.uniq
end

#subclassesArray<ClassMirror>

The known subclasses

Returns:



80
81
82
# File 'lib/mirrors/class_mirror.rb', line 80

def subclasses
  mirrors(ObjectSpace.each_object(Class).select { |a| a.superclass == @subject })
end

#superclassClassMirror

The direct superclass

Returns:



73
74
75
# File 'lib/mirrors/class_mirror.rb', line 73

def superclass
  Mirrors.reflect(@subject.superclass)
end