Module: PryExceptionExplorer
- Defined in:
- lib/pry-exception_explorer.rb,
lib/pry-exception_explorer/version.rb,
lib/pry-exception_explorer/commands.rb,
lib/pry-exception_explorer/intercept.rb,
lib/pry-exception_explorer/lazy_frame.rb,
lib/pry-exception_explorer/shim_builder.rb
Defined Under Namespace
Modules: ExceptionHelpers, ShimBuilder Classes: Intercept, LazyFrame
Constant Summary collapse
- CONTINUE_INLINE_EXCEPTION =
special constant
Object.new
- VERSION =
"0.1.6"
- Commands =
Pry::CommandSet.new do create_command "enter-exception", "Enter the context of the last exception" do include PryExceptionExplorer::ExceptionHelpers <<-BANNER Usage: enter-exception Enter the context of the last exception BANNER def process if enterable_exception? PryStackExplorer.create_and_push_frame_manager(last_exception.exception_call_stack, _pry_) PryExceptionExplorer.setup_exception_context(last_exception, _pry_) # have to use _pry_.run_command instead of 'run' here as # 'run' works on the current target which hasnt been updated # yet, whereas _pry_.run_command operates on the newly # updated target (the context of the exception) _pry_.run_command "whereami" elsif last_exception raise Pry::CommandError, "Current exception can't be entered! (perhaps a C exception)" else raise Pry::CommandError, "No exception to enter!" end end end create_command "exit-exception", "Leave the context of the current exception." do include ExceptionHelpers <<-BANNER Usage: exit-exception Exit active exception and return to containing context. BANNER def process if !in_exception? raise Pry::CommandError, "You are not in an exception!" elsif !prior_context_exists? run "exit-all" else popped_fm = PryStackExplorer.pop_frame_manager(_pry_) _pry_.last_exception = popped_fm.user[:exception] end end end create_command "continue-exception", "Attempt to continue the current exception." do include ExceptionHelpers <<-BANNER Usage: continue-exception Attempt to continue the current exception. BANNER def process if inline_exception? PryStackExplorer.pop_frame_manager(_pry_) run "exit-all PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION" elsif normal_exception? popped_fm = PryStackExplorer.pop_frame_manager(_pry_) popped_fm.user[:exception].continue else raise Pry::CommandError, "No exception to continue!" end end end end
- CompileError =
Class.new(StandardError)
Class Method Summary collapse
-
.amend_exception_call_stack!(ex) ⇒ Object
Amends (destructively) an exception call stack according to the info in
PryExceptionExplorer.intercept_object
, specificallyPryExceptionExplorer::Intercept#skip_until_block
andPryExceptionExplorer::Intercept#skip_while_block
. -
.enabled ⇒ Boolean
(also: enabled?)
Whether Exception Explorer is enabled.
- .enabled=(v) ⇒ Object
-
.enter_exception(ex, options = {}) ⇒ Object
Enter the exception context.
-
.init ⇒ Object
Set initial state.
-
.intercept(*exceptions) {|lazy_frame, exception| ... } ⇒ Object
This method allows the user to assert the situations where an exception interception occurs.
-
.intercept_object ⇒ PryExceptionExplorer::Intercept
The object defined earlier by a call to
PryExceptionExplorer.intercept
. -
.intercept_object=(b) ⇒ PryExceptionExplorer::Intercept
The object defined earlier by a call to
PryExceptionExplorer.intercept
. -
.local_hash ⇒ Hash
A local hash.
-
.setup_exception_context(ex, _pry_, options = {}) ⇒ Object
Prepare the
Pry
instance and associated call-stack when entering into an exception context. -
.should_intercept_exception?(frame, ex) ⇒ Boolean
This method invokes the
PryExceptionExplorer.intercept_object
, passing in the exception's frame and the exception object itself. -
.wrap { ... } ⇒ Object
Wrap the provided block - intercepting all exceptions that bubble out, provided they satisfy the assertion in
PryExceptionExplorer.intercept
. -
.wrap_active ⇒ Boolean
(also: wrap_active?)
Whether to intercept only those exceptions that bubble out of
EE.wrap
block. - .wrap_active=(v) ⇒ Object
Class Method Details
.amend_exception_call_stack!(ex) ⇒ Object
Amends (destructively) an exception call stack according to the info in
PryExceptionExplorer.intercept_object
, specifically
PryExceptionExplorer::Intercept#skip_until_block
and PryExceptionExplorer::Intercept#skip_while_block
.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/pry-exception_explorer.rb', line 136 def amend_exception_call_stack!(ex) call_stack = ex.exception_call_stack # skip_until if intercept_object.skip_until_block idx = call_stack.each_with_index.find_index do |frame, idx| intercept_object.skip_until_block.call(LazyFrame.new(frame, idx, call_stack)) end call_stack = call_stack.drop(idx) if idx # skip_while elsif intercept_object.skip_while_block idx = call_stack.each_with_index.find_index do |frame, idx| intercept_object.skip_while_block.call(LazyFrame.new(frame, idx, call_stack)) == false end call_stack = call_stack.drop(idx) if idx end ex.exception_call_stack = call_stack end |
.enabled ⇒ Boolean Also known as: enabled?
Returns Whether Exception Explorer is enabled.
36 37 38 |
# File 'lib/pry-exception_explorer.rb', line 36 def enabled !!local_hash[:enabled] end |
.enabled=(v) ⇒ Object
31 32 33 |
# File 'lib/pry-exception_explorer.rb', line 31 def enabled=(v) local_hash[:enabled] = v end |
.enter_exception(ex, options = {}) ⇒ Object
Enter the exception context.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/pry-exception_explorer.rb', line 177 def enter_exception(ex, ={}) hooks = Pry.config.hooks.dup.add_hook(:before_session, :set_exception_flag) do |_, _, _pry_| setup_exception_context(ex, _pry_, ) end.add_hook(:before_session, :manage_intercept_recurse) do PryExceptionExplorer.intercept_object.disable! if !PryExceptionExplorer.intercept_object.intercept_recurse? end.add_hook(:after_session, :manage_intercept_recurse) do PryExceptionExplorer.intercept_object.enable! if !PryExceptionExplorer.intercept_object.active? end # Pry.load_plugins # binding.pry # if we have this here and step through with pry-nav sometimes we get segfaults :/ Pry.start binding, :call_stack => ex.exception_call_stack, :hooks => hooks end |
.init ⇒ Object
Set initial state
193 194 195 196 197 198 199 200 201 202 |
# File 'lib/pry-exception_explorer.rb', line 193 def init # disable by default (intercept exceptions inline) PryExceptionExplorer.wrap_active = false # default is to capture all exceptions PryExceptionExplorer.intercept { true } # disable by default PryExceptionExplorer.enabled = false end |
.intercept(*exceptions) {|lazy_frame, exception| ... } ⇒ Object
This method allows the user to assert the situations where an exception interception occurs. This method can be invoked in two ways. The general form takes a block, the block is passed both the frame where the exception was raised, and the exception itself. The user then creates an assertion (a stack-assertion) based on these attributes. If the assertion is later satisfied by a raised exception, that exception will be intercepted. In the second form, the method simply takes an exception class, or a number of exception classes. If one of these exceptions is raised, it will be intercepted.
99 100 101 102 103 104 105 106 107 |
# File 'lib/pry-exception_explorer.rb', line 99 def intercept(*exceptions, &block) return if exceptions.empty? && block.nil? if !exceptions.empty? block = proc { |_, ex| exceptions.any? { |v| v === ex } } end local_hash[:intercept_object] = Intercept.new(block) end |
.intercept_object ⇒ PryExceptionExplorer::Intercept
Returns The object defined earlier by a call to PryExceptionExplorer.intercept
.
115 116 117 |
# File 'lib/pry-exception_explorer.rb', line 115 def intercept_object local_hash[:intercept_object] end |
.intercept_object=(b) ⇒ PryExceptionExplorer::Intercept
Returns The object defined earlier by a call to PryExceptionExplorer.intercept
.
110 111 112 |
# File 'lib/pry-exception_explorer.rb', line 110 def intercept_object=(b) local_hash[:intercept_object] = b end |
.local_hash ⇒ Hash
Returns A local hash.
26 27 28 |
# File 'lib/pry-exception_explorer.rb', line 26 def local_hash @hash ||= {} end |
.setup_exception_context(ex, _pry_, options = {}) ⇒ Object
Prepare the Pry
instance and associated call-stack when entering
into an exception context.
164 165 166 167 168 169 170 |
# File 'lib/pry-exception_explorer.rb', line 164 def setup_exception_context(ex, _pry_, ={}) _pry_.last_exception = ex _pry_.backtrace = ex.backtrace PryStackExplorer.frame_manager(_pry_).user[:exception] = ex PryStackExplorer.frame_manager(_pry_).user[:inline_exception] = !![:inline] end |
.should_intercept_exception?(frame, ex) ⇒ Boolean
This method invokes the PryExceptionExplorer.intercept_object
,
passing in the exception's frame and the exception object itself.
124 125 126 127 128 129 130 |
# File 'lib/pry-exception_explorer.rb', line 124 def should_intercept_exception?(frame, ex) if intercept_object intercept_object.call(LazyFrame.new(frame), ex) else false end end |
.wrap { ... } ⇒ Object
Wrap the provided block - intercepting all exceptions
that bubble out, provided they satisfy the
assertion in PryExceptionExplorer.intercept
.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/pry-exception_explorer.rb', line 60 def wrap old_enabled, old_wrap_active = enabled, wrap_active self.enabled = true self.wrap_active = true yield rescue Exception => ex if ex.should_intercept? enter_exception(ex) else raise ex end ensure self.enabled = old_enabled self.wrap_active = old_wrap_active end |
.wrap_active ⇒ Boolean Also known as: wrap_active?
Returns Whether to intercept only those exceptions that bubble out of
EE.wrap
block.
48 49 50 |
# File 'lib/pry-exception_explorer.rb', line 48 def wrap_active !!local_hash[:wrap_active] end |
.wrap_active=(v) ⇒ Object
42 43 44 |
# File 'lib/pry-exception_explorer.rb', line 42 def wrap_active=(v) local_hash[:wrap_active] = v end |