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



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

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

.interfaceObject



30
31
32
# File 'lib/byebug/context.rb', line 30

def interface
  @interface ||= LocalInterface.new
end

.processorObject



36
37
38
# File 'lib/byebug/context.rb', line 36

def processor
  @processor ||= CommandProcessor
end

Instance Method Details

#at_breakpoint(breakpoint) ⇒ Object

Breakpoint handler



111
112
113
# File 'lib/byebug/context.rb', line 111

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

#at_catchpoint(exception) ⇒ Object

Catchpoint handler



118
119
120
# File 'lib/byebug/context.rb', line 118

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

#at_endObject

End of class definition handler



134
135
136
137
138
# File 'lib/byebug/context.rb', line 134

def at_end
  return if ignored_file?(file)

  processor.at_end
end

#at_lineObject

Line handler



92
93
94
95
96
97
# File 'lib/byebug/context.rb', line 92

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

  processor.at_line
end

#at_return(return_value) ⇒ Object

Return handler



125
126
127
128
129
# File 'lib/byebug/context.rb', line 125

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

  processor.at_return(return_value)
end

#at_tracingObject

Tracing handler



102
103
104
105
106
# File 'lib/byebug/context.rb', line 102

def at_tracing
  return if ignored_file?(file)

  processor.at_tracing
end

#backtraceObject

#dead?Boolean

Returns:

  • (Boolean)

#frameObject

Reader for the current frame



44
45
46
# File 'lib/byebug/context.rb', line 44

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

#frame=(pos) ⇒ Object

Writer for the current frame



51
52
53
# File 'lib/byebug/context.rb', line 51

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

#frame_binding(frame_position = 0) ⇒ Binding

Returns frame’s binding.

Returns:

  • (Binding)


210
211
212
213
214
215
216
# File 'ext/byebug/context.c', line 210

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)


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

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)


238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'ext/byebug/context.c', line 238

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)


261
262
263
264
265
266
267
268
269
270
271
# File 'ext/byebug/context.c', line 261

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.



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

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)


297
298
299
300
301
302
303
# File 'ext/byebug/context.c', line 297

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



68
69
70
71
72
# File 'lib/byebug/context.rb', line 68

def full_location
  return location if virtual_file?(file)

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

#ignored?Boolean

Returns:

  • (Boolean)

#interruptObject



85
86
87
# File 'lib/byebug/context.rb', line 85

def interrupt
  step_into 1
end

#locationObject

Current file & line information



61
62
63
# File 'lib/byebug/context.rb', line 61

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

#resumenil

Resumes thread from the suspended mode.

Returns:

  • (nil)


327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'ext/byebug/context.c', line 327

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



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

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



397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'ext/byebug/context.c', line 397

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.



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'ext/byebug/context.c', line 437

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



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'ext/byebug/context.c', line 470

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



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'ext/byebug/context.c', line 361

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)


501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'ext/byebug/context.c', line 501

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)


551
552
553
554
555
556
557
558
559
# File 'ext/byebug/context.c', line 551

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)


529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'ext/byebug/context.c', line 529

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)


597
598
599
600
601
602
603
604
# File 'ext/byebug/context.c', line 597

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.



612
613
614
615
616
617
618
619
620
621
622
623
624
# File 'ext/byebug/context.c', line 612

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