Skip to content

Commit

Permalink
remain breakpoints on reloaded files
Browse files Browse the repository at this point in the history
Breakpoints should be remained on reloaded files. To make sure
maintaining loaded file names.

fix #870
  • Loading branch information
ko1 committed Mar 25, 2023
1 parent f190b28 commit f00aa6d
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 37 deletions.
14 changes: 6 additions & 8 deletions lib/debug/breakpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,6 @@ def skip_path?(path)
def generate_label(name)
colorize(" BP - #{name} ", [:YELLOW, :BOLD, :REVERSE])
end

def pending_until_load?
false
end
end

if RUBY_VERSION.to_f <= 2.7
Expand Down Expand Up @@ -163,10 +159,6 @@ def initialize path, line, cond: nil, oneshot: false, hook_call: true, command:
@pending = !@iseq
end

def pending_until_load?
@pending
end

def setup
return unless @type

Expand Down Expand Up @@ -207,6 +199,8 @@ def activate iseq, event, line
if @pending && !@oneshot
DEBUGGER__.info "#{self} is activated."
end

@pending = false
end

def activate_exact iseq, events, line
Expand Down Expand Up @@ -299,6 +293,10 @@ def to_s
def inspect
"<#{self.class.name} #{self.to_s}>"
end

def path_is? path
DEBUGGER__.compare_path(@path, path)
end
end

class CatchBreakpoint < Breakpoint
Expand Down
1 change: 0 additions & 1 deletion lib/debug/server_dap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ def process
when 'setBreakpoints'
req_path = args.dig('source', 'path')
path = UI_DAP.local_to_remote_path(req_path)

if path
SESSION.clear_line_breakpoints path

Expand Down
47 changes: 21 additions & 26 deletions lib/debug/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,11 @@ def initialize
@commands = {}
@unsafe_context = false

has_keep_script_lines = RubyVM.respond_to? :keep_script_lines
@has_keep_script_lines = RubyVM.respond_to? :keep_script_lines

@tp_load_script = TracePoint.new(:script_compiled){|tp|
if !has_keep_script_lines || bps_pending_until_load?
eval_script = tp.eval_script unless has_keep_script_lines
ThreadClient.current.on_load tp.instruction_sequence, eval_script
end
eval_script = tp.eval_script unless @has_keep_script_lines
ThreadClient.current.on_load tp.instruction_sequence, eval_script
}
@tp_load_script.enable

Expand Down Expand Up @@ -1334,10 +1332,6 @@ def ask msg, default = 'Y'

# breakpoint management

def bps_pending_until_load?
@bps.any?{|key, bp| bp.pending_until_load?}
end

def iterate_bps
deleted_bps = []
i = 0
Expand Down Expand Up @@ -1513,7 +1507,7 @@ def clear_breakpoints(&condition)
def clear_line_breakpoints path
path = resolve_path(path)
clear_breakpoints do |k, bp|
bp.is_a?(LineBreakpoint) && DEBUGGER__.compare_path(k.first, path)
bp.is_a?(LineBreakpoint) && bp.path_is?(path)
end
rescue Errno::ENOENT
# just ignore
Expand Down Expand Up @@ -1737,25 +1731,26 @@ def on_load iseq, src
file_path, reloaded = @sr.add(iseq, src)
@ui.event :load, file_path, reloaded

pending_line_breakpoints = @bps.find_all do |key, bp|
LineBreakpoint === bp && !bp.iseq
end

pending_line_breakpoints.each do |_key, bp|
if DEBUGGER__.compare_path(bp.path, (iseq.absolute_path || iseq.path))
bp.try_activate iseq
end
end

if reloaded
@bps.find_all do |key, bp|
LineBreakpoint === bp && DEBUGGER__.compare_path(bp.path, file_path)
# check breakpoints
if file_path
@bps.find_all do |_key, bp|
LineBreakpoint === bp && bp.path_is?(file_path)
end.each do |_key, bp|
@bps.delete bp.key # to allow duplicate
if nbp = LineBreakpoint.copy(bp, iseq)
add_bp nbp
if !bp.iseq
bp.try_activate iseq
elsif reloaded
@bps.delete bp.key # to allow duplicate
if nbp = LineBreakpoint.copy(bp, iseq)
add_bp nbp
end
end
end
else # !file_path => file_path is not existing
@bps.find_all do |_key, bp|
LineBreakpoint === bp && !bp.iseq && DEBUGGER__.compare_path(bp.path, (iseq.absolute_path || iseq.path))
end.each do |_key, bp|
bp.try_activate iseq
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/debug/source_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def initialize
end

def add iseq, src
# do nothing
# only manage loaded file names
if (path = (iseq.absolute_path || iseq.path)) && File.exist?(path)
if @loaded_file_map.has_key? path
return path, true # reloaded
Expand Down
38 changes: 37 additions & 1 deletion test/console/break_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ def program path
RUBY
end

def test_break_on_realoded_file
def test_break_on_realoded_file_pending
with_extra_tempfile do |extra_file|
debug_code(program(extra_file.path)) do
type "break #{extra_file.path}:2 do: p :xyzzy"
Expand All @@ -837,6 +837,42 @@ def test_break_on_realoded_file
end
end
end

def test_break_on_reloaded_file
code = <<~'DEBUG_CODE'
1| require 'tempfile'
2| tf = Tempfile.new('debug_gem_test')
3| tf.puts(<<RUBY)
4| def foo
5| p 1
6| end
7| RUBY
8| tf.close
9| load tf.path
10| # p :loeaded
11| debugger do: "b #{tf.path}:2"
12| foo
13| tf.open
14| tf.seek 0
15| tf.puts(<<RUBY)
16| def foo
17| p 0
18| p 1
19| end
20| RUBY
21| tf.close
22| load tf.path
23| foo
DEBUG_CODE

debug_code code do
type 'c'
assert_line_num 2 # on tempfile
type 'c'
assert_line_num 2 # on tempfile
type 'c'
end
end
end

class BreakAtLineTest < ConsoleTestCase
Expand Down

0 comments on commit f00aa6d

Please sign in to comment.