Class: Pry::Method
- Extended by:
- Forwardable, Helpers::BaseHelpers
- 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
Defined Under Namespace
Classes: Disowned, Patcher, WeirdMethodLocator
Constant Summary
Constants included from Helpers::DocumentationHelpers
Helpers::DocumentationHelpers::YARD_TAGS
Class Method Summary collapse
-
.all_from_class(klass, include_super = true) ⇒ Array[Pry::Method]
Get all of the instance methods of a ‘Class` or `Module`.
-
.all_from_obj(obj, include_super = true) ⇒ Array[Pry::Method]
Get all of the methods on an ‘Object`.
-
.from_binding(binding) ⇒ Pry::Method?
Given a ‘Binding`, try to extract the `::Method` it originated from and use it to instantiate a `Pry::Method`.
-
.from_class(klass, name, target = TOPLEVEL_BINDING) ⇒ Pry::Method?
(also: 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.
-
.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.
-
.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.
- .instance_method_definition?(name, definition_line) ⇒ Boolean
-
.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`.
-
.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.
- .method_definition?(name, definition_line) ⇒ Boolean
-
.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.
- .singleton_class_of(obj) ⇒ Object
-
.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.
- .singleton_method_definition?(name, definition_line) ⇒ Boolean
Instance Method Summary collapse
- #==(other) ⇒ Boolean
-
#alias? ⇒ Boolean
Is the method definitely an alias?.
-
#aliases ⇒ Array<String>
All known aliases for the method.
-
#bound_method? ⇒ Boolean
Whether the method is bound.
- #comment ⇒ Object
-
#doc ⇒ String?
The documentation for the method, or ‘nil` if it’s unavailable.
-
#dynamically_defined? ⇒ Boolean
Was the method defined outside a source file?.
-
#initialize(method, known_info = {}) ⇒ Pry::Method
constructor
A new instance of ‘Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
- #is_a?(klass) ⇒ Boolean (also: #kind_of?)
-
#method_missing(method_name, *args, &block) ⇒ Object
Delegate any unknown calls to the wrapped method.
-
#name ⇒ String
Get the name of the method as a String, regardless of the underlying Method#name type.
-
#name_with_owner ⇒ String
Get the name of the method including the class on which it was defined.
-
#original_name ⇒ String?
The original name the method was defined under, before any aliasing, or ‘nil` if it can’t be determined.
-
#pry_method? ⇒ Boolean
Was the method defined within the Pry REPL?.
-
#redefine(source) ⇒ Object
Update the live copy of the method’s source.
- #respond_to?(method_name, include_all = false) ⇒ Boolean
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
#signature ⇒ String
A representation of the method’s signature, including its name and parameters.
-
#singleton_method? ⇒ Boolean
Whether the method is a singleton method.
-
#source ⇒ String?
The source code of the method, or ‘nil` if it’s unavailable.
-
#source? ⇒ Boolean
Can we get the source code for this method?.
-
#source_file ⇒ String?
The name of the file the method is defined in, or ‘nil` if the filename is unavailable.
-
#source_line ⇒ Fixnum?
The line of code in ‘source_file` which begins the method’s definition, or ‘nil` if that information is unavailable.
-
#source_range ⇒ Range?
The range of lines in ‘source_file` which contain the method’s definition, or ‘nil` if that information is unavailable.
-
#source_type ⇒ Symbol
The source type of the method.
-
#super(times = 1) ⇒ Pry::Method?
The wrapped method that is called when you use “super” in the body of this method.
-
#unbound_method? ⇒ Boolean
Whether the method is unbound.
-
#undefined? ⇒ Boolean
Is the method undefined? (aka ‘Disowned`).
-
#visibility ⇒ Symbol
The visibility of the method.
-
#wrapped ⇒ Method, ...
Get underlying object wrapped by this Pry::Method instance.
-
#wrapped_owner ⇒ Pry::Module
Get the owner of the method as a Pry::Module.
Methods included from Helpers::BaseHelpers
colorize_code, find_command, heading, highlight, not_a_real_file?, safe_send, silence_warnings, stagger_output, use_ansi_codes?
Methods included from Forwardable
Methods included from CodeObject::Helpers
#c_method?, #c_module?, #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`.
263 264 265 266 |
# File 'lib/pry/method.rb', line 263 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.
503 504 505 506 507 508 509 |
# File 'lib/pry/method.rb', line 503 def method_missing(method_name, *args, &block) if @method.respond_to?(method_name) @method.__send__(method_name, *args, &block) else super end 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`
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/pry/method.rb', line 161 def all_from_class(klass, include_super = true) %w[public protected private].flat_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 end |
.all_from_obj(obj, include_super = true) ⇒ Array[Pry::Method]
Get all of the methods on an ‘Object`
184 185 186 |
# File 'lib/pry/method.rb', line 184 def all_from_obj(obj, include_super = true) all_from_class(singleton_class_of(obj), include_super) end |
.from_binding(binding) ⇒ 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.
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 |
# File 'lib/pry/method.rb', line 77 def from_binding(binding) meth_name = binding.eval('::Kernel.__method__') if [:__script__, nil].include?(meth_name) nil else method = begin if Object === binding.eval('self') # rubocop:disable Style/CaseEquality new( Kernel.instance_method(:method) .bind(binding.eval("self")) .call(meth_name) ) else str = 'class << self; self; end' \ '.instance_method(::Kernel.__method__).bind(self)' new(binding.eval(str)) end rescue NameError, NoMethodError # rubocop:disable Lint/ShadowedException Disowned.new(binding.eval('self'), meth_name.to_s) end if WeirdMethodLocator.weird_method?(method, binding) WeirdMethodLocator.new(method, binding).find_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.
136 137 138 139 140 |
# File 'lib/pry/method.rb', line 136 def from_class(klass, name, target = TOPLEVEL_BINDING) new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue StandardError 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.
151 152 153 154 155 |
# File 'lib/pry/method.rb', line 151 def from_obj(obj, name, target = TOPLEVEL_BINDING) new(lookup_method_via_binding(obj, name, :method, target)) rescue StandardError 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.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/pry/method.rb', line 43 def from_str(name, target = TOPLEVEL_BINDING, = {}) if name.nil? nil elsif name.to_s =~ /(.+)\#(\S+)\Z/ context = Regexp.last_match(1) meth_name = Regexp.last_match(2) from_module(target.eval(context), meth_name, target) elsif name.to_s =~ /(.+)(\[\])\Z/ context = Regexp.last_match(1) meth_name = Regexp.last_match(2) from_obj(target.eval(context), meth_name, target) elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/ context = Regexp.last_match(1) meth_name = Regexp.last_match(3) from_obj(target.eval(context), meth_name, target) elsif [:instance] from_module(target.eval("self"), name, target) elsif [:methods] from_obj(target.eval("self"), name, target) else from_str(name, target, instance: true) || from_str(name, target, methods: true) end rescue Pry::RescuableException nil end |
.instance_method_definition?(name, definition_line) ⇒ Boolean
227 228 229 230 231 232 |
# File 'lib/pry/method.rb', line 227 def instance_method_definition?(name, definition_line) regexp = /^define_method\(?\s*[:\"\']#{Regexp.escape(name)}| ^def\s*#{Regexp.escape(name)}/x regexp =~ 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.
210 211 212 213 |
# File 'lib/pry/method.rb', line 210 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.
114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/pry/method.rb', line 114 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
215 216 217 218 |
# File 'lib/pry/method.rb', line 215 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.
192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/pry/method.rb', line 192 def resolution_order(obj) if Class === obj # rubocop:disable Style/CaseEquality singleton_class_resolution_order(obj) + instance_resolution_order(Class) else klass = begin singleton_class_of(obj) rescue StandardError obj.class end instance_resolution_order(klass) end end |
.singleton_class_of(obj) ⇒ Object
247 248 249 250 251 |
# File 'lib/pry/method.rb', line 247 def singleton_class_of(obj) class << obj; self; end rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ... obj.class 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.
238 239 240 241 242 243 244 245 |
# File 'lib/pry/method.rb', line 238 def singleton_class_resolution_order(klass) ancestors = Pry::Method.safe_send(klass, :ancestors) resolution_order = ancestors.grep(Class).flat_map do |anc| [singleton_class_of(anc), *singleton_class_of(anc).included_modules] end resolution_order.reverse.uniq.reverse - Class.included_modules end |
.singleton_method_definition?(name, definition_line) ⇒ Boolean
220 221 222 223 224 225 |
# File 'lib/pry/method.rb', line 220 def singleton_method_definition?(name, definition_line) regexp = /^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}| ^def\s*self\.#{Regexp.escape(name)}/x regexp =~ definition_line.strip end |
Instance Method Details
#==(other) ⇒ Boolean
483 484 485 486 487 |
# File 'lib/pry/method.rb', line 483 def ==(other) return other == @method if other.is_a?(Pry::Method) @method == other end |
#alias? ⇒ Boolean
Returns Is the method definitely an alias?.
478 479 480 |
# File 'lib/pry/method.rb', line 478 def alias? name != original_name end |
#aliases ⇒ Array<String>
Returns All known aliases for the method.
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
# File 'lib/pry/method.rb', line 461 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.
446 447 448 |
# File 'lib/pry/method.rb', line 446 def bound_method? is_a?(::Method) end |
#comment ⇒ Object
515 516 517 |
# File 'lib/pry/method.rb', line 515 def comment Pry::Code.from_file(source_file).comment_describing(source_line) end |
#doc ⇒ String?
Returns The documentation for the method, or ‘nil` if it’s unavailable.
329 330 331 332 333 334 335 336 337 338 |
# File 'lib/pry/method.rb', line 329 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?.
436 437 438 |
# File 'lib/pry/method.rb', line 436 def dynamically_defined? !!(source_file && source_file =~ /(\(.*\))|<.*>/) end |
#is_a?(klass) ⇒ Boolean Also known as: kind_of?
491 492 493 |
# File 'lib/pry/method.rb', line 491 def is_a?(klass) (klass == Pry::Method) || @method.is_a?(klass) end |
#name ⇒ String
Get the name of the method as a String, regardless of the underlying Method#name type.
272 273 274 |
# File 'lib/pry/method.rb', line 272 def name @method.name.to_s end |
#name_with_owner ⇒ String
Get the name of the method including the class on which it was defined.
299 300 301 |
# File 'lib/pry/method.rb', line 299 def name_with_owner "#{wrapped_owner.method_prefix}#{name}" end |
#original_name ⇒ String?
Returns The original name the method was defined under, before any aliasing, or ‘nil` if it can’t be determined.
429 430 431 432 433 |
# File 'lib/pry/method.rb', line 429 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?.
456 457 458 |
# File 'lib/pry/method.rb', line 456 def pry_method? source_file == Pry.eval_path end |
#redefine(source) ⇒ Object
Update the live copy of the method’s source.
314 315 316 317 |
# File 'lib/pry/method.rb', line 314 def redefine(source) Patcher.new(self).patch_in_ram source Pry::Method(owner.instance_method(name)) end |
#respond_to?(method_name, include_all = false) ⇒ Boolean
498 499 500 |
# File 'lib/pry/method.rb', line 498 def respond_to?(method_name, include_all = false) super || @method.respond_to?(method_name, include_all) end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
511 512 513 |
# File 'lib/pry/method.rb', line 511 def respond_to_missing?(method_name, include_private = false) @method.respond_to?(method_name) || super end |
#signature ⇒ String
Returns A representation of the method’s signature, including its name and parameters. Optional and “rest” parameters are marked with ‘*` and block parameters with `&`. Keyword arguments are shown with `:` If the parameter names are unavailable, they’re given numbered names instead. Paraphrased from ‘awesome_print` gem.
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/pry/method.rb', line 391 def signature if respond_to?(:parameters) args = parameters.inject([]) do |args_array, (arg_type, name)| name ||= (arg_type == :block ? 'block' : "arg#{args_array.size + 1}") args_array.push( case arg_type when :req then name.to_s when :opt then "#{name}=?" when :rest then "*#{name}" when :block then "&#{name}" when :key then "#{name}:?" when :keyreq 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.
451 452 453 |
# File 'lib/pry/method.rb', line 451 def singleton_method? wrapped_owner.singleton_class? end |
#source ⇒ String?
Returns The source code of the method, or ‘nil` if it’s unavailable.
304 305 306 307 308 309 310 311 |
# File 'lib/pry/method.rb', line 304 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?
321 322 323 324 325 |
# File 'lib/pry/method.rb', line 321 def source? !!source rescue MethodSource::SourceNotFoundError false end |
#source_file ⇒ String?
Returns The name of the file the method is defined in, or ‘nil` if the filename is unavailable.
348 349 350 351 352 353 354 355 356 357 |
# File 'lib/pry/method.rb', line 348 def source_file if source_location.nil? if source_type == :c info = pry_doc_info info.file if info end else source_location.first end end |
#source_line ⇒ Fixnum?
Returns The line of code in ‘source_file` which begins the method’s definition, or ‘nil` if that information is unavailable.
361 362 363 |
# File 'lib/pry/method.rb', line 361 def source_line source_location.nil? ? nil : source_location.last end |
#source_range ⇒ Range?
Returns The range of lines in ‘source_file` which contain the method’s definition, or ‘nil` if that information is unavailable.
367 368 369 |
# File 'lib/pry/method.rb', line 367 def source_range source_location.nil? ? nil : (source_line)..(source_line + source.lines.count - 1) end |
#source_type ⇒ Symbol
Returns The source type of the method. The options are ‘:ruby` for Ruby methods or `:c` for methods written in C.
342 343 344 |
# File 'lib/pry/method.rb', line 342 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.
417 418 419 420 421 422 423 424 425 |
# File 'lib/pry/method.rb', line 417 def super(times = 1) if @method.is_a?(UnboundMethod) 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.
441 442 443 |
# File 'lib/pry/method.rb', line 441 def unbound_method? is_a?(::UnboundMethod) end |
#undefined? ⇒ Boolean
Is the method undefined? (aka ‘Disowned`)
290 291 292 |
# File 'lib/pry/method.rb', line 290 def undefined? false end |
#visibility ⇒ Symbol
Returns The visibility of the method. May be ‘:public`, `:protected`, or `:private`.
373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/pry/method.rb', line 373 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 |
#wrapped ⇒ Method, ...
Get underlying object wrapped by this Pry::Method instance
284 285 286 |
# File 'lib/pry/method.rb', line 284 def wrapped @method end |
#wrapped_owner ⇒ Pry::Module
Get the owner of the method as a Pry::Module
278 279 280 |
# File 'lib/pry/method.rb', line 278 def wrapped_owner @wrapped_owner ||= Pry::WrappedModule.new(owner) end |