From f45f14cc1def74729edc05060975697aad3b0d92 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 25 Nov 2022 14:48:13 +0900 Subject: [PATCH 1/2] modify test target script --- test/console/control_flow_commands_test.rb | 109 +++++++++++---------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/test/console/control_flow_commands_test.rb b/test/console/control_flow_commands_test.rb index 0ac6ee521..c6dcea3c7 100644 --- a/test/console/control_flow_commands_test.rb +++ b/test/console/control_flow_commands_test.rb @@ -10,114 +10,117 @@ class BasicControlFlowTest < ConsoleTestCase def program <<~RUBY 1| class Student - 2| def initialize(name) - 3| @name = name + 2| def initialize(name, age) + 3| @name = name; @age = age 4| end 5| 6| def name 7| @name 8| end - 9| end - 10| - 11| s = Student.new("John") - 12| s.name - 13| "foo" + 9| + 10| def age + 11| @age + 12| end + 13| end + 14| + 15| s = Student.new("John", 17) + 16| s.name; s.age + 17| s.inspect # do not show RUBY end def test_step_goes_to_the_next_statement - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 + assert_line_num 15 type 's' assert_line_num 3 type 's' assert_line_num 4 type 's' - assert_line_num 12 + assert_line_num 16 type 's' assert_line_num 7 type 's' assert_line_num 8 type 's' - assert_line_num 13 - type 'quit' - type 'y' + assert_line_num 11 + type 's' + assert_line_num 12 + type 's' + assert_line_num 17 + type 's' end end def test_step_with_number_goes_to_the_next_nth_statement - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 + assert_line_num 15 type 's 2' assert_line_num 4 type 's 3' assert_line_num 8 - type 's' - assert_line_num 13 - type 'quit' - type 'y' + type 's 2' + assert_line_num 12 + type 's 2' end end def test_next_goes_to_the_next_line - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 + assert_line_num 15 type 'n' - assert_line_num 12 + assert_line_num 16 + type 'n' + assert_line_num 17 type 'n' - assert_line_num 13 - type 'quit' - type 'y' end end def test_next_with_number_goes_to_the_next_nth_line - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 + assert_line_num 15 type 'n 2' - assert_line_num 13 - type 'quit' - type 'y' + assert_line_num 17 + type 'n' end end def test_continue_goes_to_the_next_breakpoint - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 - type 'b 13' + assert_line_num 15 + type 'b 17' + type 'c' + assert_line_num 17 type 'c' - assert_line_num 13 - type 'quit' - type 'y' end end def test_finish_leaves_the_current_frame - debug_code(program) do - type 'b 11' + debug_code program do + type 'b 15' type 'c' - assert_line_num 11 + assert_line_num 15 type 's' assert_line_num 3 type 'fin' assert_line_num 4 type 's' - assert_line_num 12 + assert_line_num 16 type 's' assert_line_num 7 type 'fin' assert_line_num 8 - type 'kill!' + type 'c' end end end @@ -136,7 +139,7 @@ def program end def test_step_steps_out_of_blocks_when_done - debug_code(program) do + debug_code program do type 'step' assert_line_num 2 type 'step' @@ -153,7 +156,7 @@ def test_step_steps_out_of_blocks_when_done end def test_next_steps_out_of_blocks_right_away - debug_code(program) do + debug_code program do type 'step' assert_line_num 2 type 'next' @@ -309,7 +312,7 @@ def program end def test_next_steps_out_of_if_blocks_when_done - debug_code(program) do + debug_code program do type 'next' assert_line_num 6 type 'quit' @@ -318,7 +321,7 @@ def test_next_steps_out_of_if_blocks_when_done end def test_step_steps_out_of_if_blocks_when_done - debug_code(program) do + debug_code program do type 'step' assert_line_num 6 type 'quit' @@ -347,7 +350,7 @@ def program end def test_next_steps_over_rescue_when_raising_from_method - debug_code(program) do + debug_code program do type 'break Foo::Bar.raise_error' type 'continue' assert_line_num 4 @@ -479,7 +482,7 @@ def program end def test_next - debug_code(program) do + debug_code program do type 'b 13' type 'c' assert_line_num 13 @@ -490,7 +493,7 @@ def test_next end def test_finish - debug_code(program) do + debug_code program do type 'b 13' type 'c' assert_line_num 13 From a8e9774aa039fc8afb94067820d2d7e891802cfb Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 25 Nov 2022 15:46:24 +0900 Subject: [PATCH 2/2] fix next/finish/until for duplicate lines On the code like that: ```ruby foo; bar next_line ``` and breaking at the end of `foo`, `next` command moves to the beggining of `bar`, bit it should be `next_line`. This patch solves this issue. --- lib/debug/thread_client.rb | 55 ++++++++++++++-------- test/console/control_flow_commands_test.rb | 49 +++++++++++++++++-- 2 files changed, 79 insertions(+), 25 deletions(-) diff --git a/lib/debug/thread_client.rb b/lib/debug/thread_client.rb index 1379352f2..5cce77a06 100644 --- a/lib/debug/thread_client.rb +++ b/lib/debug/thread_client.rb @@ -870,6 +870,7 @@ def wait_next_action_ frame = @target_frames.first path = frame.location.absolute_path || "!eval:#{frame.path}" line = frame.location.lineno + label = frame.location.base_label if frame.iseq frame.iseq.traceable_lines_norec(lines = {}) @@ -881,23 +882,32 @@ def wait_next_action_ depth = @target_frames.first.frame_depth - step_tp iter do + step_tp iter do |tp| loc = caller_locations(2, 1).first loc_path = loc.absolute_path || "!eval:#{loc.path}" + loc_label = loc.base_label + loc_depth = DEBUGGER__.frame_depth - 3 - # same stack depth - (DEBUGGER__.frame_depth - 3 <= depth) || - - # different frame - (next_line && loc_path == path && - (loc_lineno = loc.lineno) > line && - loc_lineno <= next_line) + case + when loc_depth == depth && loc_label == label + true + when loc_depth < depth + # lower stack depth + true + when (next_line && + loc_path == path && + (loc_lineno = loc.lineno) > line && + loc_lineno <= next_line) + # different frame (maybe block) but the line is before next_line + true + end end break when :finish finish_frames = (iter || 1) - 1 - goal_depth = @target_frames.first.frame_depth - finish_frames + frame = @target_frames.first + goal_depth = frame.frame_depth - finish_frames - (frame.has_return_value ? 1 : 0) step_tp nil, [:return, :b_return] do DEBUGGER__.frame_depth - 3 <= goal_depth ? true : false @@ -907,22 +917,25 @@ def wait_next_action_ when :until location = iter&.strip frame = @target_frames.first - depth = frame.frame_depth + depth = frame.frame_depth - (frame.has_return_value ? 1 : 0) target_location_label = frame.location.base_label case location when nil, /\A(?:(.+):)?(\d+)\z/ - file = $1 + no_loc = !location + file = $1 || frame.location.path line = ($2 || frame.location.lineno + 1).to_i step_tp nil, [:line, :return] do |tp| if tp.event == :line - next true if file && tp.path.end_with?(file) - next true if tp.lineno >= line + next false if no_loc && depth < DEBUGGER__.frame_depth - 3 + next false unless tp.path.end_with?(file) + next false unless tp.lineno >= line + true else - next true if depth >= DEBUGGER__.frame_depth - 3 && - caller_locations(2, 1).first.label == target_location_label - # TODO: imcomplete condition + true if depth >= DEBUGGER__.frame_depth - 3 && + caller_locations(2, 1).first.label == target_location_label + # TODO: imcomplete condition end end else @@ -934,11 +947,11 @@ def wait_next_action_ step_tp nil, [:call, :c_call, :return] do |tp| case tp.event when :call, :c_call - next true if pat === tp.callee_id.to_s + true if pat === tp.callee_id.to_s else # :return, :b_return - next true if depth >= DEBUGGER__.frame_depth - 3 && - caller_locations(2, 1).first.label == target_location_label - # TODO: imcomplete condition + true if depth >= DEBUGGER__.frame_depth - 3 && + caller_locations(2, 1).first.label == target_location_label + # TODO: imcomplete condition end end end @@ -1181,6 +1194,8 @@ def wait_next_action_ rescue Exception => e pp ["DEBUGGER Exception: #{__FILE__}:#{__LINE__}", e, e.backtrace] raise + ensure + @returning = false end def debug_event(ev, args) diff --git a/test/console/control_flow_commands_test.rb b/test/console/control_flow_commands_test.rb index c6dcea3c7..dd46301b8 100644 --- a/test/console/control_flow_commands_test.rb +++ b/test/console/control_flow_commands_test.rb @@ -82,6 +82,19 @@ def test_next_goes_to_the_next_line end end + def test_next_skips_method_in_a_same_line + debug_code program do + type 'b 7' + type 'c' + assert_line_num 7 + type 'n' + assert_line_num 8 + type 'n' + assert_line_num 17 + type 'n' + end + end + def test_next_with_number_goes_to_the_next_nth_line debug_code program do type 'b 15' @@ -123,6 +136,17 @@ def test_finish_leaves_the_current_frame type 'c' end end + + def test_finish_skips_method_in_a_same_line + debug_code program do + type 'b 7' + type 'c' + assert_line_num 7 + type 'fin' + assert_line_num 8 + type 'fin' + end + end end # @@ -254,7 +278,6 @@ def test_finish_4 end end - def program2 <<~RUBY 1| def foo x @@ -279,7 +302,7 @@ def test_finish_param type 'finish' assert_line_num 6 type 'next' - assert_line_num 2 + assert_line_num 9 type 'c' end end @@ -417,9 +440,13 @@ def program 4| end 5| c = 3 6| def foo - 7| x = 1 + 7| @x = 1 8| end - 9| foo + 9| def bar + 10| @y = 2 + 11| end + 12| foo; bar + 13| [@x, @y].inspect RUBY end @@ -447,11 +474,23 @@ def test_until_method debug_code program do type 'u foo' assert_line_num 7 - type 'u bar' + type 'u baz' assert_line_num 8 type 'c' end end + + def test_unit_method_in_the_same_line + debug_code program do + type 'u foo' + assert_line_num 7 + type 'u' + assert_line_num 8 + type 'u' + assert_line_num 13 + type 'c' + end + end end #