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

pry_instance[RW]
str[RW]
super_level[RW]
target[RW]

Public Class Methods

lookup(str, pry_instance, options = {}) click to toggle source
# 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
new(str, pry_instance, options = {}) click to toggle source
# 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

command_lookup() click to toggle source

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
default_lookup() click to toggle source

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
empty_lookup() click to toggle source

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
method_or_class_lookup() click to toggle source
# 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

looks_like_an_instance_method?(str) click to toggle source

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
lookup_super(obj, super_level) click to toggle source

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
safe_to_evaluate?(str) click to toggle source

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
sourcable_object?(obj) click to toggle source
# File lib/pry/code_object.rb, line 152
def sourcable_object?(obj)
  [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) }
end
target_self() click to toggle source
# File lib/pry/code_object.rb, line 181
def target_self
  target.eval('self')
end