Skip to content

Commit

Permalink
Make Binding#source_location polyfill
Browse files Browse the repository at this point in the history
  • Loading branch information
joallard committed May 22, 2020
1 parent 1811f29 commit bb8afde
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 15 deletions.
7 changes: 4 additions & 3 deletions lib/pry-rescue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require File.expand_path('../pry-rescue/commands', __FILE__)
require File.expand_path('../pry-rescue/rack', __FILE__)
require File.expand_path('../pry-rescue/peek.rb', __FILE__)
require File.expand_path('../pry-rescue/source_location.rb', __FILE__)

if ENV['PRY_RESCUE_RAILS']
require File.expand_path('../pry-rescue/rails', __FILE__)
Expand Down Expand Up @@ -103,7 +104,7 @@ def in_exception_context?
# @param [Exception] e The raised exception
def phantom_load_raise?(e)
bindings = e.instance_variable_get(:@rescue_bindings)
bindings.any? && bindings.first.eval("__FILE__") == __FILE__
bindings.any? && SourceLocation.call(bindings.first)[0] == __FILE__
end

# When using pry-stack-explorer we want to start the rescue session outside of gems
Expand All @@ -113,7 +114,7 @@ def phantom_load_raise?(e)
# @return [Fixnum] The offset of the first binding of user code
def initial_frame(bindings)
bindings.each_with_index do |binding, i|
return i if user_path?(binding.eval("__FILE__"))
return i if user_path?(SourceLocation.call(binding)[0])
end

0
Expand Down Expand Up @@ -170,7 +171,7 @@ def stdlib_path?(file)
def without_bindings_below_raise(bindings)
return bindings if bindings.size <= 1
bindings.drop_while do |b|
b.eval("__FILE__") == File.expand_path("../pry-rescue/core_ext.rb", __FILE__)
SourceLocation.call(b)[0] == File.expand_path("../pry-rescue/core_ext.rb", __FILE__)
end.drop_while do |b|
Interception == b.eval("self")
end
Expand Down
13 changes: 13 additions & 0 deletions lib/pry-rescue/source_location.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class PryRescue
module SourceLocation
DEPRECATION_TIME = Time.new(2021,4,1)

WithRuby2_5 = ->(b){ [b.eval("__FILE__"), b.eval("__LINE__")] }
WithRuby2_6 = ->(b){ b.source_location }

define_singleton_method(
:call,
(RUBY_VERSION < "2.6.0") ? WithRuby2_5 : WithRuby2_6
)
end
end
32 changes: 20 additions & 12 deletions spec/pry_rescue_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
require 'uri'

describe "PryRescue.load" do
before :all do
if !binding.respond_to?(:source_location)
Binding.define_method :source_location do
PryRescue::SourceLocation.call(self)
end
end
end

if defined?(PryStackExplorer)
it "should open at the correct point" do
expect(PryRescue).to receive(:pry).once { |opts|
expect(opts[:call_stack].first.eval("__FILE__")).to end_with('spec/fixtures/simple.rb')
expect(opts[:call_stack].first.source_location[0]).to end_with('spec/fixtures/simple.rb')
}
expect(lambda {
PryRescue.load("spec/fixtures/simple.rb")
Expand All @@ -14,7 +22,7 @@

it "should open above the standard library" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][opts[:initial_frame]].eval("__FILE__")).to end_with('spec/fixtures/uri.rb')
expect(opts[:call_stack][opts[:initial_frame]].source_location[0]).to end_with('spec/fixtures/uri.rb')
end
expect(lambda{
PryRescue.load("spec/fixtures/uri.rb")
Expand All @@ -23,7 +31,7 @@

it "should keep the standard library on the binding stack" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack].first.eval("__FILE__")).to start_with(RbConfig::CONFIG['libdir'])
expect(opts[:call_stack].first.source_location[0]).to start_with(RbConfig::CONFIG['libdir'])
end
expect(lambda{
PryRescue.load("spec/fixtures/uri.rb")
Expand All @@ -32,7 +40,7 @@

it "should open above gems" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][opts[:initial_frame]].eval("__FILE__")).to end_with('spec/fixtures/coderay.rb')
expect(opts[:call_stack][opts[:initial_frame]].source_location[0]).to end_with('spec/fixtures/coderay.rb')
end
expect(lambda{
PryRescue.load("spec/fixtures/coderay.rb")
Expand All @@ -45,7 +53,7 @@
Gem::Specification.detect{|x| x.name == 'coderay' }.full_gem_path :
Gem.all_load_paths.grep(/coderay/).last

expect(opts[:call_stack].first.eval("__FILE__")).to start_with(coderay_path)
expect(opts[:call_stack].first.source_location[0]).to start_with(coderay_path)
end
expect(lambda{
PryRescue.load("spec/fixtures/coderay.rb")
Expand All @@ -67,8 +75,8 @@

it "should filter out duplicate stack frames" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][0].eval("__LINE__")).to be(4)
expect(opts[:call_stack][1].eval("__LINE__")).to be(12)
expect(opts[:call_stack][0].source_location[1]).to be(4)
expect(opts[:call_stack][1].source_location[1]).to be(12)
end
expect(lambda{
PryRescue.load("spec/fixtures/super.rb")
Expand All @@ -77,8 +85,8 @@

it "should calculate correct initial frame even when duplicates are present" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][0].eval("__FILE__")).to end_with('fake.rb')
expect(opts[:call_stack][opts[:initial_frame]].eval("__FILE__")).to end_with('spec/fixtures/initial.rb')
expect(opts[:call_stack][0].source_location[0]).to end_with('fake.rb')
expect(opts[:call_stack][opts[:initial_frame]].source_location[0]).to end_with('spec/fixtures/initial.rb')
end
expect(lambda{
PryRescue.load("spec/fixtures/initial.rb")
Expand All @@ -87,7 +95,7 @@

it "should skip over reraises from within gems" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][0].eval("__FILE__")).to end_with('spec/fixtures/reraise.rb')
expect(opts[:call_stack][0].source_location[0]).to end_with('spec/fixtures/reraise.rb')
end
expect(lambda{
PryRescue.load("spec/fixtures/reraise.rb")
Expand All @@ -96,7 +104,7 @@

it "should not skip over independent raises within gems" do
expect(PryRescue).to receive(:pry).once do |opts|
expect(opts[:call_stack][0].eval("__FILE__")).to end_with('fake.rb')
expect(opts[:call_stack][0].source_location[0]).to end_with('fake.rb')
end
expect(lambda{
PryRescue.load("spec/fixtures/raiseother.rb")
Expand All @@ -111,7 +119,7 @@
else
it "should open at the correct point" do
expect(Pry).to receive(:start).once { |binding, h|
expect(binding.eval("__FILE__")).to end_with('spec/fixtures/simple.rb')
expect(binding.source_location[0]).to end_with('spec/fixtures/simple.rb')
}
expect(lambda{
PryRescue.load("spec/fixtures/simple.rb")
Expand Down
19 changes: 19 additions & 0 deletions spec/source_location_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
describe PryRescue::SourceLocation do
describe ".call" do
subject{ described_class.call(binding) }

it "matches [file, line]" do
is_expected.to match([__FILE__, be_between(2,30)])
end
end

it "will be removed when Ruby 2.5 is EOL" do
time = Time.now

if time >= described_class::DEPRECATION_TIME
expect(
defined?(PryRescue::SourceLocation)
).to be false
end
end
end

0 comments on commit bb8afde

Please sign in to comment.