Class: Pry::Method

Inherits:
Object show all
Extended by:
Helpers::BaseHelpers
Includes:
CodeObject::Helpers, Helpers::BaseHelpers, Helpers::DocumentationHelpers
Defined in:
lib/pry/method.rb,
lib/pry/method/patcher.rb,
lib/pry/method/disowned.rb,
lib/pry/method/weird_method_locator.rb

Overview

This class wraps the normal `Method` and `UnboundMethod` classes to provide extra functionality useful to Pry.

Direct Known Subclasses

Disowned

Defined Under Namespace

Classes: Disowned, Patcher, WeirdMethodLocator

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::BaseHelpers

colorize_code, command_dependencies_met?, find_command, heading, highlight, jruby?, jruby_19?, mri?, mri_19?, mri_20?, mri_21?, mri_2?, not_a_real_file?, rbx?, safe_send, safe_send, silence_warnings, stagger_output, use_ansi_codes?, windows?, windows_ansi?

Methods included from CodeObject::Helpers

#c_method?, #command?, #module_with_yard_docs?, #real_method_object?

Methods included from Helpers::DocumentationHelpers

get_comment_content, process_comment_markup, process_rdoc, process_yardoc, process_yardoc_tag, strip_comments_from_c_code, strip_leading_whitespace

Constructor Details

#initialize(method, known_info = {}) ⇒ Pry::Method

A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.

Parameters:

  • method (::Method, UnboundMethod, Proc)
  • known_info (Hash) (defaults to: {})

    Can be used to pre-cache expensive to compute stuff.



236
237
238
239
# File 'lib/pry/method.rb', line 236

def initialize(method, known_info={})
  @method = method
  @visibility = known_info[:visibility]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object

Delegate any unknown calls to the wrapped method.



469
470
471
# File 'lib/pry/method.rb', line 469

def method_missing(method_name, *args, &block)
  @method.send(method_name, *args, &block)
end

Class Method Details

.all_from_class(klass, include_super = true) ⇒ Array[Pry::Method]

Get all of the instance methods of a `Class` or `Module`

Parameters:

  • klass (Class, Module)
  • include_super (Boolean) (defaults to: true)

    Whether to include methods from ancestors.

Returns:



142
143
144
145
146
147
148
# File 'lib/pry/method.rb', line 142

def all_from_class(klass, include_super=true)
  %w(public protected private).map do |visibility|
    safe_send(klass, :"#{visibility}_instance_methods", include_super).map do |method_name|
      new(safe_send(klass, :instance_method, method_name), :visibility => visibility.to_sym)
    end
  end.flatten(1)
end

.all_from_common(obj, method_type = nil, include_super = true) ⇒ Object

Deprecated.

please use #all_from_obj instead. the `method_type` argument is ignored.



169
170
171
# File 'lib/pry/method.rb', line 169

def all_from_common(obj, method_type = nil, include_super=true)
  all_from_obj(obj, include_super)
end

.all_from_obj(obj, include_super = true) ⇒ Array[Pry::Method]

Get all of the methods on an `Object`

Parameters:

  • obj (Object)
  • include_super (Boolean) (defaults to: true)

    indicates whether or not to include methods from ancestors.

Returns:



160
161
162
# File 'lib/pry/method.rb', line 160

def all_from_obj(obj, include_super=true)
  all_from_class(singleton_class_of(obj), include_super)
end

.from_binding(b) ⇒ Pry::Method?

Given a `Binding`, try to extract the `::Method` it originated from and use it to instantiate a `Pry::Method`. Return `nil` if this isn't possible.

Parameters:

  • b (Binding)

Returns:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/pry/method.rb', line 74

def from_binding(b)
  meth_name = b.eval('::Kernel.__method__')
  if [:__script__, nil].include?(meth_name)
    nil
  else
    method = begin
               if Object === b.eval('self')
                 new(Kernel.instance_method(:method).bind(b.eval("self")).call(meth_name))
               else
                 new(b.eval('class << self; self; end.instance_method(::Kernel.__method__).bind(self)'))
               end
             rescue NameError, NoMethodError
               Disowned.new(b.eval('self'), meth_name.to_s)
             end

    if WeirdMethodLocator.weird_method?(method, b)
      WeirdMethodLocator.new(method, b).get_method || method
    else
      method
    end
  end
end

.from_class(klass, name, target = TOPLEVEL_BINDING) ⇒ Pry::Method? Also known as: from_module

Given a `Class` or `Module` and the name of a method, try to instantiate a `Pry::Method` containing the instance method of that name. Return `nil` if no such method exists.

Parameters:

  • klass (Class, Module)
  • name (String)
  • target (Binding) (defaults to: TOPLEVEL_BINDING)

    The binding where the method is looked up.

Returns:



121
122
123
# File 'lib/pry/method.rb', line 121

def from_class(klass, name, target=TOPLEVEL_BINDING)
  new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue nil
end

.from_obj(obj, name, target = TOPLEVEL_BINDING) ⇒ Pry::Method?

Given an object and the name of a method, try to instantiate a `Pry::Method` containing the method of that name bound to that object. Return `nil` if no such method exists.

Parameters:

  • obj (Object)
  • name (String)
  • target (Binding) (defaults to: TOPLEVEL_BINDING)

    The binding where the method is looked up.

Returns:



134
135
136
# File 'lib/pry/method.rb', line 134

def from_obj(obj, name, target=TOPLEVEL_BINDING)
  new(lookup_method_via_binding(obj, name, :method, target)) rescue nil
end

.from_str(name, target = TOPLEVEL_BINDING, options = {}) ⇒ Pry::Method?

Given a string representing a method name and optionally a binding to search in, find and return the requested method wrapped in a `Pry::Method` instance.

Parameters:

  • name (String)

    The name of the method to retrieve.

  • target (Binding) (defaults to: TOPLEVEL_BINDING)

    The context in which to search for the method.

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :instance (Boolean)

    Look for an instance method if `name` doesn't contain any context.

  • :methods (Boolean)

    Look for a bound/singleton method if `name` doesn't contain any context.

Returns:

  • (Pry::Method, nil)

    A `Pry::Method` instance containing the requested method, or `nil` if name is `nil` or no method could be located matching the parameters.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/pry/method.rb', line 42

def from_str(name, target=TOPLEVEL_BINDING, options={})
  if name.nil?
    nil
  elsif name.to_s =~ /(.+)\#(\S+)\Z/
    context, meth_name = $1, $2
    from_module(target.eval(context), meth_name, target)
  elsif name.to_s =~ /(.+)(\[\])\Z/
    context, meth_name = $1, $2
    from_obj(target.eval(context), meth_name, target)
  elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/
    context, meth_name = $1, $3
    from_obj(target.eval(context), meth_name, target)
  elsif options[:instance]
    from_module(target.eval("self"), name, target)
  elsif options[:methods]
    from_obj(target.eval("self"), name, target)
  else
    from_str(name, target, :instance => true) or
      from_str(name, target, :methods => true)
  end

rescue Pry::RescuableException
  nil
end

.instance_method_definition?(name, definition_line) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/pry/method.rb', line 205

def instance_method_definition?(name, definition_line)
  /^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*#{Regexp.escape(name)}/ =~ definition_line.strip
end

.instance_resolution_order(klass) ⇒ Array[Class, Module]

Get every `Class` and `Module`, in order, that will be checked when looking for methods on instances of the given `Class` or `Module`. This does not treat singleton classes of classes specially.

Parameters:

  • klass (Class, Module)

Returns:

  • (Array[Class, Module])


191
192
193
194
# File 'lib/pry/method.rb', line 191

def instance_resolution_order(klass)
  # include klass in case it is a singleton class,
  ([klass] + Pry::Method.safe_send(klass, :ancestors)).uniq
end

.lookup_method_via_binding(obj, method_name, method_type, target = TOPLEVEL_BINDING) ⇒ Method, UnboundMethod

In order to support 2.0 Refinements we need to look up methods inside the relevant Binding.

Parameters:

  • obj (Object)

    The owner/receiver of the method.

  • method_name (Symbol)

    The name of the method.

  • method_type (Symbol)

    The type of method: :method or :instance_method

  • target (Binding) (defaults to: TOPLEVEL_BINDING)

    The binding where the method is looked up.

Returns:

  • (Method, UnboundMethod)

    The 'refined' method object.



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

def lookup_method_via_binding(obj, method_name, method_type, target=TOPLEVEL_BINDING)
  Pry.current[:obj] = obj
  Pry.current[:name] = method_name
  receiver = obj.is_a?(Module) ? "Module" : "Kernel"
  target.eval("::#{receiver}.instance_method(:#{method_type}).bind(Pry.current[:obj]).call(Pry.current[:name])")
ensure
  Pry.current[:obj] = Pry.current[:name] = nil
end

.method_definition?(name, definition_line) ⇒ Boolean

Returns:

  • (Boolean)


196
197
198
199
# File 'lib/pry/method.rb', line 196

def method_definition?(name, definition_line)
  singleton_method_definition?(name, definition_line) ||
    instance_method_definition?(name, definition_line)
end

.resolution_order(obj) ⇒ Array[Class, Module]

Get every `Class` and `Module`, in order, that will be checked when looking for an instance method to call on this object.

Parameters:

Returns:

  • (Array[Class, Module])


177
178
179
180
181
182
183
184
# File 'lib/pry/method.rb', line 177

def resolution_order(obj)
  if Class === obj
    singleton_class_resolution_order(obj) + instance_resolution_order(Class)
  else
    klass = singleton_class_of(obj) rescue obj.class
    instance_resolution_order(klass)
  end
end

.singleton_class_of(obj) ⇒ Object



222
223
224
225
226
227
228
# File 'lib/pry/method.rb', line 222

def singleton_class_of(obj)
  begin
    class << obj; self; end
  rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ...
    obj.class
  end
end

.singleton_class_resolution_order(klass) ⇒ Object

Get the singleton classes of superclasses that could define methods on the given class object, and any modules they include. If a module is included at multiple points in the ancestry, only the lowest copy will be returned.



213
214
215
216
217
218
219
220
# File 'lib/pry/method.rb', line 213

def singleton_class_resolution_order(klass)
  ancestors = Pry::Method.safe_send(klass, :ancestors)
  resolution_order = ancestors.grep(Class).map do |anc|
    [singleton_class_of(anc), *singleton_class_of(anc).included_modules]
  end.flatten(1)

  resolution_order.reverse.uniq.reverse - Class.included_modules
end

.singleton_method_definition?(name, definition_line) ⇒ Boolean

Returns:

  • (Boolean)


201
202
203
# File 'lib/pry/method.rb', line 201

def singleton_method_definition?(name, definition_line)
  /^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*self\.#{Regexp.escape(name)}/ =~ definition_line.strip
end

Instance Method Details

#==(obj) ⇒ Boolean

Returns:

  • (Boolean)


447
448
449
450
451
452
453
# File 'lib/pry/method.rb', line 447

def ==(obj)
  if obj.is_a? Pry::Method
    obj == @method
  else
    @method == obj
  end
end

#alias?Boolean

Returns Is the method definitely an alias?

Returns:

  • (Boolean)

    Is the method definitely an alias?



442
443
444
# File 'lib/pry/method.rb', line 442

def alias?
  name != original_name
end

#aliasesArray<String>

Returns All known aliases for the method.

Returns:

  • (Array<String>)

    All known aliases for the method.



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/pry/method.rb', line 425

def aliases
  owner = @method.owner
  # Avoid using `to_sym` on {Method#name}, which returns a `String`, because
  # it won't be garbage collected.
  name = @method.name

  all_methods_to_compare = owner.instance_methods | owner.private_instance_methods
  alias_list = all_methods_to_compare.combination(2).select do |pair|
    pair.include?(name) &&
      owner.instance_method(pair.first) == owner.instance_method(pair.last)
  end.flatten
  alias_list.delete(name)

  alias_list.map(&:to_s)
end

#bound_method?Boolean

Returns Whether the method is bound.

Returns:

  • (Boolean)

    Whether the method is bound.



410
411
412
# File 'lib/pry/method.rb', line 410

def bound_method?
  is_a?(::Method)
end

#commentObject



473
474
475
# File 'lib/pry/method.rb', line 473

def comment
  Pry::Code.from_file(source_file).comment_describing(source_line)
end

#docString?

Returns The documentation for the method, or `nil` if it's unavailable.

Returns:

  • (String, nil)

    The documentation for the method, or `nil` if it's unavailable.



300
301
302
303
304
305
306
307
308
# File 'lib/pry/method.rb', line 300

def doc
  @doc ||= case source_type
    when :c
      info = pry_doc_info
      info.docstring if info
    when :ruby
      get_comment_content(comment)
    end
end

#dynamically_defined?Boolean

Returns Was the method defined outside a source file?

Returns:

  • (Boolean)

    Was the method defined outside a source file?



400
401
402
# File 'lib/pry/method.rb', line 400

def dynamically_defined?
  !!(source_file and source_file =~ /(\(.*\))|<.*>/)
end

#is_a?(klass) ⇒ Boolean Also known as: kind_of?

Parameters:

  • klass (Class)

Returns:

  • (Boolean)


457
458
459
# File 'lib/pry/method.rb', line 457

def is_a?(klass)
  klass == Pry::Method or @method.is_a?(klass)
end

#nameString

Get the name of the method as a String, regardless of the underlying Method#name type.

Returns:

  • (String)


243
244
245
# File 'lib/pry/method.rb', line 243

def name
  @method.name.to_s
end

#name_with_ownerString

Get the name of the method including the class on which it was defined.

Examples:

method(:puts).method_name
=> "Kernel.puts"

Returns:

  • (String)


270
271
272
# File 'lib/pry/method.rb', line 270

def name_with_owner
  "#{wrapped_owner.method_prefix}#{name}"
end

#original_nameString?

Returns The original name the method was defined under, before any aliasing, or `nil` if it can't be determined.

Returns:

  • (String, nil)

    The original name the method was defined under, before any aliasing, or `nil` if it can't be determined.



394
395
396
397
# File 'lib/pry/method.rb', line 394

def original_name
  return nil if source_type != :ruby
  method_name_from_first_line(source.lines.first)
end

#pry_method?Boolean

Returns Was the method defined within the Pry REPL?

Returns:

  • (Boolean)

    Was the method defined within the Pry REPL?



420
421
422
# File 'lib/pry/method.rb', line 420

def pry_method?
  source_file == Pry.eval_path
end

#redefine(source) ⇒ Object

Update the live copy of the method's source.



285
286
287
288
# File 'lib/pry/method.rb', line 285

def redefine(source)
  Patcher.new(self).patch_in_ram source
  Pry::Method(owner.instance_method(name))
end

#respond_to?(method_name) ⇒ Boolean

Parameters:

  • method_name (String, Symbol)

Returns:

  • (Boolean)


464
465
466
# File 'lib/pry/method.rb', line 464

def respond_to?(method_name)
  super or @method.respond_to?(method_name)
end

#signatureString

Returns A representation of the method's signature, including its name and parameters. Optional and “rest” parameters are marked with `*` and block parameters with `&`. If the parameter names are unavailable, they're given numbered names instead. Paraphrased from `awesome_print` gem.

Returns:

  • (String)

    A representation of the method's signature, including its name and parameters. Optional and “rest” parameters are marked with `*` and block parameters with `&`. If the parameter names are unavailable, they're given numbered names instead. Paraphrased from `awesome_print` gem.



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/pry/method.rb', line 360

def signature
  if respond_to?(:parameters)
    args = parameters.inject([]) do |arr, (type, name)|
      name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
      arr << case type
             when :req   then name.to_s
             when :opt   then "#{name}=?"
             when :rest  then "*#{name}"
             when :block then "&#{name}"
             else '?'
             end
    end
  else
    args = (1..arity.abs).map { |i| "arg#{i}" }
    args[-1] = "*#{args[-1]}" if arity < 0
  end

  "#{name}(#{args.join(', ')})"
end

#singleton_method?Boolean

Returns Whether the method is a singleton method.

Returns:

  • (Boolean)

    Whether the method is a singleton method.



415
416
417
# File 'lib/pry/method.rb', line 415

def singleton_method?
  wrapped_owner.singleton_class?
end

#sourceString?

Returns The source code of the method, or `nil` if it's unavailable.

Returns:

  • (String, nil)

    The source code of the method, or `nil` if it's unavailable.



275
276
277
278
279
280
281
282
# File 'lib/pry/method.rb', line 275

def source
  @source ||= case source_type
              when :c
                c_source
              when :ruby
                ruby_source
              end
end

#source?Boolean

Can we get the source code for this method?

Returns:

  • (Boolean)


292
293
294
295
296
# File 'lib/pry/method.rb', line 292

def source?
  !!source
rescue MethodSource::SourceNotFoundError
  false
end

#source_fileString?

Returns The name of the file the method is defined in, or `nil` if the filename is unavailable.

Returns:

  • (String, nil)

    The name of the file the method is defined in, or `nil` if the filename is unavailable.



318
319
320
321
322
323
324
325
326
327
# File 'lib/pry/method.rb', line 318

def source_file
  if source_location.nil?
    if !rbx? and source_type == :c
      info = pry_doc_info
      info.file if info
    end
  else
    source_location.first
  end
end

#source_lineFixnum?

Returns The line of code in `source_file` which begins the method's definition, or `nil` if that information is unavailable.

Returns:

  • (Fixnum, nil)

    The line of code in `source_file` which begins the method's definition, or `nil` if that information is unavailable.



331
332
333
# File 'lib/pry/method.rb', line 331

def source_line
  source_location.nil? ? nil : source_location.last
end

#source_rangeRange?

Returns The range of lines in `source_file` which contain the method's definition, or `nil` if that information is unavailable.

Returns:

  • (Range, nil)

    The range of lines in `source_file` which contain the method's definition, or `nil` if that information is unavailable.



337
338
339
# File 'lib/pry/method.rb', line 337

def source_range
  source_location.nil? ? nil : (source_line)..(source_line + source.lines.count - 1)
end

#source_typeSymbol

Returns The source type of the method. The options are `:ruby` for Ruby methods or `:c` for methods written in C.

Returns:

  • (Symbol)

    The source type of the method. The options are `:ruby` for Ruby methods or `:c` for methods written in C.



312
313
314
# File 'lib/pry/method.rb', line 312

def source_type
  source_location.nil? ? :c : :ruby
end

#super(times = 1) ⇒ Pry::Method?

Returns The wrapped method that is called when you use “super” in the body of this method.

Returns:

  • (Pry::Method, nil)

    The wrapped method that is called when you use “super” in the body of this method.



382
383
384
385
386
387
388
389
390
# File 'lib/pry/method.rb', line 382

def super(times=1)
  if UnboundMethod === @method
    sup = super_using_ancestors(Pry::Method.instance_resolution_order(owner), times)
  else
    sup = super_using_ancestors(Pry::Method.resolution_order(receiver), times)
    sup &&= sup.bind(receiver)
  end
  Pry::Method.new(sup) if sup
end

#unbound_method?Boolean

Returns Whether the method is unbound.

Returns:

  • (Boolean)

    Whether the method is unbound.



405
406
407
# File 'lib/pry/method.rb', line 405

def unbound_method?
  is_a?(::UnboundMethod)
end

#undefined?Boolean

Is the method undefined? (aka `Disowned`)

Returns:

  • (Boolean)

    false



261
262
263
# File 'lib/pry/method.rb', line 261

def undefined?
  false
end

#visibilitySymbol

Returns The visibility of the method. May be `:public`, `:protected`, or `:private`.

Returns:

  • (Symbol)

    The visibility of the method. May be `:public`, `:protected`, or `:private`.



343
344
345
346
347
348
349
350
351
352
353
# File 'lib/pry/method.rb', line 343

def visibility
 @visibility ||= if owner.public_instance_methods.any? { |m| m.to_s == name }
                   :public
                 elsif owner.protected_instance_methods.any? { |m| m.to_s == name }
                   :protected
                 elsif owner.private_instance_methods.any? { |m| m.to_s == name }
                   :private
                 else
                   :none
                 end
end

#wrappedMethod, ...

Get underlying object wrapped by this Pry::Method instance

Returns:

  • (Method, UnboundMethod, Proc)


255
256
257
# File 'lib/pry/method.rb', line 255

def wrapped
  @method
end

#wrapped_ownerPry::Module

Get the owner of the method as a Pry::Module

Returns:

  • (Pry::Module)


249
250
251
# File 'lib/pry/method.rb', line 249

def wrapped_owner
  @wrapped_owner ||= Pry::WrappedModule.new(owner)
end