mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Improve Ruby 2.0 refinement support, closes #738
added lookup_method_via_binding(), using this rather than safe_send we respect the method object introduced by any refinements in the binding. Further work can be done for refinement support -- such as indicating that the method is a refinement, showing the name of the refining module, and so on.
This commit is contained in:
parent
70416d36a0
commit
cddfc409ed
2 changed files with 31 additions and 27 deletions
|
@ -17,6 +17,7 @@ class Pry
|
||||||
# This class wraps the normal `Method` and `UnboundMethod` classes
|
# This class wraps the normal `Method` and `UnboundMethod` classes
|
||||||
# to provide extra functionality useful to Pry.
|
# to provide extra functionality useful to Pry.
|
||||||
class Method
|
class Method
|
||||||
|
extend Helpers::BaseHelpers
|
||||||
include RbxMethod if Helpers::BaseHelpers.rbx?
|
include RbxMethod if Helpers::BaseHelpers.rbx?
|
||||||
include Helpers::DocumentationHelpers
|
include Helpers::DocumentationHelpers
|
||||||
|
|
||||||
|
@ -40,14 +41,14 @@ class Pry
|
||||||
from_binding(target)
|
from_binding(target)
|
||||||
elsif name.to_s =~ /(.+)\#(\S+)\Z/
|
elsif name.to_s =~ /(.+)\#(\S+)\Z/
|
||||||
context, meth_name = $1, $2
|
context, meth_name = $1, $2
|
||||||
from_module(target.eval(context), meth_name)
|
from_module(target.eval(context), meth_name, target)
|
||||||
elsif name.to_s =~ /(.+)\.(\S+)\Z/
|
elsif name.to_s =~ /(.+)\.(\S+)\Z/
|
||||||
context, meth_name = $1, $2
|
context, meth_name = $1, $2
|
||||||
from_obj(target.eval(context), meth_name)
|
from_obj(target.eval(context), meth_name, target)
|
||||||
elsif options[:instance]
|
elsif options[:instance]
|
||||||
from_module(target.eval("self"), name)
|
from_module(target.eval("self"), name, target)
|
||||||
elsif options[:methods]
|
elsif options[:methods]
|
||||||
from_obj(target.eval("self"), name)
|
from_obj(target.eval("self"), name, target)
|
||||||
else
|
else
|
||||||
from_str(name, target, :instance => true) or
|
from_str(name, target, :instance => true) or
|
||||||
from_str(name, target, :methods => true)
|
from_str(name, target, :methods => true)
|
||||||
|
@ -110,6 +111,22 @@ class Pry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# In order to support 2.0 Refinements we need to look up methods
|
||||||
|
# inside the relevant Binding.
|
||||||
|
# @param [Object] obj The owner/receiver of the method.
|
||||||
|
# @param [Symbol] method_name The name of the method.
|
||||||
|
# @param [Symbol] method_type The type of method: :method or :instance_method
|
||||||
|
# @param [Binding] target The binding where the method is looked up.
|
||||||
|
# @return [Method, UnboundMethod] The 'refined' method object.
|
||||||
|
def lookup_method_via_binding(obj, method_name, method_type, target=TOPLEVEL_BINDING)
|
||||||
|
Pry.th[:obj] = obj
|
||||||
|
Pry.th[:name] = method_name
|
||||||
|
receiver = obj.is_a?(Module) ? "Module" : "Kernel"
|
||||||
|
target.eval("::#{receiver}.instance_method(:#{method_type}).bind(Pry.th[:obj]).call(Pry.th[:name])")
|
||||||
|
ensure
|
||||||
|
Pry.th[:obj] = Pry.th[:name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
# Given a `Class` or `Module` and the name of a method, try to
|
# Given a `Class` or `Module` and the name of a method, try to
|
||||||
# instantiate a `Pry::Method` containing the instance method of
|
# instantiate a `Pry::Method` containing the instance method of
|
||||||
# that name. Return `nil` if no such method exists.
|
# that name. Return `nil` if no such method exists.
|
||||||
|
@ -117,8 +134,8 @@ class Pry
|
||||||
# @param [Class, Module] klass
|
# @param [Class, Module] klass
|
||||||
# @param [String] name
|
# @param [String] name
|
||||||
# @return [Pry::Method, nil]
|
# @return [Pry::Method, nil]
|
||||||
def from_class(klass, name)
|
def from_class(klass, name, target=TOPLEVEL_BINDING)
|
||||||
new(safe_send(klass, :instance_method, name)) rescue nil
|
new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue nil
|
||||||
end
|
end
|
||||||
alias from_module from_class
|
alias from_module from_class
|
||||||
|
|
||||||
|
@ -129,10 +146,10 @@ class Pry
|
||||||
# @param [Object] obj
|
# @param [Object] obj
|
||||||
# @param [String] name
|
# @param [String] name
|
||||||
# @return [Pry::Method, nil]
|
# @return [Pry::Method, nil]
|
||||||
def from_obj(obj, name)
|
def from_obj(obj, name, target=TOPLEVEL_BINDING)
|
||||||
new(safe_send(obj, :method, name)) rescue nil
|
new(lookup_method_via_binding(obj, name, :method, target)) rescue nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get all of the instance methods of a `Class` or `Module`
|
# Get all of the instance methods of a `Class` or `Module`
|
||||||
# @param [Class,Module] klass
|
# @param [Class,Module] klass
|
||||||
# @param [Boolean] include_super Whether to include methods from ancestors.
|
# @param [Boolean] include_super Whether to include methods from ancestors.
|
||||||
|
@ -187,15 +204,6 @@ class Pry
|
||||||
end.flatten(1)
|
end.flatten(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Acts like send but ignores any methods defined below Object or Class in the
|
|
||||||
# inheritance hierarchy.
|
|
||||||
# This is required to introspect methods on objects like Net::HTTP::Get that
|
|
||||||
# have overridden the `method` method.
|
|
||||||
def safe_send(obj, method, *args, &block)
|
|
||||||
(Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block)
|
|
||||||
end
|
|
||||||
public :safe_send
|
|
||||||
|
|
||||||
# Get the singleton classes of superclasses that could define methods on
|
# Get the singleton classes of superclasses that could define methods on
|
||||||
# the given class object, and any modules they include.
|
# the given class object, and any modules they include.
|
||||||
# If a module is included at multiple points in the ancestry, only
|
# If a module is included at multiple points in the ancestry, only
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Pry
|
||||||
end
|
end
|
||||||
|
|
||||||
class WrappedModule
|
class WrappedModule
|
||||||
|
include Pry::Helpers::BaseHelpers
|
||||||
include Pry::Helpers::DocumentationHelpers
|
include Pry::Helpers::DocumentationHelpers
|
||||||
|
|
||||||
attr_reader :wrapped
|
attr_reader :wrapped
|
||||||
|
@ -271,16 +272,11 @@ class Pry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME: this method is also found in Pry::Method
|
# @param [String] doc The raw docstring to process.
|
||||||
def safe_send(obj, method, *args, &block)
|
# @return [String] Process docstring markup and strip leading white space.
|
||||||
(Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block)
|
def process_doc(doc)
|
||||||
|
process_comment_markup(strip_leading_hash_and_whitespace_from_ruby_comments(doc))
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [String] doc The raw docstring to process.
|
|
||||||
# @return [String] Process docstring markup and strip leading white space.
|
|
||||||
def process_doc(doc)
|
|
||||||
process_comment_markup(strip_leading_hash_and_whitespace_from_ruby_comments(doc))
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue