Class: Byebug::Context

Inherits:
Object
  • Object
show all
Extended by:
Helpers::PathHelper, Forwardable
Includes:
Helpers::FileHelper
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 Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::PathHelper

all_files, bin_file, gem_files, lib_files, root_path, test_files

Methods included from Helpers::FileHelper

#get_line, #get_lines, #n_lines, #normalize, #shortpath, #virtual_file?

Class Attribute Details

.ignored_filesObject

List of files byebug will ignore while debugging



25
26
27
28
# File 'lib/byebug/context.rb', line 25

def ignored_files
  @ignored_files ||=
    Byebug.mode == :standalone ? lib_files + [bin_file] : lib_files
end

.interfaceObject



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

def interface
  @interface ||= LocalInterface.new
end

.processorObject



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

def processor
  @processor ||= CommandProcessor
end

Instance Method Details

#at_breakpoint(breakpoint) ⇒ Object

Breakpoint handler



113
114
115
# File 'lib/byebug/context.rb', line 113

def at_breakpoint(breakpoint)
  processor.at_breakpoint(breakpoint)
end

#at_catchpoint(exception) ⇒ Object

Catchpoint handler



120
121
122
# File 'lib/byebug/context.rb', line 120

def at_catchpoint(exception)
  processor.at_catchpoint(exception)
end

#at_endObject

End of class definition handler



136
137
138
139
140
# File 'lib/byebug/context.rb', line 136

def at_end
  return if ignored_file?(file)

  processor.at_end
end

#at_lineObject

Line handler



94
95
96
97
98
99
# File 'lib/byebug/context.rb', line 94

def at_line
  self.frame = 0
  return if ignored_file?(file)

  processor.at_line
end

#at_return(return_value) ⇒ Object

Return handler



127
128
129
130
131
# File 'lib/byebug/context.rb', line 127

def at_return(return_value)
  return if ignored_file?(file)

  processor.at_return(return_value)
end

#at_tracingObject

Tracing handler



104
105
106
107
108
# File 'lib/byebug/context.rb', line 104

def at_tracing
  return if ignored_file?(file)

  processor.at_tracing
end

#backtraceObject

#dead?Boolean

Returns:

  • (Boolean)

#frameObject

Reader for the current frame



46
47
48
# File 'lib/byebug/context.rb', line 46

def frame
  @frame ||= Frame.new(self, 0)
end

#frame=(pos) ⇒ Object

Writer for the current frame



53
54
55
# File 'lib/byebug/context.rb', line 53

def frame=(pos)
  @frame = Frame.new(self, pos)
end

#frame_binding(frame_position = 0) ⇒ Binding

Returns frame’s binding.

Returns:

  • (Binding)


223
224
225
226
227
228
229
# File 'ext/byebug/context.c', line 223

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

Returns frame’s defined class.

Returns:

  • (Class)


237
238
239
240
241
242
243
# File 'ext/byebug/context.c', line 237

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)


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'ext/byebug/context.c', line 251

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

Returns the line number in the file in the frame.

Returns:

  • (Integer)


274
275
276
277
278
279
280
281
282
283
284
# File 'ext/byebug/context.c', line 274

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

Returns the sym of the method in the frame.



292
293
294
295
296
297
298
299
300
301
302
# File 'ext/byebug/context.c', line 292

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)


310
311
312
313
314
315
316
# File 'ext/byebug/context.c', line 310

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

  return dc_frame_self(context, frame_n);
}

#full_locationObject

Current file, line and source code information



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

def full_location
  return location if virtual_file?(file)

  "#{location} #{get_line(file, line)}"
end

#ignored?Boolean

Returns:

  • (Boolean)

#interruptObject



87
88
89
# File 'lib/byebug/context.rb', line 87

def interrupt
  step_into 1
end

#locationObject

Current file & line information



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

def location
  "#{normalize(file)}:#{line}"
end

#resumenil

Resumes thread from the suspended mode.

Returns:

  • (nil)


340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'ext/byebug/context.c', line 340

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_sizeObject

Context’s stack size



79
80
81
82
83
84
85
# File 'lib/byebug/context.rb', line 79

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

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



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'ext/byebug/context.c', line 410

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



450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'ext/byebug/context.c', line 450

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

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



483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
# File 'ext/byebug/context.c', line 483

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_reasonObject



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'ext/byebug/context.c', line 374

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)


514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
# File 'ext/byebug/context.c', line 514

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?Boolean

Returns true if the thread is suspended by debugger.

Returns:

  • (Boolean)


564
565
566
567
568
569
570
571
572
# File 'ext/byebug/context.c', line 564

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

#switchnil

Switches execution to this context.

Returns:

  • (nil)


542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'ext/byebug/context.c', line 542

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

#thnumObject

#threadObject

#tracingBoolean

Returns the tracing flag for the current context.

Returns:

  • (Boolean)


610
611
612
613
614
615
616
617
# File 'ext/byebug/context.c', line 610

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.



625
626
627
628
629
630
631
632
633
634
635
636
637
# File 'ext/byebug/context.c', line 625

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