class Pry::CodeObject
This class is responsible for taking a string (identifying a command/class/method/etc) and returning the relevant type of object. For example, if the user looks up “show-source” then a `Pry::Command` will be returned. Alternatively, if the user passes in “Pry#repl” then a `Pry::Method` object will be returned.
The `CodeObject.lookup` method is responsible for 1. figuring out what kind of object the user wants (applying precedence rules in doing so – i.e methods get precedence over commands with the same name) and 2. Returning the appropriate object. If the user fails to provide a string identifer for the object (i.e they pass in `nil` or “”) then the object looked up will be the 'current method' or 'current class' associated with the Binding.
TODO: This class is a clusterfuck. We need a much more robust concept of what a “Code Object” really is. Currently commands/classes/candidates/methods and so on just share a very ill-defined interface.
Attributes
Public Class Methods
# File lib/pry/code_object.rb, line 69 def lookup(str, pry_instance, options = {}) co = new(str, pry_instance, options) co.default_lookup || co.method_or_class_lookup || co.command_lookup || co.empty_lookup end
# File lib/pry/code_object.rb, line 82 def initialize(str, pry_instance, options = {}) options = { super: 0 }.merge!(options) @str = str @pry_instance = pry_instance @target = pry_instance.current_context @super_level = options[:super] end
Public Instance Methods
TODO: just make it so find_command_by_match_or_listing doesn't raise?
# File lib/pry/code_object.rb, line 94 def command_lookup pry_instance.commands.find_command_by_match_or_listing(str) rescue StandardError nil end
lookup variables and constants and `self` that are not modules
# File lib/pry/code_object.rb, line 118 def default_lookup # we skip instance methods as we want those to fall through to # method_or_class_lookup() if safe_to_evaluate?(str) && !looks_like_an_instance_method?(str) obj = target.eval(str) # restrict to only objects we KNOW for sure support the full API # Do NOT support just any object that responds to source_location if sourcable_object?(obj) Pry::Method(obj) elsif !obj.is_a?(Module) Pry::WrappedModule(obj.class) end end rescue Pry::RescuableException nil end
when no paramter is given (i.e CodeObject.lookup(nil)
), then we lookup the 'current object' from the binding.
# File lib/pry/code_object.rb, line 102 def empty_lookup return nil if str && !str.empty? obj = if internal_binding?(target) mod = target_self.is_a?(Module) ? target_self : target_self.class Pry::WrappedModule(mod) else Pry::Method.from_binding(target) end # respect the super level (i.e user might have specified a # --super flag to show-source) lookup_super(obj, super_level) end
# File lib/pry/code_object.rb, line 136 def method_or_class_lookup obj = case str when /\S+\(\)\z/ Pry::Method.from_str(str.sub(/\(\)\z/, ''), target) || Pry::WrappedModule.from_str(str, target) else Pry::WrappedModule.from_str(str, target) || Pry::Method.from_str(str, target) end lookup_super(obj, super_level) end
Private Instance Methods
Returns true if `str` looks like a method, i.e Klass#method We need to consider this case because method lookups should fall through to the `method_or_class_lookup()` method but a defined?() on a “Klass#method` string will see the `#` as a comment and only evaluate the `Klass` part. @param [String] str @return [Boolean] Whether the string looks like an instance method.
# File lib/pry/code_object.rb, line 163 def looks_like_an_instance_method?(str) str =~ /\S#\S/ end
grab the nth (`super_level`) super of `obj @param [Object] obj @param [Fixnum] super_level
How far up the super chain to ascend.
# File lib/pry/code_object.rb, line 188 def lookup_super(obj, super_level) return unless obj sup = obj.super(super_level) raise Pry::CommandError, "No superclass found for #{obj.wrapped}" unless sup sup end
We use this method to decide whether code is safe to eval. Method's are generally not, but everything else is. TODO: is just checking != “method” enough?? TODO: see duplication of this method in Pry::WrappedModule
@param [String] str The string to lookup @return [Boolean]
# File lib/pry/code_object.rb, line 173 def safe_to_evaluate?(str) return true if str.strip == "self" return false if str =~ /%/ kind = target.eval("defined?(#{str})") kind =~ /variable|constant/ end
# File lib/pry/code_object.rb, line 152 def sourcable_object?(obj) [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) } end
# File lib/pry/code_object.rb, line 181 def target_self target.eval('self') end