mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
add Pry::LastException.
pry adds behavior(methods) to the exception it returns at _pry_.last_exception in a repl but when the exception has been passed along as a frozen object ruby will raise an exception and pry fails to function as usual. the commit changes that behavior so that the exception is wrapped in an instance of Pry::LastException who is a subclass of BasicObject. Pry::LastException is a copy&paste of what was defined dynamically in pry_instance.rb but it allows for frozen exceptions to remain frozen and still provides the methods pry dynamically defined on an exception object before. through a wrapper class pry also no longer modifies an exception object that it doesn't own.
This commit is contained in:
parent
90dacb8f25
commit
24bbe12dc2
4 changed files with 67 additions and 19 deletions
|
@ -184,3 +184,4 @@ require 'pry/terminal'
|
|||
require 'pry/editor'
|
||||
require 'pry/rubygem'
|
||||
require "pry/indent"
|
||||
require "pry/last_exception"
|
||||
|
|
35
lib/pry/last_exception.rb
Normal file
35
lib/pry/last_exception.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
class Pry::LastException < BasicObject
|
||||
attr_reader :file, :line
|
||||
attr_accessor :bt_index
|
||||
|
||||
def initialize(e)
|
||||
@e = e
|
||||
@bt_index = 0
|
||||
@file, @line = bt_source_location_for(0)
|
||||
end
|
||||
|
||||
def method_missing(name, *args, &block)
|
||||
if @e.respond_to?(name)
|
||||
@e.public_send(name, *args, &block)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to_missing?(name, boolean=false)
|
||||
@e.respond_to?(name)
|
||||
end
|
||||
|
||||
def pry?
|
||||
true
|
||||
end
|
||||
|
||||
def bt_source_location_for(index)
|
||||
backtrace[index] =~ /(.*):(\d+)/
|
||||
[$1, $2.to_i]
|
||||
end
|
||||
|
||||
def inc_bt_index
|
||||
@bt_index = (@bt_index + 1) % backtrace.size
|
||||
end
|
||||
end
|
|
@ -467,27 +467,17 @@ class Pry
|
|||
self.last_result = result unless code =~ /\A\s*\z/
|
||||
end
|
||||
|
||||
#
|
||||
# Set the last exception for a session.
|
||||
# @param [Exception] ex
|
||||
def last_exception=(ex)
|
||||
class << ex
|
||||
attr_accessor :file, :line, :bt_index
|
||||
def bt_source_location_for(index)
|
||||
backtrace[index] =~ /(.*):(\d+)/
|
||||
[$1, $2.to_i]
|
||||
end
|
||||
|
||||
def inc_bt_index
|
||||
@bt_index = (@bt_index + 1) % backtrace.size
|
||||
end
|
||||
end
|
||||
|
||||
ex.bt_index = 0
|
||||
ex.file, ex.line = ex.bt_source_location_for(0)
|
||||
|
||||
#
|
||||
# @param [Exception] e
|
||||
# the last exception.
|
||||
#
|
||||
def last_exception=(e)
|
||||
last_exception = Pry::LastException.new(e)
|
||||
@last_result_is_exception = true
|
||||
@output_array << ex
|
||||
@last_exception = ex
|
||||
@output_array << last_exception
|
||||
@last_exception = last_exception
|
||||
end
|
||||
|
||||
# Update Pry's internal state after evalling code.
|
||||
|
|
|
@ -67,6 +67,28 @@ describe Pry do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#last_exception=" do
|
||||
before do
|
||||
@pry = Pry.new binding: binding
|
||||
@e = mock_exception "foo.rb:1"
|
||||
end
|
||||
|
||||
it "returns an instance of Pry::LastException" do
|
||||
@pry.last_exception = @e
|
||||
should.satisfy { @pry.last_exception.pry? == true }
|
||||
end
|
||||
|
||||
it "returns a frozen exception" do
|
||||
@pry.last_exception = @e.freeze
|
||||
@pry.last_exception.should.be.frozen?
|
||||
end
|
||||
|
||||
it "returns an object who mirrors itself as the wrapped exception" do
|
||||
@pry.last_exception = @e.freeze
|
||||
@pry.last_exception.should.be.instance_of?(StandardError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "open a Pry session on an object" do
|
||||
describe "rep" do
|
||||
before do
|
||||
|
|
Loading…
Reference in a new issue