In Files

  • debug-1.4.0/lib/debug/breakpoint.rb

DEBUGGER__::LineBreakpoint

Constants

NearestISeq

Attributes

iseq[R]
line[R]
path[R]

Public Class Methods

new(path, line, cond: nil, oneshot: false, hook_call: true, command: nil) click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 129
def initialize path, line, cond: nil, oneshot: false, hook_call: true, command: nil
  @path = path
  @line = line
  @cond = cond
  @oneshot = oneshot
  @hook_call = hook_call
  @command = command
  @pending = false

  @iseq = nil
  @type = nil

  @key = [@path, @line].freeze

  super()

  try_activate
  @pending = !@iseq
end
            

Public Instance Methods

activate(iseq, event, line) click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 175
def activate iseq, event, line
  @iseq = iseq
  @type = event
  @line = line
  @path = iseq.absolute_path

  @key = [@path, @line].freeze
  SESSION.rehash_bps
  setup
  enable

  if @pending && !@oneshot
    DEBUGGER__.warn "#{self} is activated."
  end
end
            
activate_exact(iseq, events, line) click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 191
def activate_exact iseq, events, line
  case
  when events.include?(:RUBY_EVENT_CALL)
    # "def foo" line set bp on the beginning of method foo
    activate(iseq, :call, line)
  when events.include?(:RUBY_EVENT_LINE)
    activate(iseq, :line, line)
  when events.include?(:RUBY_EVENT_RETURN)
    activate(iseq, :return, line)
  when events.include?(:RUBY_EVENT_B_RETURN)
    activate(iseq, :b_return, line)
  when events.include?(:RUBY_EVENT_END)
    activate(iseq, :end, line)
  else
    # not actiavated
  end
end
            
duplicable?() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 209
def duplicable?
  @oneshot
end
            
enable() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 161
def enable
  return unless @iseq

  if @type == :line
    @tp.enable(target: @iseq, target_line: @line)
  else
    @tp.enable(target: @iseq)
  end

rescue ArgumentError
  puts @iseq.disasm # for debug
  raise
end
            
inspect() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 267
def inspect
  "<#{self.class.name} #{self.to_s}>"
end
            
setup() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 149
def setup
  return unless @type

  @tp = TracePoint.new(@type) do |tp|
    if @cond
      next unless safe_eval tp.binding, @cond
    end
    delete if @oneshot
    suspend
  end
end
            
to_s() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 257
def to_s
  oneshot = @oneshot ? " (oneshot)" : ""

  if @iseq
    "#{generate_label("Line")} #{@path}:#{@line} (#{@type})#{oneshot}" + super
  else
    "#{generate_label("Line (pending)")} #{@path}:#{@line}#{oneshot}" + super
  end
end
            
try_activate() click to toggle source
 
               # File debug-1.4.0/lib/debug/breakpoint.rb, line 215
def try_activate
  nearest = nil # NearestISeq

  ObjectSpace.each_iseq{|iseq|
    if (iseq.absolute_path || iseq.path) == self.path &&
        iseq.first_lineno <= self.line &&
        iseq.type != :ensure # ensure iseq is copied (duplicated)

      iseq.traceable_lines_norec(line_events = {})
      lines = line_events.keys.sort

      if !lines.empty? && lines.last >= line
        nline = lines.bsearch{|l| line <= l}
        events = line_events[nline]

        next if events == [:RUBY_EVENT_B_CALL]

        if @hook_call &&
           events.include?(:RUBY_EVENT_CALL) &&
           self.line == iseq.first_lineno
          nline = iseq.first_lineno
        end

        if !nearest || ((line - nline).abs < (line - nearest.line).abs)
          nearest = NearestISeq.new(iseq, nline, events)
        else
          if @hook_call && nearest.iseq.first_lineno <= iseq.first_lineno
            if (nearest.line > line && !nearest.events.include?(:RUBY_EVENT_CALL)) ||
               (events.include?(:RUBY_EVENT_CALL))
              nearest = NearestISeq.new(iseq, nline, events)
            end
          end
        end
      end
    end
  }

  if nearest
    activate_exact nearest.iseq, nearest.events, nearest.line
  end
end