diff --git a/src/Debugger.jl b/src/Debugger.jl index f38fba6..706d36d 100644 --- a/src/Debugger.jl +++ b/src/Debugger.jl @@ -97,7 +97,12 @@ function _make_frame(mod, arg) frame === nothing && error("failed to enter the function, perhaps it is set to run in compiled mode") frame = JuliaInterpreter.maybe_step_through_kwprep!(frame) frame = JuliaInterpreter.maybe_step_through_wrapper!(frame) - JuliaInterpreter.maybe_next_call!(frame) + # Advance to the first call, but stop earlier if a breakpoint is set on + # one of the initial statements (#134) + JuliaInterpreter.maybe_next_until!(frame) do fr + JuliaInterpreter.shouldbreak(fr, fr.pc) || + JuliaInterpreter.is_call_or_return(JuliaInterpreter.pc_expr(fr)) + end frame end end diff --git a/src/repl.jl b/src/repl.jl index fe5ae51..7eb6bd7 100644 --- a/src/repl.jl +++ b/src/repl.jl @@ -155,7 +155,9 @@ function RunDebugger(frame, repl = nothing, terminal = nothing; initial_continue state.standard_keymap = keymaps panel.keymap_dict = LineEdit.keymap([repl_switch;state.standard_keymap]) - if initial_continue + # If a breakpoint is set on the statement we are already stopped at, `c` would + # step over it, so stay put and show the prompt instead (#134) + if initial_continue && !JuliaInterpreter.shouldbreak(state.frame, state.frame.pc) try execute_command(state, Val(:c), "c") catch err diff --git a/test/misc.jl b/test/misc.jl index 8c43676..6665006 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -225,6 +225,22 @@ execute_command(state, Val{:bp}(), """bp add lfdshfds""") @test !_iscall(:(identity() do; end)) end +# Issue #134: a breakpoint on one of the initial statements of a function should +# not be stepped over when entering the frame +@testset "breakpoint on first statement" begin + function f_bp_first(x) + y = x + 1 + return y * 2 + end + JuliaInterpreter.breakpoint(f_bp_first) + try + frame = @make_frame f_bp_first(1) + @test JuliaInterpreter.shouldbreak(frame, frame.pc) + finally + JuliaInterpreter.remove() + end +end + # Issue #394: backslash (latex) completions in the evaluation mode @testset "completions" begin f_completions(x) = x + 1 diff --git a/test/ui.jl b/test/ui.jl index e225ce7..e2b3fe5 100644 --- a/test/ui.jl +++ b/test/ui.jl @@ -140,12 +140,12 @@ end Vector{UInt8}(codeunits(actual_decorator))) end - function run_terminal_test(frame, commands, validation) + function run_terminal_test(frame, commands, validation; initial_continue=false) run_debugger = function (emuterm) repl = REPL.LineEditREPL(emuterm, true) repl.interface = REPL.setup_interface(repl) repl.specialdisplay = REPL.REPLDisplay(repl) - RunDebugger(frame, repl, emuterm) + RunDebugger(frame, repl, emuterm; initial_continue=initial_continue) end output_path = joinpath(@__DIR__, validation) if get(ENV, "DEBUGGER_UPDATE_UI_SNAPSHOTS", "false") == "true" @@ -195,6 +195,18 @@ end ["bt\n", "c\n"], "ui/big_repr_ui.multiout") + # Issue #134: `@run` should stop at a breakpoint on the first statement + # instead of continuing past it + JuliaInterpreter.breakpoint(mysum) + try + run_terminal_test(@make_frame(mysum([1,2,3])), + ["c\n"], + "ui/bp_first_statement.multiout"; + initial_continue=true) + finally + JuliaInterpreter.remove() + end + was_breaking_on_error = JuliaInterpreter.break_on_error[] Debugger.break_on(:error) try diff --git a/test/ui/bp_first_statement.multiout b/test/ui/bp_first_statement.multiout new file mode 100644 index 0000000..2cf409a --- /dev/null +++ b/test/ui/bp_first_statement.multiout @@ -0,0 +1,24 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++ +|In mysum(x) at ui.jl:94 +| 94 function mysum(x) +|> 95 s = 0 +| 96 for v in x +| 97 s += v +| 98 end +| 99 return s +| 100 end +| +|About to run: 0 +|1|debug> +-------------------------------------------------- +|AAAAAAAAAAAAAAAAAAAAAAA +|AAAAAAAAAAAAAAAAAAAAAAA +|BBBBBBAAAAAAAAA +|AAAAAAAAAAAAAAAAAAAA +|CCCCCCAAAAAAAAAAAAAA +|AAAAAAAAAAAAA +|AAAAAAAAAAAAAAAAAA +|AAAAAAAAA +| +|AAAAAAAAAAAAAAA +|DDDDDDDDD \ No newline at end of file