class Pry::Method::Patcher

def self.code_for(filename)

def self.code_for(filename)
  @@source_cache[filename]
end

def cache_key

def cache_key
  "pry-redefined(0x#{method.owner.object_id.to_s(16)}##{method.name})"
end

def definition_for_owner(line)

Returns:
  • (String) - The new definition line. e.g. def foo(bar, baz=1)

Parameters:
  • line (String) -- The original definition line. e.g. def self.foo(bar, baz=1)
def definition_for_owner(line)
  if line =~ /\Adef (?:.*?\.)?#{Regexp.escape(method.original_name)}(?=[\(\s;]|$)/
    "def #{method.original_name}#{$'}"
  else
    raise CommandError,
          "Could not find original `def #{method.original_name}` line " \
          "to patch."
  end
end

def initialize(method)

def initialize(method)
  @method = method
end

def patch_in_ram(source)

perform the patch
def patch_in_ram(source)
  if method.alias?
    with_method_transaction do
      redefine source
    end
  else
    redefine source
  end
end

def redefine(source)

def redefine(source)
  @@source_cache[cache_key] = source
  TOPLEVEL_BINDING.eval wrap(source), cache_key
end

def with_method_transaction


continue to work.
translation we make that not happen, which means that alias_method_chains, etc.
unaliased name (so that super continues to work). By wrapping that code in a
When we're redefining aliased methods we will overwrite the method at the

Run some code ensuring that at the end target#meth_name will not have changed.
def with_method_transaction
  temp_name = "__pry_#{method.original_name}__"
  method = self.method
  method.owner.class_eval do
    alias_method temp_name, method.original_name
    yield
    alias_method method.name, method.original_name
    alias_method method.original_name, temp_name
  end
ensure
  begin
    method.send(:remove_method, temp_name)
  rescue StandardError
    nil
  end
end

def wrap(source)

Returns:
  • (String) - The wrapped source.

Parameters:
  • source (String) --
def wrap(source)
  wrap_for_nesting(wrap_for_owner(source))
end

def wrap_for_nesting(source)

Returns:
  • (String) -

Parameters:
  • source (String) -- The source to wrap.
def wrap_for_nesting(source)
  nesting = Pry::Code.from_file(method.source_file).nesting_at(method.source_line)
  (nesting + [source] + nesting.map { "end" } + [""]).join(";")
rescue Pry::Indent::UnparseableNestingError
  source
end

def wrap_for_owner(source)

Returns:
  • (String) -

Parameters:
  • source (String) -- The source to wrap
def wrap_for_owner(source)
  Pry.current[:pry_owner] = method.owner
  owner_source = definition_for_owner(source)
  visibility_fix = "#{method.visibility} #{method.name.to_sym.inspect}"
  "Pry.current[:pry_owner].class_eval do; #{owner_source}\n#{visibility_fix}\nend"
end