class DEBUGGER__::MethodBreakpoint
def enable
def enable try_enable end
def eval_class_name
def eval_class_name return @klass if @klass @klass = @klass_eval_binding.eval(@sig_klass_name) @klass_eval_binding = nil @klass end
def initialize b, klass_name, op, method_name, cond: nil, command: nil, path: nil
def initialize b, klass_name, op, method_name, cond: nil, command: nil, path: nil @sig_klass_name = klass_name @sig_op = op @sig_method_name = method_name @klass_eval_binding = b @override_method = false @klass = nil @method = nil @cond_class = nil @key = "#{klass_name}#{op}#{method_name}".freeze super(cond, command, path, do_enable: false) end
def override klass
def override klass sig_method_name = @sig_method_name klass.prepend Module.new{ define_method(sig_method_name) do |*args, &block| super(*args, &block) end } end
def override klass
def override klass sig_method_name = @sig_method_name klass.prepend Module.new{ define_method(sig_method_name) do |*args, **kw, &block| super(*args, **kw, &block) end } end
def search_method
def search_method case @sig_op when '.' @method = @klass.method(@sig_method_name) when '#' @method = @klass.instance_method(@sig_method_name) else raise "Unknown op: #{@sig_op}" end end
def setup
def setup @tp = TracePoint.new(:call){|tp| next if !safe_eval(tp.binding, @cond) if @cond next if @cond_class && !tp.self.kind_of?(@cond_class) caller_location = caller_locations(2, 1).first.to_s next if skip_path?(caller_location) suspend } end
def sig
def sig @key end
def to_s
def to_s if @method loc = @method.source_location || [] "#{generate_label("Method")} #{sig} at #{loc.join(':')}" else "#{generate_label("Method (pending)")} #{sig}" end + super end
def try_enable added: false
def try_enable added: false eval_class_name search_method begin retried = false @tp.enable(target: @method) DEBUGGER__.info "#{self} is activated." if added if @sig_op == '#' @cond_class = @klass if @method.owner != @klass else # '.' begin @cond_class = @klass.singleton_class if @method.owner != @klass.singleton_class rescue TypeError end end rescue ArgumentError raise if retried retried = true # maybe C method case @sig_op when '.' begin override @klass.singleton_class rescue TypeError override @klass.class end when '#' override @klass end # re-collect the method object after the above patch search_method @override_method = true if @method retry end rescue Exception raise unless added end