pry-moves 0.1.13 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +9 -5
  4. data/README.md +25 -9
  5. data/lib/commands/debug.rb +21 -0
  6. data/lib/commands/finish.rb +26 -0
  7. data/lib/commands/goto.rb +19 -0
  8. data/lib/commands/iterate.rb +22 -0
  9. data/lib/commands/next.rb +37 -0
  10. data/lib/commands/next_breakpoint.rb +22 -0
  11. data/lib/commands/step.rb +83 -0
  12. data/lib/commands/trace_command.rb +87 -0
  13. data/lib/commands/trace_helpers.rb +49 -0
  14. data/lib/commands/traced_method.rb +71 -0
  15. data/lib/debug_sugar.rb +73 -0
  16. data/lib/pry-moves/add_suffix.rb +87 -0
  17. data/lib/pry-moves/backtrace.rb +99 -50
  18. data/lib/pry-moves/bindings_stack.rb +106 -0
  19. data/lib/pry-moves/commands.rb +42 -3
  20. data/lib/pry-moves/error_with_data.rb +10 -0
  21. data/lib/pry-moves/formatter.rb +79 -0
  22. data/lib/pry-moves/painter.rb +3 -2
  23. data/lib/pry-moves/pry_ext.rb +66 -18
  24. data/lib/pry-moves/pry_wrapper.rb +30 -17
  25. data/lib/pry-moves/recursion_tracker.rb +94 -0
  26. data/lib/pry-moves/restartable.rb +39 -0
  27. data/lib/pry-moves/version.rb +1 -1
  28. data/lib/pry-moves/watch.rb +3 -0
  29. data/lib/pry-moves.rb +77 -6
  30. data/lib/pry-stack_explorer/frame_helpers.rb +114 -0
  31. data/lib/pry-stack_explorer/frame_manager.rb +6 -9
  32. data/lib/pry-stack_explorer/pry-stack_explorer.rb +2 -17
  33. data/lib/pry-stack_explorer/{commands.rb → stack_commands.rb} +6 -109
  34. data/lib/pry-stack_explorer/when_started_hook.rb +10 -65
  35. data/playground/Gemfile.lock +9 -5
  36. data/playground/README.md +1 -0
  37. data/playground/playground.rb +94 -9
  38. data/playground/sand.rb +12 -10
  39. data/playground/test.rb +5 -1
  40. data/playground/test.sh +1 -0
  41. data/pry-moves.gemspec +4 -2
  42. data/publish.sh +2 -1
  43. data/spec/backtrace_spec.rb +11 -13
  44. data/spec/blocks_spec.rb +41 -8
  45. data/spec/commands_spec.rb +26 -25
  46. data/spec/pry_debugger.rb +5 -1
  47. data/spec/redirection_spec.rb +7 -0
  48. data/spec/spec_helper.rb +9 -4
  49. data/spec/step_spec.rb +51 -0
  50. metadata +60 -13
  51. data/lib/pry-moves/helpers.rb +0 -56
  52. data/lib/pry-moves/trace_commands.rb +0 -109
  53. data/lib/pry-moves/traced_method.rb +0 -61
  54. data/lib/pry-moves/tracer.rb +0 -140
  55. data/lib/pry-moves/traversing.rb +0 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8826581b1684b35099d08f56064e2f3b38ccf3e0d24e3bf40779de9da58151f1
4
- data.tar.gz: d73a5a0b30ac023416e901a3a965d95b4d232bdef5c0f44ab49ec4dfc7708585
3
+ metadata.gz: a9dc991b1aed888cf23fd1e9a76b29d274ce56989119f802982e9fbdc46cc034
4
+ data.tar.gz: 25e331897d83de799b696e84d1de474166095d4e80853a7f9cde99ba64290432
5
5
  SHA512:
6
- metadata.gz: 2ade46c2440bcd4e14a296b9f3785ce0fff501abe953670ce19c9851d0b52488795113179717dffab6b57221c81839317236417bd1ce76380ceed96c3ed4a596
7
- data.tar.gz: b5b959011051e252cb8a65c1b049f0cdfd8dcd6056b47b7cc7ba87052bb84ec5e1fd767d641385ab2ac1c162f0230d6a7bc760f77ac2699bc5fdbd5d6e812a05
6
+ metadata.gz: fbaa701da70c665fe7795de825db1540e5a1ab2d4f2021c41d4294c14bce3429b34b7e64d21949f51fd08dbbc24b6ffc047776bb7207b8c73834893e0e03ced7
7
+ data.tar.gz: 169ee4d3b3e40f8f63c7969c2b709c82dfc23881c994a335b25635fbf90b798ea21616bc33c08dd0bd44418a2c996f0b5eb6079732d769ff5c061757af35f5e7
data/Gemfile CHANGED
@@ -4,6 +4,6 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :development, :test do
7
- gem 'pry'
7
+ gem 'pry', '0.11.3'
8
8
  gem 'rspec'
9
9
  end
data/Gemfile.lock CHANGED
@@ -1,9 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pry-moves (0.1.13)
4
+ pry-moves (1.0.2)
5
5
  binding_of_caller (~> 0.7)
6
- pry (>= 0.10.4, < 0.12.0)
6
+ colorize (~> 0.8)
7
+ diffy (~> 3.4.0)
8
+ pry (>= 0.10.4, < 0.13)
7
9
 
8
10
  GEM
9
11
  remote: https://rubygems.org/
@@ -11,8 +13,10 @@ GEM
11
13
  binding_of_caller (0.8.0)
12
14
  debug_inspector (>= 0.0.1)
13
15
  coderay (1.1.2)
14
- debug_inspector (0.0.3)
16
+ colorize (0.8.1)
17
+ debug_inspector (1.1.0)
15
18
  diff-lcs (1.3)
19
+ diffy (3.4.0)
16
20
  method_source (0.9.0)
17
21
  pry (0.11.3)
18
22
  coderay (~> 1.1.0)
@@ -39,10 +43,10 @@ PLATFORMS
39
43
  ruby
40
44
 
41
45
  DEPENDENCIES
42
- pry
46
+ pry (= 0.11.3)
43
47
  pry-moves!
44
48
  pry-remote (~> 0.1.6)
45
49
  rspec
46
50
 
47
51
  BUNDLED WITH
48
- 2.1.1
52
+ 1.17.3
data/README.md CHANGED
@@ -9,28 +9,39 @@ _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 latest 5 lines from backtrace
22
- * `bt 10` - latest 10 lines
23
- * `bt full` - full backtrace
24
- * `bt +` - full backtrace with hidden frames. Aliases: `bt hidden` `bt vapid` `bt all`
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
28
+ * `bt save` - save backtrace to memory
29
+ * `bt diff` - diff with saved backtrace
25
30
  * `bt > foo` - write backtrace to file `log/backtrace_foo.log`
26
- * `up`/`down`/`top`/`bottom` - move over call stack
31
+ * `up`/`down`/`top`/`bottom` (`bm`) - move over call stack
27
32
  * `up +` - move up, including vapid frames (block callers, hidden frames)
28
33
  * `up pattern` - move up till first frame which method name or file position in format `folder/script.rb:12` matches regexp pattern
34
+ * `%` - print current frame of call stack (alias to `whereami`)
35
+ * `$` - fully print current function without line numbers
29
36
  * `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
37
  * `.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
38
  * `watch variable` - display variable's value on each step
39
+ * `@` - restart. Set config `PryMoves.reload_rake_tasks = true` to automatically reload rake tasks
40
+ * `#` - exit with code 3, can be wrapped in bash script to fully reload ruby scripts
32
41
  * `!` - exit
33
42
 
43
+ Variable & methods names takes precedence over commands.
44
+ So if you have variable named `step`, to execute command `step` type `cmd step` or command's alias, e.g. `s`
34
45
 
35
46
  ## Examples
36
47
 
@@ -51,7 +62,7 @@ _Demo class source [here](https://github.com/garmoshka-mo/pry-moves/issues/1)_
51
62
 
52
63
  ## Backtrace and call stack
53
64
 
54
- You can explicitly hide frames from backtrace and call stack by defining `hide_from_stack` variable:
65
+ You can explicitly hide frames from call stack by defining variables like this:
55
66
 
56
67
  ```ruby
57
68
  def insignificant_method
@@ -61,12 +72,15 @@ def insignificant_method
61
72
  end
62
73
  ```
63
74
 
75
+ * `hide_from_stack` - hide this function from stack
76
+ * `pry_moves_stack_tip` - stop on first frame above this function
77
+ * `pry_moves_stack_end` - limits stack from bottom, not possible to step below this frame
78
+
64
79
  ## Configuration
65
80
 
66
- Here is default configuration, you can override it:
81
+ Here is default configuration, you can reassign it:
67
82
 
68
83
  ```ruby
69
- PryMoves::Backtrace::lines_count = 5
70
84
  PryMoves::Backtrace::filter =
71
85
  /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/|\/pry-moves\/)/
72
86
  ```
@@ -122,6 +136,8 @@ Please note that debugging functionality is implemented through
122
136
 
123
137
  ```
124
138
  bundle exec rspec
139
+
140
+ DEBUG=true bundle exec rspec -e 'backtrace should backtrace'
125
141
  ```
126
142
 
127
143
  ## ToDo
@@ -0,0 +1,21 @@
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 if event != 'line' or @cancel_debug
9
+ if @first_line_skipped
10
+ if binding_.local_variable_defined?(:pry_cancel_debug)
11
+ @cancel_debug = true
12
+ return
13
+ end
14
+ true
15
+ else
16
+ @first_line_skipped = true
17
+ false
18
+ end
19
+ end
20
+
21
+ 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
@@ -0,0 +1,71 @@
1
+ class PryMoves::TracedMethod < Hash
2
+
3
+ @@last = nil
4
+ def self.last
5
+ @@last
6
+ end
7
+
8
+ def initialize(binding_)
9
+ super()
10
+
11
+ method = find_method_definition binding_
12
+ if method
13
+ source = method.source_location
14
+ set_method({
15
+ file: source[0],
16
+ start: source[1],
17
+ name: method.name,
18
+ end: (source[1] + method.source.count("\n") - 1)
19
+ })
20
+ else
21
+ set_method({file: binding_.eval('__FILE__')})
22
+ end
23
+ end
24
+
25
+ def within?(file, line, id = nil)
26
+ return unless self[:file] == file
27
+ return unless self[:start].nil? or
28
+ line.between?(self[:start], self[:end])
29
+ return unless id.nil? or self[:name] == id # fix for bug in traced_method: return for dynamic methods has line number inside of caller
30
+
31
+ true
32
+ end
33
+
34
+ def binding_inside?(binding)
35
+ within? *binding.eval('[__FILE__, __LINE__, __method__]')
36
+ end
37
+
38
+ def before_end?(line)
39
+ self[:end] and line < self[:end]
40
+ end
41
+
42
+ private
43
+
44
+ def find_method_definition(binding)
45
+ method_name, obj, file =
46
+ binding.eval '[__method__, self, __FILE__]'
47
+ return unless method_name
48
+
49
+ method = obj.method(method_name)
50
+ return method if method.source_location[0] == file
51
+
52
+ # If found file was different - search definition at superclasses:
53
+ obj.class.ancestors.each do |cls|
54
+ if cls.instance_methods(false).include? method_name
55
+ method = cls.instance_method method_name
56
+ return method if method.source_location[0] == file
57
+ end
58
+ end
59
+
60
+ PryMoves.messages << "⚠️ Unable to find definition for method #{method_name} in #{obj}"
61
+
62
+ nil
63
+ end
64
+
65
+ def set_method(method)
66
+ #puts "set_traced_method #{method}"
67
+ merge! method
68
+ @@last = self
69
+ end
70
+
71
+ end
@@ -0,0 +1,73 @@
1
+ def debug *args
2
+ pry_moves_stack_end = true
3
+ PryMoves.debug *args
4
+ end
5
+
6
+ def error(msg = "Error", debug_object = nil)
7
+ pry_moves_stack_end = true
8
+ err = "😱 #{msg}"
9
+ unless PryMoves.open?
10
+ if PryMoves.stop_on_breakpoints
11
+ lines = [err.red]
12
+ lines.prepend debug_object.ai if debug_object
13
+ PryMoves.error lines.join("\n")
14
+ else
15
+ STDERR.puts debug_object.ai if debug_object
16
+ STDERR.puts err.ljust(80, ' ').red
17
+ end
18
+ end
19
+ raise PryMoves::ErrorWithData.new(msg, debug_object)
20
+ end
21
+
22
+ def shit!(err = 'Oh, shit!', debug_object = nil)
23
+ return if ENV['NO_SHIT']
24
+ pry_moves_stack_end = true
25
+ message = "💩 #{err.is_a?(String) ? err : err.message}"
26
+ raise err unless PryMoves.stop_on_breakpoints
27
+ lines = [message.red]
28
+ lines.prepend debug_object.ai if debug_object
29
+ PryMoves.error lines.join("\n")
30
+ nil
31
+ end
32
+
33
+ def required(var)
34
+ pry_moves_stack_end = true
35
+ error("required parameter is missing") if var.nil?
36
+ var
37
+ end
38
+
39
+ RSpec.configure do |config|
40
+
41
+ config.before(:each) do
42
+ PryMoves.launched_specs_examples += 1
43
+ PryMoves.stop_on_breakpoints =
44
+ PryMoves.launched_specs_examples < 2
45
+ end
46
+
47
+ config.around(:each) do |example|
48
+ PryMoves.restartable(rspec_example: example) do
49
+ example.run
50
+ end
51
+ end
52
+
53
+ end if defined? RSpec
54
+
55
+ Rake::Task.class_eval do
56
+
57
+ alias execute_origin_for_pry_moves execute
58
+
59
+ def execute(args=nil)
60
+ args ||= EMPTY_TASK_ARGS
61
+ PryMoves.restartable(rake_args: args) do
62
+ reload_actions if PryMoves.reload_rake_tasks
63
+ execute_origin_for_pry_moves args
64
+ end
65
+ end
66
+
67
+ def reload_actions
68
+ rake_task_path = actions[0].source_location[0]
69
+ actions.clear
70
+ load rake_task_path
71
+ end
72
+
73
+ end if defined? Rake and defined? Rake::Task