Class: Byebug::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/byebug/context.rb,
ext/byebug/context.c

Overview

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.ignored(path) ⇒ Object



22
23
24
# File 'lib/byebug/context.rb', line 22

def ignored(path)
  IGNORED_FILES.include?(path)
end

.stack_size(byebug_frames = false) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/byebug/context.rb', line 9

def stack_size(byebug_frames = false)
  backtrace = Thread.current.backtrace_locations(0)
  return 0 unless backtrace

  unless byebug_frames
    backtrace = backtrace.drop_while { |l| !ignored(l.path) }
                         .drop_while { |l|  ignored(l.path) }
                         .take_while { |l| !ignored(l.path) }
  end

  backtrace.size
end

Instance Method Details

#at_breakpoint(brkpnt) ⇒ Object



67
68
69
# File 'lib/byebug/context.rb', line 67

def at_breakpoint(brkpnt)
  handler.at_breakpoint(self, brkpnt)
end

#at_catchpoint(excpt) ⇒ Object



71
72
73
# File 'lib/byebug/context.rb', line 71

def at_catchpoint(excpt)
  handler.at_catchpoint(self, excpt)
end

#at_line(file, line) ⇒ Object



79
80
81
# File 'lib/byebug/context.rb', line 79

def at_line(file, line)
  handler.at_line(self, file, line) unless IGNORED_FILES.include?(file)
end

#at_return(file, line) ⇒ Object



83
84
85
# File 'lib/byebug/context.rb', line 83

def at_return(file, line)
  handler.at_return(self, file, line)
end

#at_tracing(file, line) ⇒ Object



75
76
77
# File 'lib/byebug/context.rb', line 75

def at_tracing(file, line)
  handler.at_tracing(self, file, line)
end

#c_frame_args(frame_no) ⇒ Object



37
38
39
40
41
# File 'lib/byebug/context.rb', line 37

def c_frame_args(frame_no)
  myself = frame_self frame_no
  return [] unless myself.to_s != 'main'
  myself.send(:method, frame_method(frame_no)).parameters
end

#calced_stack_sizeObject

#dead?Boolean

Returns:

  • (Boolean)

#frame_args(frame_no = 0) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/byebug/context.rb', line 54

def frame_args(frame_no = 0)
  bind = frame_binding frame_no
  if bind.nil?
    c_frame_args frame_no
  else
    ruby_frame_args bind
  end
end

#frame_binding(frame_position = 0) ⇒ Binding

Returns frame’s binding.

Returns:

  • (Binding)


201
202
203
204
205
206
207
# File 'ext/byebug/context.c', line 201

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) ⇒ Binding

Returns frame’s defined class.

Returns:

  • (Binding)


215
216
217
218
219
220
221
# File 'ext/byebug/context.c', line 215

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

Returns the name of the file in the frame.

Returns:

  • (String)


229
230
231
232
233
234
235
236
237
238
239
# File 'ext/byebug/context.c', line 229

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

  FRAME_SETUP

  loc = dc_frame_location(context, frame_n);

  return rb_funcall(loc, rb_intern("path"), 0);
}

#frame_line(frame_position) ⇒ Integer

Returns the line number in the file.

Returns:

  • (Integer)


247
248
249
250
251
252
253
254
255
256
257
# File 'ext/byebug/context.c', line 247

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_locals(frame_no = 0) ⇒ Object



32
33
34
35
# File 'lib/byebug/context.rb', line 32

def frame_locals(frame_no = 0)
  bind = frame_binding frame_no
  eval 'local_variables.inject({}){|h, v| h[v] = eval(v.to_s); h}', bind
end

#frame_method(frame_position = 0) ⇒ Object

Returns the sym of the called method.



265
266
267
268
269
270
271
272
273
274
275
# File 'ext/byebug/context.c', line 265

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) ⇒ Object

Returns self object of the frame.

Returns:

  • (Object)


283
284
285
286
287
288
289
# File 'ext/byebug/context.c', line 283

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

  return dc_frame_self(context, frame_n);
}

#handlerObject



63
64
65
# File 'lib/byebug/context.rb', line 63

def handler
  Byebug.handler || fail('No interface loaded')
end

#ignored?Boolean

Returns:

  • (Boolean)

#interruptObject



28
29
30
# File 'lib/byebug/context.rb', line 28

def interrupt
  step_into 1
end

#resumenil

Resumes thread from the suspended mode.

Returns:

  • (nil)


323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'ext/byebug/context.c', line 323

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))
      rb_raise(rb_eRuntimeError, "Thread is not suspended.");

    context_resume_0(context);

    return Qnil;
}

#ruby_frame_args(bind) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/byebug/context.rb', line 43

def ruby_frame_args(bind)
  return [] unless eval '__method__', bind
  begin
    eval 'self.method(__method__).parameters', bind
  rescue NameError => e
    puts "WARNING: Got exception #{e.class}: \"#{e.message}\" " \
         'while retreving parameters from frame'
    return []
  end
end

#step_into(steps, force = false) ⇒ Object

Stops the current context after a number of steps are made. force parameter (if true) ensures that the cursor moves away from the current line.



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'ext/byebug/context.c', line 392

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

  rb_scan_args(argc, argv, "11", &steps, &force);
  if (FIX2INT(steps) < 0)
    rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");

  Data_Get_Struct(self, debug_context_t, context);
  context->steps = FIX2INT(steps);

  if (RTEST(force))
    CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
  else
    CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);

  return steps;
}

#step_out(n_frames = 1, force = false) ⇒ Object

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.



422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'ext/byebug/context.c', line 422

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 wan't 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, force = false) ⇒ Object

Steps over lines lines. Make step over operation on frame, by default the newest frame. force parameter (if true) ensures that the cursor moves away from the current line.



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# File 'ext/byebug/context.c', line 457

static VALUE
Context_step_over(int argc, VALUE *argv, VALUE self)
{
  int n_args, frame;
  VALUE lines, v_frame, force;
  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, "12", &lines, &v_frame, &force);
  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;

  if (n_args == 3 && RTEST(force))
    CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
  else
    CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);

  return Qnil;
}

#stop_reasonObject



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'ext/byebug/context.c', line 356

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));
}

#suspendnil

Suspends the thread when it is running.

Returns:

  • (nil)


509
510
511
512
513
514
515
516
517
518
519
520
# File 'ext/byebug/context.c', line 509

static VALUE
Context_suspend(VALUE self)
{
  debug_context_t *context;
  Data_Get_Struct(self, debug_context_t, context);

  if (CTX_FL_TEST(context, CTX_FL_SUSPEND))
    rb_raise(rb_eRuntimeError, "Already suspended.");

  context_suspend_0(context);
  return Qnil;
}

#suspended?Boolean

Returns true if the thread is suspended by debugger.

Returns:

  • (Boolean)


528
529
530
531
532
533
534
535
# File 'ext/byebug/context.c', line 528

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;
}

#thnumObject

#threadObject

#tracingBoolean

Returns the tracing flag for the current context.

Returns:

  • (Boolean)


570
571
572
573
574
575
576
577
# File 'ext/byebug/context.c', line 570

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) ⇒ Object

Controls the tracing for this context.



585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'ext/byebug/context.c', line 585

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;
}