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
@@ -1,117 +1,13 @@
1
- module PryStackExplorer
2
- module FrameHelpers
3
- private
4
-
5
- # @return [PryStackExplorer::FrameManager] The active frame manager for
6
- # the current `Pry` instance.
7
- def frame_manager
8
- PryStackExplorer.frame_manager(_pry_)
9
- end
10
-
11
- # @return [Array<PryStackExplorer::FrameManager>] All the frame
12
- # managers for the current `Pry` instance.
13
- def frame_managers
14
- PryStackExplorer.frame_managers(_pry_)
15
- end
16
-
17
- # @return [Boolean] Whether there is a context to return to once
18
- # the current `frame_manager` is popped.
19
- def prior_context_exists?
20
- frame_managers.count > 1 || frame_manager.prior_binding
21
- end
22
-
23
- # Return a description of the frame (binding).
24
- # This is only useful for regular old bindings that have not been
25
- # enhanced by `#of_caller`.
26
- # @param [Binding] b The binding.
27
- # @return [String] A description of the frame (binding).
28
- def frame_description(b)
29
- b_self = b.eval('self')
30
- b_method = b.eval('__method__')
31
-
32
- if b_method && b_method != :__binding__ && b_method != :__binding_impl__
33
- b_method.to_s
34
- elsif b_self.instance_of?(Module)
35
- "<module:#{b_self}>"
36
- elsif b_self.instance_of?(Class)
37
- "<class:#{b_self}>"
38
- else
39
- "<main>"
40
- end
41
- end
42
-
43
- # Return a description of the passed binding object. Accepts an
44
- # optional `verbose` parameter.
45
- # @param [Binding] b The binding.
46
- # @param [Boolean] verbose Whether to generate a verbose description.
47
- # @return [String] The description of the binding.
48
- def frame_info(b, verbose = false)
49
- b_self = b.eval('self')
50
- type = b.frame_type ? "[#{b.frame_type}]".ljust(9) : ""
51
- desc = b.frame_description ? "#{b.frame_description}" : "#{frame_description(b)}"
52
- sig = PryMoves::Helpers.method_signature_with_owner b
53
-
54
- self_clipped = "#{Pry.view_clip(b_self)}"
55
- path = "@ #{b.eval('__FILE__')}:#{b.eval('__LINE__')}"
56
-
57
- if !verbose
58
- "#{type} #{desc} #{sig}"
59
- else
60
- "#{type} #{desc} #{sig}\n in #{self_clipped} #{path}"
61
- end
62
- end
63
-
64
- def find_frame_by_regex(regex, up_or_down)
65
- frame_index = find_frame_by_block(up_or_down) do |b|
66
- (b.eval('"#{__FILE__}:#{__LINE__}"') =~ regex) or
67
- (b.eval("__method__").to_s =~ regex)
68
- end
1
+ require_relative 'frame_helpers.rb'
69
2
 
70
- frame_index || raise(Pry::CommandError, "No frame that matches #{regex.source} found")
71
- end
72
-
73
- def find_frame_by_block(up_or_down)
74
- start_index = frame_manager.binding_index
75
-
76
- if up_or_down == :down
77
- enum = start_index == 0 ? [].each :
78
- frame_manager.bindings[0..start_index - 1].reverse_each
79
- else
80
- enum = frame_manager.bindings[start_index + 1..-1]
81
- end
82
-
83
- new_frame = enum.find do |b|
84
- yield(b)
85
- end
86
-
87
- frame_manager.bindings.index(new_frame)
88
- end
89
-
90
- def find_frame_by_direction(up_or_down, step_into_vapid: false)
91
- frame_index = find_frame_by_block(up_or_down) do |b|
92
- step_into_vapid or
93
- not b.local_variable_defined?(:vapid_frame)
94
- end
95
-
96
- frame_index ||
97
- raise(Pry::CommandError, "At #{up_or_down == :up ? 'top' : 'bottom'} of stack, cannot go further")
98
- end
3
+ module PryStackExplorer
99
4
 
100
- def move(direction, param)
101
- raise Pry::CommandError, "Nowhere to go" unless frame_manager
5
+ COMMANDS = Pry::CommandSet.new do
102
6
 
103
- if param == '+' or param.nil?
104
- index = find_frame_by_direction direction, step_into_vapid: param == '+'
105
- frame_manager.change_frame_to index
106
- else
107
- index = find_frame_by_regex(Regexp.new(param), direction)
108
- frame_manager.change_frame_to index
109
- end
7
+ block_command '%', 'Print current stack frame' do
8
+ run 'whereami'
110
9
  end
111
- end
112
-
113
10
 
114
- Commands = Pry::CommandSet.new do
115
11
  create_command "up", "Go up to the caller's context." do
116
12
  include FrameHelpers
117
13
 
@@ -159,6 +55,7 @@ module PryStackExplorer
159
55
  frame_manager.change_frame_to 0
160
56
  end
161
57
  end
58
+ alias_command 'bm', 'bottom'
162
59
 
163
60
  create_command "frame", "Switch to a particular frame." do
164
61
  include FrameHelpers
@@ -2,94 +2,39 @@ module PryStackExplorer
2
2
  class WhenStartedHook
3
3
  include Pry::Helpers::BaseHelpers
4
4
 
5
- def caller_bindings(target)
6
- bindings = binding.callers
7
- pre_callers = Thread.current[:pre_callers]
8
- bindings = bindings + pre_callers if pre_callers
9
- bindings = remove_internal_frames(bindings)
10
- mark_vapid_frames(bindings)
11
- bindings
12
- end
13
-
14
5
  def call(target, options, _pry_)
15
6
  start_from_console = target.eval('__callee__').nil? &&
16
7
  target.eval('__FILE__') == '<main>' &&
17
8
  target.eval('__LINE__') == 0
18
9
  return if start_from_console
19
10
 
20
- target ||= _pry_.binding_stack.first if _pry_
21
11
  options = {
22
- :call_stack => true,
23
- :initial_frame => 0
12
+ call_stack: true
24
13
  }.merge!(options)
25
14
 
26
- return if !options[:call_stack]
15
+ return unless options[:call_stack]
16
+ initial_frame = options[:initial_frame]
27
17
 
28
18
  if options[:call_stack].is_a?(Array)
29
19
  bindings = options[:call_stack]
30
-
20
+ initial_frame ||= 0
31
21
  unless valid_call_stack?(bindings)
32
22
  raise ArgumentError, ":call_stack must be an array of bindings"
33
23
  end
34
24
  else
35
- bindings = caller_bindings(target)
36
- initial_frame = bindings.find do |b|
37
- not b.local_variable_defined?(:vapid_frame)
25
+ bindings = PryMoves::BindingsStack.new options
26
+ initial_frame ||= bindings.suggest_initial_frame_index
27
+ # if Thread.current[:pry_moves_debug] and initial_frame > 0
28
+ if initial_frame > 0
29
+ PryMoves.messages << "👽 Frames hidden: #{initial_frame}"
38
30
  end
39
- options[:initial_frame] = bindings.index initial_frame
40
31
  end
41
32
 
42
- PryStackExplorer.create_and_push_frame_manager bindings, _pry_, initial_frame: options[:initial_frame]
33
+ PryStackExplorer.create_and_push_frame_manager bindings, _pry_, initial_frame: initial_frame
43
34
  end
44
35
 
45
36
  private
46
37
 
47
- def mark_vapid_frames(bindings)
48
- stepped_out = false
49
- actual_file, actual_method = nil, nil
50
-
51
- bindings.each do |binding|
52
- if stepped_out
53
- if actual_file == binding.eval("__FILE__") and actual_method == binding.eval("__method__")
54
- stepped_out = false
55
- else
56
- binding.local_variable_set :vapid_frame, true
57
- end
58
- elsif binding.frame_type == :block
59
- stepped_out = true
60
- actual_file = binding.eval("__FILE__")
61
- actual_method = binding.eval("__method__")
62
- end
63
-
64
- if binding.local_variable_defined? :hide_from_stack
65
- binding.local_variable_set :vapid_frame, true
66
- end
67
- end
68
- end
69
-
70
- # remove internal frames related to setting up the session
71
- def remove_internal_frames(bindings)
72
- i = top_internal_frame_index(bindings)
73
- # DEBUG:
74
- #bindings.each_with_index do |b, index|
75
- # puts "#{index}: #{b.eval("self.class")} #{b.eval("__method__")}"
76
- #end
77
- #puts "FOUND top internal frame: #{bindings.size} => #{i}"
78
-
79
- bindings.drop i+1
80
- end
81
-
82
- def top_internal_frame_index(bindings)
83
- bindings.rindex do |b|
84
- if b.frame_type == :method
85
- self_, method = b.eval("self"), b.eval("__method__")
86
- self_.equal?(Pry) && method == :start ||
87
- self_.class == Binding && method == :pry ||
88
- self_.class == PryMoves::Tracer && method == :tracing_func
89
- end
90
- end
91
- end
92
-
93
38
  def valid_call_stack?(bindings)
94
39
  bindings.any? && bindings.all? { |v| v.is_a?(Binding) }
95
40
  end
@@ -1,17 +1,21 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- pry-moves (0.1.11)
4
+ pry-moves (1.0.1)
5
5
  binding_of_caller (~> 0.7)
6
- pry (>= 0.10.4, < 1)
6
+ colorize (~> 0.8)
7
+ diffy
8
+ pry (>= 0.10.4, < 0.13)
7
9
 
8
10
  GEM
9
11
  remote: https://rubygems.org/
10
12
  specs:
11
13
  binding_of_caller (0.8.0)
12
14
  debug_inspector (>= 0.0.1)
13
- coderay (1.1.2)
14
- debug_inspector (0.0.3)
15
+ coderay (1.1.3)
16
+ colorize (0.8.1)
17
+ debug_inspector (1.1.0)
18
+ diffy (3.4.0)
15
19
  method_source (0.9.2)
16
20
  pry (0.12.2)
17
21
  coderay (~> 1.1.0)
@@ -24,4 +28,4 @@ DEPENDENCIES
24
28
  pry-moves!
25
29
 
26
30
  BUNDLED WITH
27
- 1.17.0
31
+ 1.17.3
data/playground/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ```
4
4
  be ruby sand.rb
5
+ be ruby test.rb
5
6
  ```
6
7
 
7
8
  ## Conditions to be met
@@ -16,6 +16,23 @@ class Playground
16
16
  binding.pry # step_into stop
17
17
  something_inside # point to step inside
18
18
  end
19
+
20
+ def skip_hidden_impl
21
+ binding.pry # skip_hidden_impl stop
22
+ hidden_self.something_inside # point to step inside
23
+ end
24
+
25
+ def hidden_self
26
+ hide_from_stack = true # hidden_self 1
27
+ self # hidden_self 2
28
+ end
29
+
30
+ def hidden_stop
31
+ hide_from_stack = true
32
+ binding.pry # hidden stop
33
+ dummy = :ok_next # hidden_stop for next
34
+ dummy = :ok_step # hidden_stop for step
35
+ end
19
36
 
20
37
  def continue
21
38
  binding.pry # first stop
@@ -39,6 +56,16 @@ class Playground
39
56
  step_by_name
40
57
  :after_step_by_name # after_step_by_name
41
58
  end
59
+
60
+ def early_return_wrap
61
+ early_return
62
+ :after_return # after early return
63
+ end
64
+
65
+ def early_return
66
+ return true if level_c # at early return
67
+ dummy = 1
68
+ end
42
69
 
43
70
  def level_a
44
71
  level_b # inside of level_a
@@ -52,7 +79,7 @@ class Playground
52
79
  def level_c(param = nil)
53
80
  binding.pry # stop in level_c
54
81
  self
55
- end
82
+ end # exit from level_c
56
83
 
57
84
  def nested_block(early_return: false)
58
85
  binding.pry # stop in nested_block
@@ -62,7 +89,7 @@ class Playground
62
89
  end
63
90
  :after_block # after block
64
91
  end
65
-
92
+
66
93
  def native_block(early_return: false)
67
94
  binding.pry # stop in native_block
68
95
  2.times do |i| # iterator line
@@ -72,25 +99,83 @@ class Playground
72
99
  :after_block # after block
73
100
  end
74
101
 
102
+ def one_line_in_block
103
+ binding.pry # stop in one_line_in_block
104
+ iterator do |i| # iterator line
105
+ dummy = 1 # inside block
106
+ end
107
+ :after_block # after block
108
+ end
109
+
110
+ def one_line_block
111
+ binding.pry # stop in one_line_block
112
+ iterator { |i| dummy = 1 } # iterator line
113
+ :after_block # after block
114
+ end
115
+
116
+ def parentheses_in_loop
117
+ binding.pry # stop in parentheses_in_loop
118
+ i = 2
119
+ while (i = i - 1) > 0 # iterator line
120
+ dummy = 1 # inside block
121
+ end
122
+ :after_block # after block
123
+ end
124
+
75
125
  def zaloop(pass = :root)
76
126
  binding.pry if pass == :root # stop in zaloop
77
- iterator do |i|
127
+ iterator do |i| # iterator line
78
128
  dummy = 1 # inside block
79
129
  zaloop i if pass == :root
130
+ return unless pass == :root # after sub-zaloop
80
131
  end
81
132
  :after_block # after block
82
- end
133
+ end # exit from zaloop
83
134
 
84
135
  def method_with_redirection
85
- debug_redirect = '=level_a' # at method_with_redirection
136
+ debug_redirect = :level_a # at method_with_redirection
86
137
  level_a
87
138
  end
88
139
 
140
+ def instant_redirection
141
+ debug_redirect = '=something_inside'
142
+ binding.pry # at instant_redirection
143
+ something_inside
144
+ end
145
+
89
146
  def redirection_host
90
147
  binding.pry # redirection host
91
148
  method_with_redirection
92
149
  end
93
150
 
151
+ def something_inside
152
+ :something # some internal line
153
+ end
154
+
155
+ def method_with_breakpoints
156
+ binding.pry # method_with_breakpoints host
157
+ dummy = 1 # some internal line
158
+ debug_ # breakpoint
159
+ dummy = 1 # after breakpoint
160
+ dummy = 1 # after after breakpoint
161
+ debug_ # breakpoint 2
162
+ dummy = 1 # after breakpoint 2
163
+ end
164
+
165
+ def skip_test
166
+ binding.pry # stop in skip_test
167
+ skipped_method.not_skipped_method # next step
168
+ end
169
+
170
+ def skipped_method
171
+ pry_moves_skip = true # at skipped_method
172
+ self # at skipped_method
173
+ end
174
+
175
+ def not_skipped_method
176
+ :not_skipped_method # at not_skipped_method
177
+ end
178
+
94
179
  private
95
180
 
96
181
  def iterator
@@ -99,10 +184,10 @@ class Playground
99
184
  yield i
100
185
  :post_yield # post_yield
101
186
  end
102
- end
103
-
104
- def something_inside
105
- :something # some internal line
187
+ end # exit from iterator
188
+
189
+ def debug_
190
+ :something # inside of debug method
106
191
  end
107
192
 
108
193
  end
data/playground/sand.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # cd playground
2
+ # be ruby sand.rb
3
+
1
4
  require 'pry-moves'
2
5
  require './tracer.rb'
3
6
 
@@ -7,42 +10,41 @@ def fi(param)
7
10
  puts param
8
11
  end
9
12
 
10
- class A
13
+ class Sand
11
14
 
12
15
  def initialize
13
16
  puts :xuilo
14
17
  end
15
18
 
16
- def aa
19
+ def some_logic
17
20
  puts 'aa: step 1'
18
21
  puts 'aa: step 2'
19
22
  end
20
23
 
21
- def bb
24
+ def method_with_hidden_stack
22
25
  debug_redirect = :aa
23
26
  hide_from_stack = true
24
27
  puts 'bb: step 1'
25
28
  puts 'bb: step 2'
26
- aa
29
+ some_logic
27
30
  end
28
31
 
29
- def cc
32
+ def debugged_method
30
33
  koko = :love
31
- binding.pry
32
- bb
34
+ debug
35
+ method_with_hidden_stack
33
36
  (2..4).each do |i|
34
37
  puts i
35
38
  end
36
39
  puts :two
37
40
  end
38
- alias cc_al cc
41
+ alias debugged_method_alias debugged_method
39
42
 
40
43
  end
41
44
 
42
45
  puts :prepare
43
46
 
44
- A.new.cc_al
45
- A.new.cc_al
47
+ Sand.new.method_with_hidden_stack
46
48
 
47
49
 
48
50
  bb = 1
data/playground/test.rb CHANGED
@@ -2,4 +2,8 @@ require 'pry-moves'
2
2
  require_relative '../playground/playground.rb'
3
3
 
4
4
  i = Playground.new
5
- i.recursion
5
+ if ARGV[0]
6
+ i.send ARGV[0]
7
+ else
8
+ i.zaloop
9
+ end
@@ -0,0 +1 @@
1
+ bundle exec ruby playground/test.rb $@
data/pry-moves.gemspec CHANGED
@@ -18,8 +18,10 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  # Dependencies
21
- gem.required_ruby_version = '>= 1.8.7'
22
- gem.add_runtime_dependency 'pry', '>= 0.10.4', '< 0.12.0'
21
+ gem.required_ruby_version = '>= 1.8.7', '< 3'
22
+ gem.add_runtime_dependency 'pry', '>= 0.10.4', '< 0.13'
23
23
  gem.add_runtime_dependency 'binding_of_caller', '~> 0.7'
24
+ gem.add_runtime_dependency 'colorize', '~> 0.8'
25
+ gem.add_runtime_dependency 'diffy', '~> 3.4.0'
24
26
  gem.add_development_dependency 'pry-remote', '~> 0.1.6'
25
27
  end
data/publish.sh CHANGED
@@ -1,2 +1,3 @@
1
- gem build pry-moves.gemspec
1
+ bundle exec rspec && \
2
+ gem build pry-moves.gemspec && \
2
3
  gem push pry-moves-`ruby -e 'require "./lib/pry-moves/version.rb"; puts PryMoves::VERSION'`.gem
@@ -7,25 +7,23 @@ describe 'backtrace' do
7
7
  [nil, 'stop in level_c'],
8
8
  ['bt', lambda{|b, output|
9
9
  lines = output.split("\n").reverse
10
- expect(lines[0]).to end_with 'level_c(param=?)'
11
- expect(lines[1]).to end_with 'level_a()'
12
- expect(lines[2]).to include 'Playground:'
13
- expect(lines[3]).to end_with ':block'
14
- expect(lines[4]).to include 'RSpec::ExampleGroups'
15
- expect(lines.count).to be 5
10
+ expect(lines[0]).to end_with 'level_c(param=? nil)'
11
+ expect(lines[1]).to end_with 'frames hidden: 1'
12
+ expect(lines[2]).to end_with 'level_a()'
13
+ expect(lines[3]).to include 'Playground'
14
+ expect(lines[4]).to end_with ':block'
15
+ expect(lines[5]).to include 'RSpec::ExampleGroups'
16
+ expect(lines.count).to be 7
16
17
  }],
17
- ['bt all', lambda{|b, output|
18
+ ['bt hidden', lambda{|b, output|
18
19
  lines = output.split("\n").reverse
19
20
  # show hidden frame
20
21
  expect(lines[1]).to end_with 'level_b()'
21
- expect(lines.count).to be 6
22
+ expect(lines.count).to be 11
22
23
  }],
23
- ['bt 2', lambda{|b, output|
24
+ ['up', lambda{|b, output|
24
25
  lines = output.split("\n").reverse
25
- expect(lines[0]).to end_with 'level_c(param=?)'
26
- expect(lines[1]).to end_with 'level_a()'
27
- expect(lines[3]).to start_with 'Latest 2 lines'
28
- expect(lines.count).to be 4
26
+ expect(lines[1]).to end_with 'level_b # inside of level_a'
29
27
  }],
30
28
  ]
31
29
  Playground.new.level_a
data/spec/blocks_spec.rb CHANGED
@@ -5,7 +5,7 @@ describe 'blocks' do
5
5
  it 'should go next over blocks' do
6
6
  breakpoints [
7
7
  [nil, 'stop in zaloop'],
8
- ['n', ''],
8
+ ['n', 'iterator line'],
9
9
  # repeat commands
10
10
  ['', 'inside block'],
11
11
  ['', nil],
@@ -15,11 +15,10 @@ describe 'blocks' do
15
15
  ['', 'inside block'],
16
16
  ['pass', {output: '=> 0'}],
17
17
 
18
- ['f', 'after block'],
19
- ['pass', {output: '=> 0'}],
18
+ ['f', 'iterator line'],
19
+ ['f', 'after sub-zaloop'],
20
+ ['pass', {output: '=> :root'}],
20
21
 
21
- ['f', 'post_yield'], # Тут хорошо бы, чтобы сразу шёл на "after block",
22
- # но пока и не понятно, как это угадать
23
22
  ['f', 'after block'],
24
23
  ['pass', {output: '=> :root'}],
25
24
  ]
@@ -39,7 +38,7 @@ describe 'blocks' do
39
38
  it 'should finish block with sub-calls' do
40
39
  breakpoints [
41
40
  [nil, 'stop in zaloop'],
42
- ['n', ''],
41
+ ['n', 'iterator line'],
43
42
  ['', 'inside block'],
44
43
  ['f', 'after block'],
45
44
  ['pass', {output: '=> :root'}],
@@ -79,7 +78,7 @@ describe 'blocks' do
79
78
  ['n', 'iterator line'],
80
79
  ['n', 'inside block'],
81
80
  ['iterate', 'iterator line'],
82
- ['n', 'exit'],
81
+ ['n', 'exit']
83
82
  ]
84
83
  Playground.new.native_block early_return: true
85
84
  :exit # exit
@@ -91,10 +90,44 @@ describe 'blocks' do
91
90
  ['n', 'iterator line'],
92
91
  ['n', 'inside block'],
93
92
  ['iterate', 'iterator line'],
94
- ['n', 'exit'],
93
+ ['n', 'exit']
95
94
  ]
96
95
  Playground.new.nested_block early_return: true
97
96
  :exit # exit
98
97
  end
98
+
99
+ it 'should iterate over one-line in block' do
100
+ breakpoints [
101
+ [nil, 'stop in one_line_in_block'],
102
+ ['n', 'iterator line'],
103
+ ['n', 'inside block'],
104
+ ['i', {output: '=> 0'}],
105
+ ['n', 'inside block'],
106
+ ['i', {output: '=> 1'}],
107
+ ['n', 'after block'],
108
+ ]
109
+ Playground.new.one_line_in_block
110
+ end
111
+
112
+ it 'should skip one-line block' do
113
+ breakpoints [
114
+ [nil, 'stop in one_line_block'],
115
+ ['n', 'iterator line'],
116
+ ['n', 'after block']
117
+ ]
118
+ Playground.new.one_line_block
119
+ end
120
+
121
+ it 'should skip parentheses in loop' do
122
+ breakpoints [
123
+ [nil, 'stop in parentheses_in_loop'],
124
+ ['n', nil],
125
+ ['n', 'iterator line'],
126
+ ['n', 'inside block'],
127
+ ['n', 'iterator line'],
128
+ ['n', 'after block']
129
+ ]
130
+ Playground.new.parentheses_in_loop
131
+ end
99
132
 
100
133
  end