class Byebug::Context

Mantains context information for the debugger and it's the main communication point between the library and the C-extension through the #at_breakpoint, #at_catchpoint, #at_tracing, #at_line and #at_return callbacks

Attributes

ignored_files[W]
interface[W]
processor[W]

Public Class Methods

ignored_files() click to toggle source

List of files byebug will ignore while debugging

# File lib/byebug/context.rb, line 24
def ignored_files
  @ignored_files ||=
    Byebug.mode == :standalone ? lib_files + [bin_file] : lib_files
end
interface() click to toggle source
# File lib/byebug/context.rb, line 31
def interface
  @interface ||= LocalInterface.new
end
processor() click to toggle source
# File lib/byebug/context.rb, line 37
def processor
  @processor ||= CommandProcessor
end

Public Instance Methods

at_breakpoint(breakpoint) click to toggle source

Breakpoint handler

# File lib/byebug/context.rb, line 112
def at_breakpoint(breakpoint)
  processor.at_breakpoint(breakpoint)
end
at_catchpoint(exception) click to toggle source

Catchpoint handler

# File lib/byebug/context.rb, line 119
def at_catchpoint(exception)
  processor.at_catchpoint(exception)
end
at_end() click to toggle source

End of class definition handler

# File lib/byebug/context.rb, line 135
def at_end
  return if ignored_file?(file)

  processor.at_end
end
at_line() click to toggle source

Line handler

# File lib/byebug/context.rb, line 93
def at_line
  self.frame = 0
  return if ignored_file?(file)

  processor.at_line
end
at_return(return_value) click to toggle source

Return handler

# File lib/byebug/context.rb, line 126
def at_return(return_value)
  return if ignored_file?(file)

  processor.at_return(return_value)
end
at_tracing() click to toggle source

Tracing handler

# File lib/byebug/context.rb, line 103
def at_tracing
  return if ignored_file?(file)

  processor.at_tracing
end
backtrace() click to toggle source
inline VALUE
Context_backtrace(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  return dc_backtrace(context);
}
dead?() click to toggle source
inline VALUE
Context_dead(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_DEAD) ? Qtrue : Qfalse;
}
frame() click to toggle source

Reader for the current frame

# File lib/byebug/context.rb, line 45
def frame
  @frame ||= Frame.new(self, 0)
end
frame=(pos) click to toggle source

Writer for the current frame

# File lib/byebug/context.rb, line 52
def frame=(pos)
  @frame = Frame.new(self, pos)
end
frame_binding(frame_position = 0) → binding click to toggle source

Returns frame's binding.

static VALUE
Context_frame_binding(int argc, VALUE *argv, VALUE self)
{
  FRAME_SETUP;

  return dc_frame_binding(context, frame_n);
}
frame_class(frame_position = 0) → class click to toggle source

Returns frame's defined class.

static VALUE
Context_frame_class(int argc, VALUE *argv, VALUE self)
{
  FRAME_SETUP;

  return dc_frame_class(context, frame_n);
}
frame_file(frame_position = 0) → string click to toggle source

Returns the name of the file in the frame.

static VALUE
Context_frame_file(int argc, VALUE *argv, VALUE self)
{
  VALUE loc, absolute_path;

  FRAME_SETUP;

  loc = dc_frame_location(context, frame_n);

  absolute_path = rb_funcall(loc, rb_intern("absolute_path"), 0);

  if (!NIL_P(absolute_path))
    return absolute_path;

  return rb_funcall(loc, rb_intern("path"), 0);
}
frame_line(frame_position = 0) → int click to toggle source

Returns the line number in the file in the frame.

static VALUE
Context_frame_line(int argc, VALUE *argv, VALUE self)
{
  VALUE loc;

  FRAME_SETUP;

  loc = dc_frame_location(context, frame_n);

  return rb_funcall(loc, rb_intern("lineno"), 0);
}
frame_method(frame_position = 0) → sym click to toggle source

Returns the sym of the method in the frame.

static VALUE
Context_frame_method(int argc, VALUE *argv, VALUE self)
{
  VALUE loc;

  FRAME_SETUP;

  loc = dc_frame_location(context, frame_n);

  return rb_str_intern(rb_funcall(loc, rb_intern("label"), 0));
}
frame_self(frame_postion = 0) → obj click to toggle source

Returns self object of the frame.

static VALUE
Context_frame_self(int argc, VALUE *argv, VALUE self)
{
  FRAME_SETUP;

  return dc_frame_self(context, frame_n);
}
full_location() click to toggle source

Current file, line and source code information

# File lib/byebug/context.rb, line 69
def full_location
  return location if virtual_file?(file)

  "#{location} #{get_line(file, line)}"
end
ignored?() click to toggle source
inline VALUE
Context_ignored(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
}
interrupt() click to toggle source
# File lib/byebug/context.rb, line 86
def interrupt
  step_into 1
end
location() click to toggle source

Current file & line information

# File lib/byebug/context.rb, line 62
def location
  "#{normalize(file)}:#{line}"
end
resume → nil click to toggle source

Resumes thread from the suspended mode.

static VALUE
Context_resume(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
    return Qnil;

  CTX_FL_UNSET(context, CTX_FL_SUSPEND);

  if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
    rb_thread_wakeup(context->thread);

  return Qnil;
}
stack_size() click to toggle source

Context's stack size

# File lib/byebug/context.rb, line 78
def stack_size
  return 0 unless backtrace

  backtrace.drop_while { |l| ignored_file?(l.first.path) }
           .take_while { |l| !ignored_file?(l.first.path) }
           .size
end
step_into(steps, frame = 0) click to toggle source

Stops the current context after a number of steps are made from frame frame (by default the newest one).

static VALUE
Context_step_into(int argc, VALUE *argv, VALUE self)
{
  VALUE steps, v_frame;
  int n_args, from_frame;
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (context->calced_stack_size == 0)
    rb_raise(rb_eRuntimeError, "No frames collected.");

  n_args = rb_scan_args(argc, argv, "11", &steps, &v_frame);

  if (FIX2INT(steps) <= 0)
    rb_raise(rb_eRuntimeError, "Steps argument must be positive.");

  from_frame = n_args == 1 ? 0 : FIX2INT(v_frame);

  if (from_frame < 0 || from_frame >= context->calced_stack_size)
    rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
             from_frame, context->calced_stack_size);
  else if (from_frame > 0)
    CTX_FL_SET(context, CTX_FL_IGNORE_STEPS);

  context->steps = FIX2INT(steps);
  context->dest_frame = context->calced_stack_size - from_frame;

  return steps;
}
step_out(n_frames = 1, force = false) click to toggle source

Stops after n_frames frames are finished. force parameter (if true) ensures that the execution will stop in the specified frame even when there are no more instructions to run. In that case, it will stop when the return event for that frame is triggered.

static VALUE
Context_step_out(int argc, VALUE *argv, VALUE self)
{
  int n_args, n_frames;
  VALUE v_frames, force;
  debug_context_t *context;

  n_args = rb_scan_args(argc, argv, "02", &v_frames, &force);
  n_frames = n_args == 0 ? 1 : FIX2INT(v_frames);

  Data_Get_Struct(self, debug_context_t, context);

  if (n_frames < 0 || n_frames > context->calced_stack_size)
    rb_raise(rb_eRuntimeError,
             "You want to finish %d frames, but stack size is only %d",
             n_frames, context->calced_stack_size);

  context->steps_out = n_frames;
  if (n_args == 2 && RTEST(force))
    CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
  else
    CTX_FL_UNSET(context, CTX_FL_STOP_ON_RET);

  return Qnil;
}
step_over(lines, frame = 0) click to toggle source

Steps over lines lines in frame frame (by default the newest one) or higher (if frame frame finishes).

static VALUE
Context_step_over(int argc, VALUE *argv, VALUE self)
{
  int n_args, frame;
  VALUE lines, v_frame;
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (context->calced_stack_size == 0)
    rb_raise(rb_eRuntimeError, "No frames collected.");

  n_args = rb_scan_args(argc, argv, "11", &lines, &v_frame);
  frame = n_args == 1 ? 0 : FIX2INT(v_frame);

  if (frame < 0 || frame >= context->calced_stack_size)
    rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
             frame, context->calced_stack_size);

  context->lines = FIX2INT(lines);
  context->dest_frame = context->calced_stack_size - frame;

  return Qnil;
}
stop_reason() click to toggle source
static VALUE
Context_stop_reason(VALUE self)
{
  debug_context_t *context;
  const char *symbol;

  Data_Get_Struct(self, debug_context_t, context);

  if (CTX_FL_TEST(context, CTX_FL_DEAD))
    symbol = "post-mortem";
  else
    switch (context->stop_reason)
    {
      case CTX_STOP_STEP:
        symbol = "step";
        break;
      case CTX_STOP_BREAKPOINT:
        symbol = "breakpoint";
        break;
      case CTX_STOP_CATCHPOINT:
        symbol = "catchpoint";
        break;
      case CTX_STOP_NONE:
      default:
        symbol = "none";
    }
  return ID2SYM(rb_intern(symbol));
}
suspend → nil click to toggle source

Suspends the thread when it is running.

static VALUE
Context_suspend(VALUE self)
{
  VALUE status;
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  status = rb_funcall(context->thread, rb_intern("status"), 0);

  if (rb_str_cmp(status, rb_str_new2("run")) == 0)
    CTX_FL_SET(context, CTX_FL_WAS_RUNNING);
  else if (rb_str_cmp(status, rb_str_new2("sleep")) == 0)
    CTX_FL_UNSET(context, CTX_FL_WAS_RUNNING);
  else
    return Qnil;

  CTX_FL_SET(context, CTX_FL_SUSPEND);

  return Qnil;
}
suspended? → bool click to toggle source

Returns true if the thread is suspended by debugger.

static VALUE
Context_is_suspended(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  return CTX_FL_TEST(context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
}
switch → nil click to toggle source

Switches execution to this context.

static VALUE
Context_switch(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  next_thread = context->thread;

  context->steps = 1;
  context->steps_out = 0;
  CTX_FL_SET(context, CTX_FL_STOP_ON_RET);

  return Qnil;
}
thnum() click to toggle source
inline VALUE
Context_thnum(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return INT2FIX(context->thnum);
}
thread() click to toggle source
inline VALUE
Context_thread(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return context->thread;
}
tracing → bool click to toggle source

Returns the tracing flag for the current context.

static VALUE
Context_tracing(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_TRACING) ? Qtrue : Qfalse;
}
tracing = bool click to toggle source

Controls the tracing for this context.

static VALUE
Context_set_tracing(VALUE self, VALUE value)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (RTEST(value))
    CTX_FL_SET(context, CTX_FL_TRACING);
  else
    CTX_FL_UNSET(context, CTX_FL_TRACING);
  return value;
}

Private Instance Methods

ignored_file?(path) click to toggle source

Tells whether a file is ignored by the debugger.

@param path [String] filename to be checked.

# File lib/byebug/context.rb, line 152
def ignored_file?(path)
  self.class.ignored_files.include?(path)
end
processor() click to toggle source
# File lib/byebug/context.rb, line 143
def processor
  @processor ||= self.class.processor.new(self, self.class.interface)
end