Class: Mirrors::MethodMirror

Inherits:
Mirror
  • Object
show all
Defined in:
lib/mirrors/method_mirror.rb

Overview

A MethodMirror should reflect on methods, but in a more general sense than the Method and UnboundMethod classes in Ruby are able to offer.

In actual execution, a method is pretty much every chunk of code, even loading a file triggers a process not unlike compiling a method (if only for the side-effects). Method mirrors should allow access to the runtime objects, but also to their static representations (bytecode, source, …), their debugging information and statistical information

Instance Method Summary collapse

Methods inherited from Mirror

#initialize, #mirrors?, #reflectee, #subject_id

Constructor Details

This class inherits a constructor from Mirrors::Mirror

Instance Method Details

#argumentsArray<String>

Queries the method for it’s arguments and returns a list of mirrors that hold name and value information.

Returns:

  • (Array<String>)


75
76
77
# File 'lib/mirrors/method_mirror.rb', line 75

def arguments
  @subject.send(:parameters).map { |_, a| a.to_s }
end

#block_argumentString?

Return the value the block argument, or nil

Returns:

  • (String, nil)


45
46
47
# File 'lib/mirrors/method_mirror.rb', line 45

def block_argument
  args(:block).first
end

#bytecodeString?

Returns the disassembled code if available.

Returns:

  • (String, nil)

    human-readable bytedcode dump



138
139
140
141
# File 'lib/mirrors/method_mirror.rb', line 138

def bytecode
  @bytecode ||= iseq.disasm if iseq
  @bytecode
end

#commentString?

Returns The pre-definition comment of this method.

Returns:

  • (String, nil)

    The pre-definition comment of this method



124
125
126
127
128
# File 'lib/mirrors/method_mirror.rb', line 124

def comment
  @subject.send(:comment)
rescue MethodSource::SourceNotFoundError
  nil
end

#defining_classClassMirror

Returns The class this method was originally defined in.

Returns:

  • (ClassMirror)

    The class this method was originally defined in



38
39
40
# File 'lib/mirrors/method_mirror.rb', line 38

def defining_class
  Mirrors.reflect @subject.send(:owner)
end

#fileString?

Returns The filename, if available.

Returns:

  • (String, nil)

    The filename, if available



21
22
23
24
# File 'lib/mirrors/method_mirror.rb', line 21

def file
  sl = source_location
  sl ? sl.first : nil
end

#iseqObject

Returns the instruction sequence for the method (cached)



131
132
133
# File 'lib/mirrors/method_mirror.rb', line 131

def iseq
  @iseq ||= RubyVM::InstructionSequence.of(@subject)
end

#lineFixnum?

Returns The source line, if available.

Returns:

  • (Fixnum, nil)

    The source line, if available



27
28
29
30
# File 'lib/mirrors/method_mirror.rb', line 27

def line
  sl = source_location
  sl && sl.last ? sl.last - 1 : nil
end

#nameObject



158
159
160
# File 'lib/mirrors/method_mirror.rb', line 158

def name
  @subject.name
end

#native_codeRubyVM::InstructionSequence?

Returns the compiled code if available.

Returns:

  • (RubyVM::InstructionSequence, nil)

    native code



154
155
156
# File 'lib/mirrors/method_mirror.rb', line 154

def native_code
  RubyVM::InstructionSequence.of(@subject)
end

#optional_argumentsArray<String>?

Returns names and values of the optional arguments.

Returns:

  • (Array<String>, nil)


60
61
62
# File 'lib/mirrors/method_mirror.rb', line 60

def optional_arguments
  args(:opt)
end

#private?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/mirrors/method_mirror.rb', line 96

def private?
  visibility?(:private)
end

#protected?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/mirrors/method_mirror.rb', line 88

def protected?
  visibility?(:protected)
end

#public?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/mirrors/method_mirror.rb', line 92

def public?
  visibility?(:public)
end

#referencesObject



162
163
164
165
166
# File 'lib/mirrors/method_mirror.rb', line 162

def references
  visitor = Mirrors::ReferencesVisitor.new
  visitor.call(self)
  visitor.markers
end

#required_argumentsArray<String>

Returns the name and possibly values of the required arguments

Returns:

  • (Array<String>)


67
68
69
# File 'lib/mirrors/method_mirror.rb', line 67

def required_arguments
  args(:req)
end

#selectorString

Returns The method name.

Returns:

  • (String)

    The method name



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

def selector
  @subject.name.to_s
end

#sexpString?

Returns the parse tree if available

Returns:

  • (String, nil)

    prettified AST



146
147
148
149
# File 'lib/mirrors/method_mirror.rb', line 146

def sexp
  src = source
  src ? Ripper.sexp(src).pretty_inspect : nil
end

#sourceString?

Returns The source code of this method.

Returns:

  • (String, nil)

    The source code of this method



117
118
119
120
121
# File 'lib/mirrors/method_mirror.rb', line 117

def source
  @source ||= unindent(@subject.send(:source))
rescue MethodSource::SourceNotFoundError
  nil
end

#splat_argumentString?

Returns a field mirror with name and possibly value of the splat argument, or nil, if there is none to this method.

Returns:

  • (String, nil)


53
54
55
# File 'lib/mirrors/method_mirror.rb', line 53

def splat_argument
  args(:rest).first
end

#super_methodObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mirrors/method_mirror.rb', line 100

def super_method
  owner = @subject.send(:owner)

  if owner.is_a?(Class)
    meth = Mirrors
      .class_singleton_method(:allocate)
      .bind(instance)
      .super_method
      .unbind
  else
    meth = @subject.bind(owner).super_method.unbind
  end

  meth ? Mirrors.reflect(meth) : nil
end

#visibilityString

Is the method :public, :private, or :protected?

Returns:

  • (String)


82
83
84
85
86
# File 'lib/mirrors/method_mirror.rb', line 82

def visibility
  return :public  if visibility?(:public)
  return :private if visibility?(:private)
  :protected
end