Skip to content

Commit 7455bb8

Browse files
committed
until command
remove `step into` command too. fix #796
1 parent 67f7223 commit 7455bb8

File tree

3 files changed

+107
-31
lines changed

3 files changed

+107
-31
lines changed

lib/debug/session.rb

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,6 @@ def register_default_command
431431
# * Step in. Resume the program until next breakable point.
432432
# * `s[tep] <n>`
433433
# * Step in, resume the program at `<n>`th breakable point.
434-
# * `s[tep] into <name>` or `s[tep] into /regexp/`
435-
# * Stop at the beggining of method `<name>` or the name matched to `/regexp/`
436434
register_command 's', 'step',
437435
repeat: true,
438436
cancel_auto_continue: true,
@@ -466,6 +464,21 @@ def register_default_command
466464
step_command :finish, arg
467465
end
468466

467+
# * `u[ntil]`
468+
# * Similar to `next` command, but only stop later lines or the end of the current frame.
469+
# * Similar to gdb's `advance` command.
470+
# * `u[ntil] <[file:]line>
471+
# * Run til the program reaches given location or the end of the current frame.
472+
# * `u[ntil] <name>
473+
# * Run til the program invokes a method `<name>`. `<name>` can be a regexp with `/name/`.
474+
register_command 'u', 'until',
475+
repeat: true,
476+
cancel_auto_continue: true,
477+
postmortem: false do |arg|
478+
479+
step_command :until, arg
480+
end
481+
469482
# * `c[ontinue]`
470483
# * Resume the program.
471484
register_command 'c', 'continue',
@@ -1105,6 +1118,11 @@ def repl_open_vscode
11051118
end
11061119

11071120
def step_command type, arg
1121+
if type == :until
1122+
leave_subsession [:step, type, arg]
1123+
return
1124+
end
1125+
11081126
case arg
11091127
when nil, /\A\d+\z/
11101128
if type == :in && @tc.recorder&.replaying?
@@ -1121,14 +1139,6 @@ def step_command type, arg
11211139
iter = $2&.to_i
11221140
request_tc [:step, type, iter]
11231141
end
1124-
when /\Ainto\s+(\S+)(\s+(\d+))?\z/
1125-
pat = $1
1126-
iter = $3&.to_i
1127-
if /\A\/(.+)\/\z/ =~ pat
1128-
pat = Regexp.new($1)
1129-
end
1130-
1131-
request_tc [:step, :into, pat, iter]
11321142
else
11331143
@ui.puts "Unknown option: #{arg}"
11341144
:retry

lib/debug/thread_client.rb

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -863,13 +863,6 @@ def wait_next_action_
863863
break
864864
end
865865

866-
when :into
867-
pat, iter = args[1], args[2]
868-
step_tp iter, [:call, :c_call] do |tp|
869-
pat === tp.callee_id.to_s
870-
end
871-
break
872-
873866
when :next
874867
frame = @target_frames.first
875868
path = frame.location.absolute_path || "!eval:#{frame.path}"
@@ -908,6 +901,47 @@ def wait_next_action_
908901
end
909902
break
910903

904+
when :until
905+
location = iter&.strip
906+
frame = @target_frames.first
907+
depth = frame.frame_depth
908+
target_location_label = frame.location.base_label
909+
910+
case location
911+
when nil, /\A(?:(.+):)?(\d+)\z/
912+
file = $1
913+
line = ($2 || frame.location.lineno + 1).to_i
914+
915+
step_tp nil, [:line, :return] do |tp|
916+
if tp.event == :line
917+
next true if file && tp.path.end_with?(file)
918+
next true if tp.lineno >= line
919+
else
920+
next true if depth >= DEBUGGER__.frame_depth - 3 &&
921+
caller_locations(2, 1).first.label == target_location_label
922+
# TODO: imcomplete condition
923+
end
924+
end
925+
else
926+
pat = location
927+
if /\A\/(.+)\/\z/ =~ pat
928+
pat = Regexp.new($1)
929+
end
930+
931+
step_tp nil, [:call, :c_call, :return] do |tp|
932+
case tp.event
933+
when :call, :c_call
934+
next true if pat === tp.callee_id.to_s
935+
else # :return, :b_return
936+
next true if depth >= DEBUGGER__.frame_depth - 3 &&
937+
caller_locations(2, 1).first.label == target_location_label
938+
# TODO: imcomplete condition
939+
end
940+
end
941+
end
942+
943+
break
944+
911945
when :back
912946
iter = iter || 1
913947
if @recorder&.can_step_back?

test/console/control_flow_commands_test.rb

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,6 @@ def test_step_with_number_goes_to_the_next_nth_statement
6363
end
6464
end
6565

66-
def test_step_into
67-
debug_code program do
68-
type 'step into name'
69-
assert_line_num 7
70-
type 'step into xyzzy' # doesn't match
71-
end
72-
73-
debug_code program do
74-
type 'step into /.ame/'
75-
assert_line_num 7
76-
type 'step into xyzzy' # doesn't match
77-
end
78-
end
79-
8066
def test_next_goes_to_the_next_line
8167
debug_code(program) do
8268
type 'b 11'
@@ -419,6 +405,52 @@ def test_finish_should_be_canceled
419405
end
420406
end
421407

408+
class UntilTest < ConsoleTestCase
409+
def program
410+
<<~RUBY
411+
1| 3.times do
412+
2| a = 1
413+
3| b = 2
414+
4| end
415+
5| c = 3
416+
6| def foo
417+
7| x = 1
418+
8| end
419+
9| foo
420+
RUBY
421+
end
422+
423+
def test_until_line
424+
debug_code program do
425+
type 'u 2'
426+
assert_line_num 2
427+
type 'u'
428+
assert_line_num 3
429+
type 'u'
430+
assert_line_num 5
431+
type 'c'
432+
end
433+
end
434+
435+
def test_until_line_overrun
436+
debug_code program do
437+
type 'u 2'
438+
assert_line_num 2
439+
type 'u 100'
440+
end
441+
end
442+
443+
def test_until_method
444+
debug_code program do
445+
type 'u foo'
446+
assert_line_num 7
447+
type 'u bar'
448+
assert_line_num 8
449+
type 'c'
450+
end
451+
end
452+
end
453+
422454
#
423455
# Tests that next/finish work for a deep call stack.
424456
# We use different logic for computing frame depth when the call stack is above/below 4096.

0 commit comments

Comments
 (0)