Class: Pry::Method
- Inherits:
-
Object
- Object
- Pry::Method
- Includes:
- Helpers::DocumentationHelpers, RbxMethod
- Defined in:
- lib/pry/method.rb
Overview
This class wraps the normal Method and UnboundMethod classes
to provide extra functionality useful to Pry.
Direct Known Subclasses
Defined Under Namespace
Classes: Disowned
Class Method Summary (collapse)
-
+ (Array[Pry::Method]) all_from_class(klass, include_super = true)
Get all of the instance methods of a
ClassorModule. -
+ (Object) all_from_common(obj, method_type, include_super = true)
private
See all_from_class and all_from_obj.
-
+ (Array[Pry::Method]) all_from_obj(obj, include_super = true)
Get all of the methods on an
Object. -
+ (Pry::Method?) from_binding(b)
Given a
Binding, try to extract the::Methodit originated from and use it to instantiate aPry::Method. -
+ (Pry::Method?) from_class(klass, name)
(also: from_module)
Given a
ClassorModuleand the name of a method, try to instantiate aPry::Methodcontaining the instance method of that name. -
+ (Pry::Method?) from_obj(obj, name)
Given an object and the name of a method, try to instantiate a
Pry::Methodcontaining the method of that name bound to that object. -
+ (Pry::Method?) from_str(name, target = TOPLEVEL_BINDING, options = {})
Given a string representing a method name and optionally a binding to search in, find and return the requested method wrapped in a
Pry::Methodinstance. -
+ (Array[Class, Module]) instance_resolution_order(klass)
Get every
ClassandModule, in order, that will be checked when looking for methods on instances of the givenClassorModule. -
+ (Array[Class, Module]) resolution_order(obj)
Get every
ClassandModule, in order, that will be checked when looking for an instance method to call on this object. -
+ (Object) safe_send(obj, method, *args, &block)
Acts like send but ignores any methods defined below Object or Class in the inheritance hierarchy.
- + (Object) singleton_class(obj) private
-
+ (Object) singleton_class_resolution_order(klass)
private
Get the singleton classes of superclasses that could define methods on the given class object, and any modules they include.
Instance Method Summary (collapse)
- - (Boolean) ==(obj)
-
- (Boolean) alias?
Is the method definitely an alias?.
-
- (String?) doc
The documentation for the method, or
nilif it's unavailable. -
- (Object) doc_for_pry_method
private
FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate.
-
- (Boolean) dynamically_defined?
Was the method defined outside a source file?.
-
- (Pry::Method) initialize(method, known_info = {})
constructor
A new instance of
Pry::Methodwrapping the given::Method,UnboundMethod, orProc. - - (Boolean) is_a?(klass) (also: #kind_of?)
-
- (Object) method_missing(method_name, *args, &block)
Delegate any unknown calls to the wrapped method.
- - (String?) method_name_from_first_line(first_ln) private
-
- (String) name
Get the name of the method as a String, regardless of the underlying Method#name type.
-
- (String) name_with_owner
Get the name of the method including the class on which it was defined.
-
- (String?) original_name
The original name the method was defined under, before any aliasing, or
nilif it can't be determined. - - (YARD::CodeObjects::MethodObject) pry_doc_info private
-
- (Boolean) pry_method?
Was the method defined within the Pry REPL?.
- - (Boolean) respond_to?(method_name)
-
- (String) signature
A representation of the method's signature, including its name and parameters.
-
- (String?) source
The source code of the method, or
nilif it's unavailable. -
- (String?) source_file
The name of the file the method is defined in, or
nilif the filename is unavailable. -
- (Fixnum?) source_line
The line of code in
source_filewhich begins the method's definition, ornilif that information is unavailable. - - (Object) source_location
-
- (Range?) source_range
The range of lines in
source_filewhich contain the method's definition, ornilif that information is unavailable. -
- (Symbol) source_type
The source type of the method.
-
- (Pry::Method?) super(times = 1)
The wrapped method that is called when you use "super" in the body of this method.
-
- (Method) super_using_ancestors(ancestors, times = 1)
private
The unwrapped super-method.
-
- (Boolean) undefined?
Is the method undefined? (aka
Disowned). -
- (Symbol) visibility
The visibility of the method.
-
- (Pry::Module) wrapped_owner
Get the owner of the method as a Pry::Module.
Methods included from Helpers::DocumentationHelpers
#process_comment_markup, #process_rdoc, #process_yardoc, #process_yardoc_tag, #strip_comments_from_c_code, #strip_leading_hash_and_whitespace_from_ruby_comments, #strip_leading_whitespace
Methods included from RbxMethod
Constructor Details
- (Pry::Method) initialize(method, known_info = {})
A new instance of Pry::Method wrapping the given ::Method, UnboundMethod, or Proc.
215 216 217 218 |
# File 'lib/pry/method.rb', line 215 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
- (Object) method_missing(method_name, *args, &block)
Delegate any unknown calls to the wrapped method.
422 423 424 |
# File 'lib/pry/method.rb', line 422 def method_missing(method_name, *args, &block) @method.send(method_name, *args, &block) end |
Class Method Details
+ (Array[Pry::Method]) all_from_class(klass, include_super = true)
Get all of the instance methods of a Class or Module
136 137 138 |
# File 'lib/pry/method.rb', line 136 def all_from_class(klass, include_super=true) all_from_common(klass, :instance_method, include_super) end |
+ (Object) all_from_common(obj, method_type, include_super = true) (private)
See all_from_class and all_from_obj.
If method_type is :instance_method, obj must be a Class or a Module
If method_type is :method, obj can be any Object
N.B. we pre-cache the visibility here to avoid O(N²) behaviour in "ls".
178 179 180 181 182 183 184 |
# File 'lib/pry/method.rb', line 178 def all_from_common(obj, method_type, include_super=true) %w(public protected private).map do |visibility| safe_send(obj, :#{visibility}_#{method_type}s", include_super).map do |method_name| new(safe_send(obj, method_type, method_name), :visibility => visibility.to_sym) end end.flatten(1) end |
+ (Array[Pry::Method]) all_from_obj(obj, include_super = true)
Get all of the methods on an Object
144 145 146 |
# File 'lib/pry/method.rb', line 144 def all_from_obj(obj, include_super=true) all_from_common(obj, :method, include_super) end |
+ (Pry::Method?) from_binding(b)
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.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/pry/method.rb', line 64 def from_binding(b) meth_name = b.eval('__method__') if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name) nil else method = begin new(b.eval("Object.instance_method(:method).bind(self).call(#{meth_name.to_s.inspect})")) rescue NameError, NoMethodError Disowned.new(b.eval('self'), meth_name.to_s) end # it's possible in some cases that the method we find by this approach is a sub-method of # the one we're currently in, consider: # # class A; def b; binding.pry; end; end # class B < A; def b; super; end; end # # Given that we can normally find the source_range of methods, and that we know which # __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases. # # This obviously won't work if the source is unavaiable for some reason, or if both # methods have the same __FILE__ and __LINE__, or if we're in rbx where b.eval('__LINE__') # is broken. # guess = method while guess # needs rescue if this is a Disowned method or a C method or something... # TODO: Fix up the exception handling so we don't need a bare rescue if (guess.source_file && guess.source_range rescue false) && File.(guess.source_file) == File.(b.eval('__FILE__')) && guess.source_range.include?(b.eval('__LINE__')) return guess else guess = guess.super end end # Uhoh... none of the methods in the chain had the right __FILE__ and __LINE__ # This may be caused by rbx https://github.com/rubinius/rubinius/issues/953, # or other unknown circumstances (TODO: we should warn the user when this happens) method end end |
+ (Pry::Method?) from_class(klass, name) 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.
116 117 118 |
# File 'lib/pry/method.rb', line 116 def from_class(klass, name) new(safe_send(klass, :instance_method, name)) rescue nil end |
+ (Pry::Method?) from_obj(obj, name)
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.
128 129 130 |
# File 'lib/pry/method.rb', line 128 def from_obj(obj, name) new(safe_send(obj, :method, name)) rescue nil end |
+ (Pry::Method?) from_str(name, target = TOPLEVEL_BINDING, options = {})
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.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/pry/method.rb', line 38 def from_str(name, target=TOPLEVEL_BINDING, ={}) if name.nil? from_binding(target) elsif name.to_s =~ /(.+)\#(\S+)\Z/ context, meth_name = $1, $2 from_module(target.eval(context), meth_name) elsif name.to_s =~ /(.+)\.(\S+)\Z/ context, meth_name = $1, $2 from_obj(target.eval(context), meth_name) elsif [:instance] from_module(target.eval("self"), name) elsif [:methods] from_obj(target.eval("self"), name) else from_str(name, target, :instance => true) or from_str(name, target, :methods => true) end end |
+ (Array[Class, Module]) instance_resolution_order(klass)
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.
166 167 168 169 |
# File 'lib/pry/method.rb', line 166 def instance_resolution_order(klass) # include klass in case it is a singleton class, ([klass] + klass.ancestors).uniq end |
+ (Array[Class, Module]) resolution_order(obj)
Get every Class and Module, in order, that will be checked when looking
for an instance method to call on this object.
152 153 154 155 156 157 158 159 |
# File 'lib/pry/method.rb', line 152 def resolution_order(obj) if Class === obj singleton_class_resolution_order(obj) + instance_resolution_order(Class) else klass = singleton_class(obj) rescue obj.class instance_resolution_order(klass) end end |
+ (Object) safe_send(obj, method, *args, &block)
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.
190 191 192 |
# File 'lib/pry/method.rb', line 190 def safe_send(obj, method, *args, &block) (Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block) end |
+ (Object) singleton_class(obj) (private)
207 |
# File 'lib/pry/method.rb', line 207 def singleton_class(obj); class << obj; self; end end |
+ (Object) singleton_class_resolution_order(klass) (private)
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.
199 200 201 202 203 204 205 |
# File 'lib/pry/method.rb', line 199 def singleton_class_resolution_order(klass) resolution_order = klass.ancestors.map do |anc| [singleton_class(anc)] + singleton_class(anc).included_modules if anc.is_a?(Class) end.compact.flatten(1) resolution_order.reverse.uniq.reverse - Class.included_modules end |
Instance Method Details
- (Boolean) ==(obj)
400 401 402 403 404 405 406 |
# File 'lib/pry/method.rb', line 400 def ==(obj) if obj.is_a? Pry::Method obj == @method else @method == obj end end |
- (Boolean) alias?
Is the method definitely an alias?
395 396 397 |
# File 'lib/pry/method.rb', line 395 def alias? name != original_name end |
- (String?) doc
The documentation for the method, or nil if it's
unavailable.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/pry/method.rb', line 270 def doc @doc ||= case source_type when :c info = pry_doc_info info.docstring if info when :ruby if Helpers::BaseHelpers.rbx? && !pry_method? strip_leading_hash_and_whitespace_from_ruby_comments(core_doc) elsif pry_method? strip_leading_hash_and_whitespace_from_ruby_comments(doc_for_pry_method) else strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment) end end end |
- (Object) doc_for_pry_method (private)
FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
# File 'lib/pry/method.rb', line 438 def doc_for_pry_method _, line_num = source_location buffer = "" Pry.line_buffer[0..(line_num - 1)].each do |line| # Add any line that is a valid ruby comment, # but clear as soon as we hit a non comment line. if (line =~ /^\s*#/) || (line =~ /^\s*$/) buffer << line.lstrip else buffer.replace("") end end buffer end |
- (Boolean) dynamically_defined?
Was the method defined outside a source file?
385 386 387 |
# File 'lib/pry/method.rb', line 385 def dynamically_defined? !!(source_file and source_file =~ /(\(.*\))|<.*>/) end |
- (Boolean) is_a?(klass) Also known as: kind_of?
410 411 412 |
# File 'lib/pry/method.rb', line 410 def is_a?(klass) klass == Pry::Method or @method.is_a?(klass) end |
- (String?) method_name_from_first_line(first_ln) (private)
471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/pry/method.rb', line 471 def method_name_from_first_line(first_ln) return nil if first_ln.strip !~ /^def / tokens = CodeRay.scan(first_ln, :ruby) tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens) tokens.each_cons(2) do |t1, t2| if t2.last == :method || t2.last == :ident && t1 == [".", :operator] return t2.first end end nil end |
- (String) name
Get the name of the method as a String, regardless of the underlying Method#name type.
222 223 224 |
# File 'lib/pry/method.rb', line 222 def name @method.name.to_s end |
- (String) name_with_owner
Get the name of the method including the class on which it was defined.
243 244 245 |
# File 'lib/pry/method.rb', line 243 def name_with_owner "#{wrapped_owner.method_prefix}#{name}" end |
- (String?) original_name
The original name the method was defined under,
before any aliasing, or nil if it can't be determined.
379 380 381 382 |
# File 'lib/pry/method.rb', line 379 def original_name return nil if source_type != :ruby method_name_from_first_line(source.lines.first) end |
- (YARD::CodeObjects::MethodObject) pry_doc_info (private)
429 430 431 432 433 434 435 |
# File 'lib/pry/method.rb', line 429 def pry_doc_info if Pry.config.has_pry_doc Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)" else raise CommandError, "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation." end end |
- (Boolean) pry_method?
Was the method defined within the Pry REPL?
390 391 392 |
# File 'lib/pry/method.rb', line 390 def pry_method? source_file == Pry.eval_path end |
- (Boolean) respond_to?(method_name)
417 418 419 |
# File 'lib/pry/method.rb', line 417 def respond_to?(method_name) super or @method.respond_to?(method_name) end |
- (String) signature
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.
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/pry/method.rb', line 345 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 |
- (String?) source
The source code of the method, or nil if it's unavailable.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/pry/method.rb', line 248 def source @source ||= case source_type when :c info = pry_doc_info if info and info.source code = strip_comments_from_c_code(info.source) end when :ruby if Helpers::BaseHelpers.rbx? && !pry_method? code = core_code elsif pry_method? code = Pry::Code.retrieve_complete_expression_from(Pry.line_buffer[source_line..-1]) else code = @method.source end strip_leading_whitespace(code) end end |
- (String?) source_file
The name of the file the method is defined in, or
nil if the filename is unavailable.
303 304 305 306 307 308 309 310 311 312 |
# File 'lib/pry/method.rb', line 303 def source_file if source_location.nil? if !Helpers::BaseHelpers.rbx? and source_type == :c info = pry_doc_info info.file if info end else source_location.first end end |
- (Fixnum?) source_line
The line of code in source_file which begins
the method's definition, or nil if that information is unavailable.
316 317 318 |
# File 'lib/pry/method.rb', line 316 def source_line source_location.nil? ? nil : source_location.last end |
- (Object) source_location
292 293 294 295 296 297 298 299 |
# File 'lib/pry/method.rb', line 292 def source_location if @method.source_location && Helpers::BaseHelpers.rbx? file, line = @method.source_location [RbxPath.convert_path_to_full(file), line] else @method.source_location end end |
- (Range?) source_range
The range of lines in source_file which contain
the method's definition, or nil if that information is unavailable.
322 323 324 |
# File 'lib/pry/method.rb', line 322 def source_range source_location.nil? ? nil : (source_line)..(source_line + source.lines.count - 1) end |
- (Symbol) source_type
The source type of the method. The options are
:ruby for Ruby methods or :c for methods written in C.
288 289 290 |
# File 'lib/pry/method.rb', line 288 def source_type source_location.nil? ? :c : :ruby end |
- (Pry::Method?) super(times = 1)
The wrapped method that is called when you use "super" in the body of this method.
367 368 369 370 371 372 373 374 375 |
# File 'lib/pry/method.rb', line 367 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 |
- (Method) super_using_ancestors(ancestors, times = 1) (private)
The unwrapped super-method
457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/pry/method.rb', line 457 def super_using_ancestors(ancestors, times=1) next_owner = self.owner times.times do i = ancestors.index(next_owner) + 1 while ancestors[i] && !(ancestors[i].method_defined?(name) || ancestors[i].private_method_defined?(name)) i += 1 end next_owner = ancestors[i] or return nil end next_owner.instance_method(name) rescue nil end |
- (Boolean) undefined?
Is the method undefined? (aka Disowned)
234 235 236 |
# File 'lib/pry/method.rb', line 234 def undefined? false end |
- (Symbol) visibility
The visibility of the method. May be :public,
:protected, or :private.
328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/pry/method.rb', line 328 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 |
- (Pry::Module) wrapped_owner
Get the owner of the method as a Pry::Module
228 229 230 |
# File 'lib/pry/method.rb', line 228 def wrapped_owner @wrapped_owner ||= Pry::WrappedModule.new(owner) end |