mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
modify edit-method -p to support aliased methods that use super
This commit is contained in:
parent
231732616e
commit
509e908688
3 changed files with 102 additions and 7 deletions
|
@ -225,8 +225,9 @@ class Pry
|
|||
if opts.p? || meth.dynamically_defined?
|
||||
lines = meth.source.lines.to_a
|
||||
|
||||
if lines[0] =~ /^def [^( \n]+/
|
||||
lines[0] = "def #{meth.name}#{$'}"
|
||||
if ((original_name = meth.original_name) &&
|
||||
lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\( ]|$)/)
|
||||
lines[0] = "def #{original_name}#{$'}"
|
||||
else
|
||||
raise CommandError, "Pry can only patch methods created with the `def` keyword."
|
||||
end
|
||||
|
@ -235,7 +236,15 @@ class Pry
|
|||
f.puts lines.join
|
||||
f.flush
|
||||
invoke_editor(f.path, 0)
|
||||
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
|
||||
|
||||
if meth.alias?
|
||||
with_method_transaction(original_name, meth.owner) do
|
||||
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
|
||||
Pry.binding_for(meth.owner).eval("alias #{meth.name} #{original_name}")
|
||||
end
|
||||
else
|
||||
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
|
||||
end
|
||||
end
|
||||
next
|
||||
end
|
||||
|
@ -252,6 +261,17 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
helpers do
|
||||
def with_method_transaction(meth_name, target=TOPLEVEL_BINDING)
|
||||
target = Pry.binding_for(target)
|
||||
temp_name = "__pry_#{meth_name}__"
|
||||
|
||||
target.eval("alias #{temp_name} #{meth_name}")
|
||||
yield
|
||||
target.eval("alias #{meth_name} #{temp_name}")
|
||||
target.eval("undef #{temp_name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -265,7 +265,7 @@ class Pry
|
|||
"#{name}(#{args.join(', ')})"
|
||||
end
|
||||
|
||||
# @return [Pry::Method, nil] The wrapped method that get's called when you
|
||||
# @return [Pry::Method, nil] The wrapped method that is called when you
|
||||
# use "super" in the body of this method.
|
||||
def super(times=1)
|
||||
if respond_to?(:receiver)
|
||||
|
@ -277,6 +277,35 @@ class Pry
|
|||
Pry::Method.new(sup) if sup
|
||||
end
|
||||
|
||||
# @return [Symbol, nil] The original name the method was defined under,
|
||||
# before any aliasing, or `nil` if it can't be determined.
|
||||
def original_name
|
||||
return nil if source_type != :ruby
|
||||
|
||||
first_line = source.lines.first
|
||||
return nil if first_line.strip !~ /^def /
|
||||
|
||||
if RUBY_VERSION =~ /^1\.9/ && RUBY_ENGINE == "ruby"
|
||||
require 'ripper'
|
||||
|
||||
tree = Ripper::SexpBuilder.new(first_line + ";end").parse
|
||||
name = tree.flatten(2).each do |lst|
|
||||
break lst[1] if lst[0] == :@ident
|
||||
end
|
||||
|
||||
name.is_a?(String) ? name : nil
|
||||
else
|
||||
require 'ruby_parser'
|
||||
|
||||
tree = RubyParser.new.parse(first_line + ";end")
|
||||
name = tree.each_cons(2) do |a, b|
|
||||
break a if b.is_a?(Array) && b.first == :args
|
||||
end
|
||||
|
||||
name.is_a?(Symbol) ? name.to_s : nil
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Boolean] Was the method defined outside a source file?
|
||||
def dynamically_defined?
|
||||
!!(source_file and source_file =~ /(\(.*\))|<.*>/)
|
||||
|
@ -287,6 +316,11 @@ class Pry
|
|||
source_file == Pry.eval_path
|
||||
end
|
||||
|
||||
# @return [Boolean] Is the method definitely an alias?
|
||||
def alias?
|
||||
name != original_name
|
||||
end
|
||||
|
||||
# @return [Boolean]
|
||||
def ==(obj)
|
||||
if obj.is_a? Pry::Method
|
||||
|
|
|
@ -370,6 +370,10 @@ describe "Pry::DefaultCommands::Introspection" do
|
|||
def a
|
||||
:yup
|
||||
end
|
||||
|
||||
def b
|
||||
:kinda
|
||||
end
|
||||
end
|
||||
|
||||
class X
|
||||
|
@ -382,6 +386,11 @@ describe "Pry::DefaultCommands::Introspection" do
|
|||
def x
|
||||
:nope
|
||||
end
|
||||
|
||||
def b
|
||||
super
|
||||
end
|
||||
alias c b
|
||||
end
|
||||
EOS
|
||||
@tempfile.flush
|
||||
|
@ -408,19 +417,19 @@ describe "Pry::DefaultCommands::Introspection" do
|
|||
it "should correctly find a class method" do
|
||||
mock_pry("edit-method X.x")
|
||||
@file.should == @tempfile.path
|
||||
@line.should == 10
|
||||
@line.should == 14
|
||||
end
|
||||
|
||||
it "should correctly find an instance method" do
|
||||
mock_pry("edit-method X#x")
|
||||
@file.should == @tempfile.path
|
||||
@line.should == 14
|
||||
@line.should == 18
|
||||
end
|
||||
|
||||
it "should correctly find a method on an instance" do
|
||||
mock_pry("x = X.new", "edit-method x.x")
|
||||
@file.should == @tempfile.path
|
||||
@line.should == 14
|
||||
@line.should == 18
|
||||
end
|
||||
|
||||
it "should correctly find a method from a module" do
|
||||
|
@ -428,6 +437,12 @@ describe "Pry::DefaultCommands::Introspection" do
|
|||
@file.should == @tempfile.path
|
||||
@line.should == 2
|
||||
end
|
||||
|
||||
it "should correctly find an aliased method" do
|
||||
mock_pry("edit-method X#c")
|
||||
@file.should == @tempfile.path
|
||||
@line.should == 22
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with -p' do
|
||||
|
@ -478,6 +493,32 @@ describe "Pry::DefaultCommands::Introspection" do
|
|||
X.new.a.should == :maybe
|
||||
end
|
||||
end
|
||||
|
||||
describe 'on an aliased method' do
|
||||
before do
|
||||
@old_editor = Pry.config.editor
|
||||
Pry.config.editor = lambda do |file, line|
|
||||
lines = File.read(file).lines.to_a
|
||||
lines[1] = '"#{super}aa".to_sym' + "\n"
|
||||
File.open(file, 'w') do |f|
|
||||
f.write(lines.join)
|
||||
end
|
||||
nil
|
||||
end
|
||||
end
|
||||
after do
|
||||
Pry.config.editor = @old_editor
|
||||
end
|
||||
|
||||
it "should change the alias, but not the original, without breaking super" do
|
||||
mock_pry("edit-method -p X#c")
|
||||
|
||||
Pry::Method.from_str("X#c").alias?.should == true
|
||||
|
||||
X.new.b.should == :kinda
|
||||
X.new.c.should == :kindaaa
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue