pry-moves 0.1.13 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +6 -4
- data/README.md +15 -7
- data/lib/commands/debug.rb +17 -0
- data/lib/commands/finish.rb +26 -0
- data/lib/commands/goto.rb +19 -0
- data/lib/commands/iterate.rb +22 -0
- data/lib/commands/next.rb +37 -0
- data/lib/commands/next_breakpoint.rb +22 -0
- data/lib/commands/step.rb +83 -0
- data/lib/commands/trace_command.rb +87 -0
- data/lib/commands/trace_helpers.rb +49 -0
- data/lib/commands/traced_method.rb +71 -0
- data/lib/debug_sugar.rb +72 -0
- data/lib/pry-moves/add_suffix.rb +88 -0
- data/lib/pry-moves/backtrace.rb +67 -43
- data/lib/pry-moves/bindings_stack.rb +97 -0
- data/lib/pry-moves/commands.rb +42 -3
- data/lib/pry-moves/formatter.rb +74 -0
- data/lib/pry-moves/painter.rb +3 -2
- data/lib/pry-moves/pry_ext.rb +64 -16
- data/lib/pry-moves/pry_wrapper.rb +30 -17
- data/lib/pry-moves/restartable.rb +38 -0
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-moves/watch.rb +3 -0
- data/lib/pry-moves.rb +65 -6
- data/lib/pry-stack_explorer/frame_manager.rb +6 -9
- data/lib/pry-stack_explorer/pry-stack_explorer.rb +1 -16
- data/lib/pry-stack_explorer/{commands.rb → stack_commands.rb} +10 -6
- data/lib/pry-stack_explorer/when_started_hook.rb +10 -65
- data/playground/Gemfile.lock +6 -4
- data/playground/README.md +1 -0
- data/playground/playground.rb +94 -9
- data/playground/test.rb +5 -1
- data/playground/test.sh +1 -0
- data/pry-moves.gemspec +3 -2
- data/publish.sh +2 -1
- data/spec/backtrace_spec.rb +11 -13
- data/spec/blocks_spec.rb +41 -8
- data/spec/commands_spec.rb +26 -25
- data/spec/pry_debugger.rb +5 -1
- data/spec/redirection_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -4
- data/spec/step_spec.rb +51 -0
- metadata +43 -13
- data/lib/pry-moves/helpers.rb +0 -56
- data/lib/pry-moves/trace_commands.rb +0 -109
- data/lib/pry-moves/traced_method.rb +0 -61
- data/lib/pry-moves/tracer.rb +0 -140
- data/lib/pry-moves/traversing.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c08b34502f7649fecea8dbf09d8bbc04e917341a260c92bc1e1b50e70ad7fe3
|
4
|
+
data.tar.gz: 27be890e5b41dafdbdf58279c85618682ef8a3f24fa2a89094053ec8d5af9455
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3d5d0a64ab6d910529b3e228154d609b638892913e66ea66c0403e152aea5aa9dceb8e66a46e8515978142af942bb7f59801ec233e1abcb2be44c2338279bc2
|
7
|
+
data.tar.gz: f288273d0b30e3bde39ec975e3bd5cb360a7d1a2f747cf8ab95d17e9190ac4f38797c9b21a90a3398383fd5b384dbd4df675a250ad23723360e60ccaed8ebf75
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pry-moves (0.
|
4
|
+
pry-moves (1.0.0)
|
5
5
|
binding_of_caller (~> 0.7)
|
6
|
-
|
6
|
+
colorize (~> 0.8)
|
7
|
+
pry (>= 0.10.4, < 0.13)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
@@ -11,6 +12,7 @@ GEM
|
|
11
12
|
binding_of_caller (0.8.0)
|
12
13
|
debug_inspector (>= 0.0.1)
|
13
14
|
coderay (1.1.2)
|
15
|
+
colorize (0.8.1)
|
14
16
|
debug_inspector (0.0.3)
|
15
17
|
diff-lcs (1.3)
|
16
18
|
method_source (0.9.0)
|
@@ -39,10 +41,10 @@ PLATFORMS
|
|
39
41
|
ruby
|
40
42
|
|
41
43
|
DEPENDENCIES
|
42
|
-
pry
|
44
|
+
pry (= 0.11.3)
|
43
45
|
pry-moves!
|
44
46
|
pry-remote (~> 0.1.6)
|
45
47
|
rspec
|
46
48
|
|
47
49
|
BUNDLED WITH
|
48
|
-
|
50
|
+
1.17.3
|
data/README.md
CHANGED
@@ -9,19 +9,22 @@ _An execution control add-on for [Pry][pry]._
|
|
9
9
|
|
10
10
|
## Commands:
|
11
11
|
|
12
|
+
Documentation for latest version. For [v0.1.12 see documentation here](https://github.com/garmoshka-mo/pry-moves/tree/v0.1.12#commands)
|
13
|
+
|
12
14
|
* `n` - **next** line in current frame, including block lines (moving to next line goes as naturally expected)
|
13
15
|
* `nn` - **next** line in current frame, skipping block lines
|
14
16
|
* `s` - **step** into function execution
|
15
17
|
* `s method_name` - step into method `method_name` (For example from `User.new.method_name`). Partial name match supported.
|
16
18
|
* `s +` - step into function, including hidden frames
|
17
19
|
* `f` - **finish** execution of current frame (block or method) and stop at next line on higher level
|
18
|
-
* `iterate` - go to next iteration of current block
|
19
20
|
* `c` - **continue**
|
21
|
+
* `b` - go to next breakpoint (breakpoints currently are methods which contain "debug" in their name)
|
22
|
+
* `iterate` - go to next iteration of current block
|
20
23
|
* `g 10` - **goto** line 10
|
21
|
-
* `bt` - show
|
22
|
-
* `bt
|
23
|
-
* `bt
|
24
|
-
* `bt
|
24
|
+
* `bt` - show backtrace, excluding hidden frames
|
25
|
+
* `bt +` `bt hidden` - show backtrace including hidden frames
|
26
|
+
* `bt a` `bt all` - full backtrace with system and hidden frames
|
27
|
+
* `bt 10` - go to backtrace line 10
|
25
28
|
* `bt > foo` - write backtrace to file `log/backtrace_foo.log`
|
26
29
|
* `up`/`down`/`top`/`bottom` - move over call stack
|
27
30
|
* `up +` - move up, including vapid frames (block callers, hidden frames)
|
@@ -29,8 +32,12 @@ _An execution control add-on for [Pry][pry]._
|
|
29
32
|
* `debug some_method(some_param)` - call `some_method(some_param)` and interactively step into it. This way you can virtually "step back" by executing previous pieces of code from current method
|
30
33
|
* `.method` or `123` or `:hash_key` - Continue traversing of last object in history. E.g. `orders` will list array, then `3` will enter `orders[3]`, then `.price` will enter `orders[3].price`
|
31
34
|
* `watch variable` - display variable's value on each step
|
35
|
+
* `@` - restart. Set config `PryMoves.reload_rake_tasks = true` to automatically reload rake tasks
|
36
|
+
* `#` - exit with code 3, can be wrapped in bash script to fully reload ruby scripts
|
32
37
|
* `!` - exit
|
33
38
|
|
39
|
+
Variable & methods names takes precedence over commands.
|
40
|
+
So if you have variable named `step`, to execute command `step` type `cmd step` or command's alias, e.g. `s`
|
34
41
|
|
35
42
|
## Examples
|
36
43
|
|
@@ -63,10 +70,9 @@ end
|
|
63
70
|
|
64
71
|
## Configuration
|
65
72
|
|
66
|
-
Here is default configuration, you can
|
73
|
+
Here is default configuration, you can reassign it:
|
67
74
|
|
68
75
|
```ruby
|
69
|
-
PryMoves::Backtrace::lines_count = 5
|
70
76
|
PryMoves::Backtrace::filter =
|
71
77
|
/(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/|\/pry-moves\/)/
|
72
78
|
```
|
@@ -122,6 +128,8 @@ Please note that debugging functionality is implemented through
|
|
122
128
|
|
123
129
|
```
|
124
130
|
bundle exec rspec
|
131
|
+
|
132
|
+
DEBUG=true bundle exec rspec -e 'backtrace should backtrace'
|
125
133
|
```
|
126
134
|
|
127
135
|
## ToDo
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class PryMoves::Debug < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
#
|
5
|
+
end
|
6
|
+
|
7
|
+
def trace(event, file, line, method, binding_)
|
8
|
+
return unless event == 'line'
|
9
|
+
if @first_line_skipped
|
10
|
+
true
|
11
|
+
else
|
12
|
+
@first_line_skipped = true
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class PryMoves::Finish < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@block_to_finish = frame_digest(binding_) if binding_.frame_type == :block
|
5
|
+
end
|
6
|
+
|
7
|
+
def trace(event, file, line, method, binding_)
|
8
|
+
return true if @on_exit_from_method
|
9
|
+
return if @call_depth > 0 or event == 'c-return'
|
10
|
+
|
11
|
+
return true if @call_depth < 0
|
12
|
+
|
13
|
+
# early return:
|
14
|
+
return true if event == 'return' and
|
15
|
+
@call_depth == 0 and @method.within?(file, line) and
|
16
|
+
method == @method[:name] and @method.before_end?(line)
|
17
|
+
|
18
|
+
# for finishing blocks inside current method
|
19
|
+
if @block_to_finish
|
20
|
+
((@call_depth == 0) ^ (event == 'return')) and
|
21
|
+
@method.within?(file, line) and
|
22
|
+
@block_to_finish != current_frame_digest
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class PryMoves::Goto < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@goto_line = @command[:param].to_i
|
5
|
+
end
|
6
|
+
|
7
|
+
def trace(event, file, line, method, binding_)
|
8
|
+
if @call_depth < 0 or
|
9
|
+
@call_depth == 0 and event == 'return' and @method.within?(file, line)
|
10
|
+
PryMoves.messages << "⚠️ Unable to reach line #{@goto_line} in current frame"
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
event == 'line' && @goto_line == line and
|
15
|
+
@method[:file] == file and
|
16
|
+
@call_depth == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class PryMoves::Iterate < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@iteration_start_line = binding_.eval('__LINE__')
|
5
|
+
@caller_digest = frame_digest(binding_)
|
6
|
+
end
|
7
|
+
|
8
|
+
def trace(event, file, line, method, binding_)
|
9
|
+
return true if event == 'return' and
|
10
|
+
@method.within?(file, line)
|
11
|
+
|
12
|
+
# промотка итерации -
|
13
|
+
# попасть на ту же или предыдущую строку или выйти из дайджеста
|
14
|
+
# будучи в том же методе
|
15
|
+
event == 'line' and @call_depth == 0 and
|
16
|
+
@method.within?(file, line) and
|
17
|
+
(line <= @iteration_start_line or
|
18
|
+
@caller_digest != current_frame_digest
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class PryMoves::Next < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@start_line = binding_.eval('__LINE__')
|
5
|
+
@start_digest = frame_digest(binding_)
|
6
|
+
if @command[:param] == 'blockless'
|
7
|
+
@stay_at_frame = @start_digest
|
8
|
+
end
|
9
|
+
@events_traced = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def trace(event, file, line, method, binding_)
|
13
|
+
@events_traced += 1
|
14
|
+
|
15
|
+
return true if @call_depth < 0
|
16
|
+
|
17
|
+
return unless @call_depth == 0 and @method.within?(file, line)
|
18
|
+
|
19
|
+
if event == 'line'
|
20
|
+
if @stay_at_frame
|
21
|
+
return (
|
22
|
+
@stay_at_frame == current_frame_digest or
|
23
|
+
@c_stack_level < 0
|
24
|
+
)
|
25
|
+
elsif @start_line != line or (
|
26
|
+
@events_traced > 1 and # чтобы не застревало на while (vx = shift)
|
27
|
+
@start_digest == current_frame_digest # for correct iterating over one_line_in_block
|
28
|
+
)
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
true if event == 'return' and
|
34
|
+
method == @method[:name] and @method.before_end?(line)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class PryMoves::NextBreakpoint < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@reach_digest = frame_digest(binding_)
|
5
|
+
end
|
6
|
+
|
7
|
+
def trace(event, file, line, method, binding_)
|
8
|
+
if @reach_digest
|
9
|
+
if @reach_digest == current_frame_digest
|
10
|
+
@reach_digest = nil
|
11
|
+
else
|
12
|
+
return
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if method.to_s.include? "debug"
|
17
|
+
@pry_start_options[:initial_frame] = 1
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class PryMoves::Step < PryMoves::TraceCommand
|
2
|
+
|
3
|
+
def init(binding_)
|
4
|
+
@step_into_funcs = nil
|
5
|
+
@start_line = binding_.eval('__LINE__')
|
6
|
+
@caller_digest = frame_digest(binding_)
|
7
|
+
func = @command[:param]
|
8
|
+
redirect_step? binding_ # set @step_into_funcs from initial binding
|
9
|
+
if func == '+'
|
10
|
+
@step_in_everywhere = true
|
11
|
+
elsif func
|
12
|
+
@find_straight_descendant = true
|
13
|
+
@step_into_funcs = [func]
|
14
|
+
@step_into_funcs << '=initialize' if ['new', '=new'].include? func
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def trace(event, file, line, method, binding_)
|
19
|
+
if binding_.local_variable_defined? :pry_moves_skip
|
20
|
+
finish_cmd = {binding: binding_}
|
21
|
+
PryMoves::Finish.new finish_cmd, @pry_start_options do |binding|
|
22
|
+
start_tracing
|
23
|
+
end
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
@const_missing_level ||= 0
|
28
|
+
if method == :const_missing
|
29
|
+
if event == 'call'
|
30
|
+
@const_missing_level += 1
|
31
|
+
elsif event == 'return'
|
32
|
+
@const_missing_level -= 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
return if @const_missing_level > 0
|
36
|
+
|
37
|
+
return unless event == 'line'
|
38
|
+
|
39
|
+
if @step_in_everywhere
|
40
|
+
return true
|
41
|
+
elsif @step_into_funcs
|
42
|
+
if @call_depth < 0
|
43
|
+
PryMoves.messages << "⚠️ Unable to find function with name #{@step_into_funcs.join(',')}"
|
44
|
+
return true
|
45
|
+
end
|
46
|
+
|
47
|
+
return false if keep_search_method? binding_
|
48
|
+
elsif redirect_step? binding_
|
49
|
+
return false
|
50
|
+
elsif binding_.local_variable_defined? :hide_from_stack and
|
51
|
+
not @method.within?(file, line, method)
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def keep_search_method? binding_
|
59
|
+
return true unless method_matches? binding_.eval('__callee__')
|
60
|
+
|
61
|
+
return true if @find_straight_descendant &&
|
62
|
+
# if we want to step-in only into straight descendant
|
63
|
+
@caller_digest != current_frame_digest(upward: 1 + 1) # 1 for getting parent and 1 for 'def keep_search_method?'
|
64
|
+
@find_straight_descendant = false
|
65
|
+
|
66
|
+
return true if redirect_step? binding_
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_matches?(method)
|
70
|
+
@step_into_funcs.any? do |pattern|
|
71
|
+
if pattern.is_a? Symbol
|
72
|
+
method == pattern
|
73
|
+
elsif pattern.is_a? Regexp
|
74
|
+
method.to_s.match pattern
|
75
|
+
elsif pattern.start_with? '='
|
76
|
+
"=#{method}" == pattern
|
77
|
+
else
|
78
|
+
method.to_s.include? pattern
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'pry' unless defined? Pry
|
3
|
+
|
4
|
+
module PryMoves
|
5
|
+
class TraceCommand
|
6
|
+
|
7
|
+
include PryMoves::TraceHelpers
|
8
|
+
|
9
|
+
def self.trace(command, pry_start_options, &callback)
|
10
|
+
cls = command[:action].to_s.split('_').collect(&:capitalize).join
|
11
|
+
cls = Object.const_get "PryMoves::#{cls}"
|
12
|
+
cls.new command, pry_start_options, &callback
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(command, pry_start_options, &callback)
|
16
|
+
@command = command
|
17
|
+
@pry_start_options = pry_start_options
|
18
|
+
@pry_start_options[:pry_moves_loop] = true
|
19
|
+
@callback = callback
|
20
|
+
@call_depth = 0
|
21
|
+
@c_stack_level = 0
|
22
|
+
|
23
|
+
binding_ = @command[:binding] # =Command.target - more rich, contains required @iseq
|
24
|
+
unless binding_.instance_variable_get('@iseq')
|
25
|
+
binding_ = PryMoves::BindingsStack.new.initial_frame
|
26
|
+
end
|
27
|
+
@method = PryMoves::TracedMethod.new binding_
|
28
|
+
|
29
|
+
if @pry_start_options.delete :exit_from_method
|
30
|
+
@on_exit_from_method = true
|
31
|
+
@call_depth -= 1
|
32
|
+
end
|
33
|
+
@pry_start_options.delete :initial_frame
|
34
|
+
|
35
|
+
init binding_
|
36
|
+
start_tracing
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_tracing
|
40
|
+
#puts "##trace_obj #{trace_obj}"
|
41
|
+
Pry.config.disable_breakpoints = true
|
42
|
+
trace_obj.set_trace_func method(:tracing_func).to_proc
|
43
|
+
end
|
44
|
+
|
45
|
+
def stop_tracing
|
46
|
+
trace_obj.set_trace_func nil
|
47
|
+
Pry.config.disable_breakpoints = false
|
48
|
+
end
|
49
|
+
|
50
|
+
# You can't call set_trace_func or Thread.current.set_trace_func recursively
|
51
|
+
# even in different threads 😪
|
52
|
+
# But! 💡
|
53
|
+
# The hack is - you can call Thread.current.set_trace_func
|
54
|
+
# from inside of set_trace_func! 🤗
|
55
|
+
def trace_obj
|
56
|
+
Thread.current[:pry_moves_debug] ?
|
57
|
+
Thread.current : Kernel
|
58
|
+
end
|
59
|
+
|
60
|
+
def tracing_func(event, file, line, id, binding_, klass)
|
61
|
+
|
62
|
+
# Ignore traces inside pry-moves code
|
63
|
+
return if file && TRACE_IGNORE_FILES.include?(File.expand_path(file))
|
64
|
+
return unless binding_ # ignore strange cases
|
65
|
+
|
66
|
+
# for cases when currently traced method called more times recursively
|
67
|
+
if event == "call" and @method.within?(file, line, id)
|
68
|
+
@call_depth += 1
|
69
|
+
elsif %w(c-call c-return).include?(event)
|
70
|
+
# todo: может быть, c-return тоже правильнее делать после trace
|
71
|
+
delta = event == 'c-call' ? 1 : -1
|
72
|
+
@c_stack_level += delta
|
73
|
+
end
|
74
|
+
|
75
|
+
printf "👟 %8s %s:%-2d %10s %8s dep:#{@call_depth} c_st:#{@c_stack_level}\n", event, file, line, id, klass if PryMoves.trace # TRACE_MOVES=1
|
76
|
+
|
77
|
+
if trace event, file, line, id, binding_
|
78
|
+
@pry_start_options[:exit_from_method] = true if event == 'return'
|
79
|
+
stop_tracing
|
80
|
+
@callback.call binding_
|
81
|
+
elsif event == "return" and @method.within?(file, line, id)
|
82
|
+
@call_depth -= 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module PryMoves::TraceHelpers
|
2
|
+
|
3
|
+
def redirect_step?(binding_)
|
4
|
+
return false unless binding_.local_variable_defined? :debug_redirect
|
5
|
+
|
6
|
+
debug_redirect = binding_.local_variable_get(:debug_redirect)
|
7
|
+
@step_into_funcs = [debug_redirect] if debug_redirect
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug_info(file, line, id)
|
12
|
+
puts "📽 call_depth:#{@call_depth} #{@method[:file]}:#{file}"
|
13
|
+
puts "#{id} #{@method[:start]} > #{line} > #{@method[:end]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_frame_digest(upward: 0)
|
17
|
+
# binding_ from tracing_func doesn't have @iseq,
|
18
|
+
# therefore binding should be re-retrieved using 'binding_of_caller' lib
|
19
|
+
frame_digest(binding.of_caller(3 + upward))
|
20
|
+
end
|
21
|
+
|
22
|
+
def frame_digest(binding_)
|
23
|
+
#puts "frame_digest for: #{binding_.eval '__callee__'}"
|
24
|
+
iseq = binding_.instance_variable_get('@iseq')
|
25
|
+
Digest::MD5.hexdigest iseq.disasm
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_frame_type(upward: 0)
|
29
|
+
# binding_ from tracing_func doesn't have @iseq,
|
30
|
+
# therefore binding should be re-retrieved using 'binding_of_caller' lib
|
31
|
+
frame_type(binding.of_caller(3 + upward))
|
32
|
+
end
|
33
|
+
|
34
|
+
def frame_type(binding_)
|
35
|
+
line = binding_.instance_variable_get('@iseq').disasm.split("\n").first
|
36
|
+
m = line.match /\== disasm: #<ISeq:([\w ]+)@/
|
37
|
+
if m
|
38
|
+
str = m[1]
|
39
|
+
if str.start_with? 'block in '
|
40
|
+
:block
|
41
|
+
else
|
42
|
+
:method
|
43
|
+
end
|
44
|
+
else
|
45
|
+
:unknown
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|