byebug 2.7.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -6
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +23 -0
  5. data/Gemfile +9 -0
  6. data/README.md +35 -32
  7. data/Rakefile +1 -3
  8. data/byebug.gemspec +0 -6
  9. data/ext/byebug/byebug.c +64 -51
  10. data/ext/byebug/byebug.h +12 -13
  11. data/ext/byebug/context.c +28 -43
  12. data/ext/byebug/extconf.rb +6 -6
  13. data/lib/byebug.rb +34 -38
  14. data/lib/byebug/command.rb +4 -2
  15. data/lib/byebug/commands/continue.rb +0 -1
  16. data/lib/byebug/commands/control.rb +0 -1
  17. data/lib/byebug/commands/edit.rb +1 -1
  18. data/lib/byebug/commands/finish.rb +10 -16
  19. data/lib/byebug/commands/help.rb +1 -1
  20. data/lib/byebug/commands/kill.rb +1 -1
  21. data/lib/byebug/commands/quit.rb +1 -1
  22. data/lib/byebug/commands/repl.rb +3 -3
  23. data/lib/byebug/commands/set.rb +24 -39
  24. data/lib/byebug/commands/show.rb +39 -112
  25. data/lib/byebug/commands/stepping.rb +0 -2
  26. data/lib/byebug/commands/threads.rb +0 -5
  27. data/lib/byebug/commands/trace.rb +1 -1
  28. data/lib/byebug/commands/variables.rb +1 -1
  29. data/lib/byebug/context.rb +8 -12
  30. data/lib/byebug/helper.rb +1 -1
  31. data/lib/byebug/history.rb +46 -0
  32. data/lib/byebug/interface.rb +5 -5
  33. data/lib/byebug/interfaces/local_interface.rb +11 -62
  34. data/lib/byebug/interfaces/remote_interface.rb +6 -22
  35. data/lib/byebug/interfaces/script_interface.rb +2 -17
  36. data/lib/byebug/processor.rb +4 -4
  37. data/lib/byebug/{command_processor.rb → processors/command_processor.rb} +7 -14
  38. data/lib/byebug/{control_command_processor.rb → processors/control_command_processor.rb} +3 -7
  39. data/lib/byebug/version.rb +1 -1
  40. data/test/edit_test.rb +6 -6
  41. data/test/examples/breakpoint_deep.rb +1 -1
  42. data/test/finish_test.rb +6 -6
  43. data/test/help_test.rb +1 -1
  44. data/test/info_test.rb +0 -1
  45. data/test/kill_test.rb +2 -2
  46. data/test/post_mortem_test.rb +35 -219
  47. data/test/quit_test.rb +2 -2
  48. data/test/restart_test.rb +12 -33
  49. data/test/set_test.rb +80 -107
  50. data/test/show_test.rb +42 -77
  51. data/test/stepping_test.rb +1 -1
  52. data/test/support/test_dsl.rb +4 -25
  53. data/test/support/test_interface.rb +40 -48
  54. data/test/test_helper.rb +1 -3
  55. data/test/timeout_test.rb +9 -0
  56. metadata +8 -75
@@ -12,8 +12,7 @@ reset_stepping_stop_points(debug_context_t *context)
12
12
  context->dest_frame = -1;
13
13
  context->lines = -1;
14
14
  context->steps = -1;
15
- context->after_frame = -1;
16
- context->before_frame = -1;
15
+ context->steps_out = -1;
17
16
  }
18
17
 
19
18
  /*
@@ -38,16 +37,10 @@ context_mark(void *data)
38
37
  rb_gc_mark(context->backtrace);
39
38
  }
40
39
 
41
- static void
42
- context_free(void *data)
43
- {
44
-
45
- }
46
-
47
40
  static int
48
41
  real_stack_size()
49
42
  {
50
- return FIX2INT(rb_funcall(cContext, rb_intern("real_stack_size"), 0));
43
+ return FIX2INT(rb_funcall(cContext, rb_intern("stack_size"), 1, Qtrue));
51
44
  }
52
45
 
53
46
  extern VALUE
@@ -67,7 +60,7 @@ context_create(VALUE thread)
67
60
 
68
61
  if (rb_obj_class(thread) == cDebugThread) CTX_FL_SET(context, CTX_FL_IGNORE);
69
62
 
70
- return Data_Wrap_Struct(cContext, context_mark, context_free, context);
63
+ return Data_Wrap_Struct(cContext, context_mark, 0, context);
71
64
  }
72
65
 
73
66
  extern VALUE
@@ -80,7 +73,7 @@ context_dup(debug_context_t *context)
80
73
  new_context->backtrace = context->backtrace;
81
74
  CTX_FL_SET(new_context, CTX_FL_DEAD);
82
75
 
83
- return Data_Wrap_Struct(cContext, context_mark, context_free, new_context);
76
+ return Data_Wrap_Struct(cContext, context_mark, 0, new_context);
84
77
  }
85
78
 
86
79
  static VALUE
@@ -225,7 +218,7 @@ Context_frame_binding(int argc, VALUE *argv, VALUE self)
225
218
  *
226
219
  * Returns frame's defined class.
227
220
  */
228
- static VALUE
221
+ static VALUE
229
222
  Context_frame_class(int argc, VALUE *argv, VALUE self)
230
223
  {
231
224
  FRAME_SETUP
@@ -405,8 +398,7 @@ Context_stop_reason(VALUE self)
405
398
  static VALUE
406
399
  Context_step_into(int argc, VALUE *argv, VALUE self)
407
400
  {
408
- VALUE steps;
409
- VALUE force;
401
+ VALUE steps, force;
410
402
  debug_context_t *context;
411
403
 
412
404
  rb_scan_args(argc, argv, "11", &steps, &force);
@@ -428,22 +420,35 @@ Context_step_into(int argc, VALUE *argv, VALUE self)
428
420
  * call-seq:
429
421
  * context.step_out(frame)
430
422
  *
431
- * Stops after frame number +frame+ is activated. Implements +finish+ and
432
- * +next+ commands.
423
+ * Stops after +n_frames+ frames are finished. Implements +finish+ and
424
+ * +next+ commands. +force+ parameter (if true) ensures that the cursor will
425
+ * stop in the specified frame even when there's no more instructions to run.
426
+ * In that case, it will stop when the return event for that frame is
427
+ * triggered.
433
428
  */
434
429
  static VALUE
435
- Context_step_out(VALUE self, VALUE frame)
430
+ Context_step_out(int argc, VALUE *argv, VALUE self)
436
431
  {
432
+ int n_args, n_frames;
433
+ VALUE v_frames, v_force;
437
434
  debug_context_t *context;
438
435
 
436
+ n_args = rb_scan_args(argc, argv, "02", &v_frames, &v_force);
437
+ n_frames = n_args == 0 ? 1 : FIX2INT(v_frames);
438
+ v_force = (n_args < 2) ? Qfalse : v_force;
439
+
439
440
  Data_Get_Struct(self, debug_context_t, context);
440
441
 
441
- if (FIX2INT(frame) < 0 || FIX2INT(frame) >= context->calced_stack_size)
442
+ if (n_frames < 0 || n_frames >= context->calced_stack_size)
442
443
  rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
443
444
 
444
- context->after_frame = context->calced_stack_size - FIX2INT(frame);
445
+ context->steps_out = n_frames;
446
+ if (RTEST(v_force))
447
+ CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
448
+ else
449
+ CTX_FL_UNSET(context, CTX_FL_STOP_ON_RET);
445
450
 
446
- return frame;
451
+ return Qnil;
447
452
  }
448
453
 
449
454
  /*
@@ -481,27 +486,6 @@ Context_step_over(int argc, VALUE *argv, VALUE self)
481
486
  return Qnil;
482
487
  }
483
488
 
484
- /*
485
- * call-seq:
486
- * context.stop_return(frame)
487
- *
488
- * Stops before frame number +frame+ is activated. Useful when you enter the
489
- * debugger after the last statement in a method.
490
- */
491
- static VALUE
492
- Context_stop_return(VALUE self, VALUE frame)
493
- {
494
- debug_context_t *context;
495
-
496
- Data_Get_Struct(self, debug_context_t, context);
497
- if (FIX2INT(frame) < 0 || FIX2INT(frame) >= context->calced_stack_size)
498
- rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
499
-
500
- context->before_frame = context->calced_stack_size - FIX2INT(frame);
501
-
502
- return frame;
503
- }
504
-
505
489
  static void
506
490
  context_suspend_0(debug_context_t *context)
507
491
  {
@@ -619,6 +603,8 @@ static VALUE
619
603
  DebugThread_inherited(VALUE klass)
620
604
  {
621
605
  rb_raise(rb_eRuntimeError, "Can't inherit Byebug::DebugThread class");
606
+
607
+ return Qnil;
622
608
  }
623
609
 
624
610
  /*
@@ -644,9 +630,8 @@ Init_context(VALUE mByebug)
644
630
  rb_define_method(cContext, "resume" , Context_resume , 0);
645
631
  rb_define_method(cContext, "calced_stack_size", Context_calced_stack_size, 0);
646
632
  rb_define_method(cContext, "step_into" , Context_step_into , -1);
647
- rb_define_method(cContext, "step_out" , Context_step_out , 1);
633
+ rb_define_method(cContext, "step_out" , Context_step_out , -1);
648
634
  rb_define_method(cContext, "step_over" , Context_step_over , -1);
649
- rb_define_method(cContext, "stop_return" , Context_stop_return , 1);
650
635
  rb_define_method(cContext, "stop_reason" , Context_stop_reason , 0);
651
636
  rb_define_method(cContext, "suspend" , Context_suspend , 0);
652
637
  rb_define_method(cContext, "suspended?" , Context_is_suspended , 0);
@@ -1,17 +1,17 @@
1
- require 'mkmf'
2
-
3
- RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
4
-
5
- if RUBY_VERSION < "2.0"
1
+ if RUBY_VERSION < '2.0'
6
2
  STDERR.print("Ruby version is too old\n")
7
3
  exit(1)
8
4
  end
9
5
 
6
+ require 'mkmf'
7
+
8
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
9
+
10
10
  if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
11
11
  $CFLAGS ||= ''
12
12
  $CFLAGS += ' -Wall -Werror -Wno-unused-parameter'
13
13
  $CFLAGS += ' -gdwarf-2 -g3 -O0' if ENV['debug']
14
14
  end
15
15
 
16
- dir_config("ruby")
16
+ dir_config('ruby')
17
17
  create_makefile('byebug/byebug')
@@ -1,9 +1,8 @@
1
1
  require 'byebug/byebug'
2
2
  require 'byebug/version'
3
3
  require 'byebug/context'
4
+ require 'byebug/interface'
4
5
  require 'byebug/processor'
5
- require 'byebug/command_processor'
6
- require 'byebug/control_command_processor'
7
6
  require 'byebug/remote'
8
7
  require 'stringio'
9
8
  require 'tracer'
@@ -15,24 +14,26 @@ module Byebug
15
14
  IGNORED_FILES = Dir.glob(File.expand_path('../**/*.rb', __FILE__))
16
15
 
17
16
  # Default options to Byebug.start
18
- DEFAULT_START_SETTINGS = {
19
- init: true, # Set $0 and save ARGV?
20
- post_mortem: false, # post-mortem debugging on uncaught exception?
21
- tracing: nil # Byebug.tracing? value. true/false resets
22
- } unless defined?(DEFAULT_START_SETTINGS)
17
+ unless defined?(DEFAULT_START_SETTINGS)
18
+ DEFAULT_START_SETTINGS = { post_mortem: false,
19
+ tracing: false,
20
+ save_history: true }
21
+ end
23
22
 
24
23
  # Configuration file used for startup commands. Default value is .byebugrc
25
24
  INITFILE = '.byebugrc' unless defined?(INITFILE)
26
25
 
26
+ # Original ARGV, command line and initial directory to make restarts possible
27
+ ARGV = ARGV.clone unless defined?(ARGV)
28
+ PROG_SCRIPT = $0 unless defined?(PROG_SCRIPT)
29
+ INITIAL_DIR = Dir.pwd unless defined?(INITIAL_DIR)
30
+
27
31
  class << self
28
32
 
29
33
  # processor modules provide +handler+ object
30
34
  attr_accessor :handler
31
35
  Byebug.handler = CommandProcessor.new
32
36
 
33
- attr_accessor :last_exception
34
- Byebug.last_exception = nil
35
-
36
37
  def source_reload
37
38
  Object.send(:remove_const, 'SCRIPT_LINES__') if
38
39
  Object.const_defined?('SCRIPT_LINES__')
@@ -102,25 +103,23 @@ module Byebug
102
103
  # many times as you called Byebug.start method.</i>
103
104
  #
104
105
  # +options+ is a hash used to set various debugging options.
105
- # :init - true if you want to save ARGV and some other variables to
106
- # make a byebug restart possible. Only the first time :init
107
- # is set to true the values will get set. Since ARGV is
108
- # saved, you should make sure it hasn't been changed before
109
- # the (first) call.
110
- # :post_mortem - true if you want to enter post-mortem debugging on an
111
- # uncaught exception. Once post-mortem debugging is set, it
112
- # can't be unset.
106
+ # :post_mortem - true if you want to enter post-mortem debugging on an
107
+ # uncaught exception, false otherwise. Default: false.
108
+ # :tracing - true if line tracing should be enabled, false otherwise.
109
+ # Default: false.
110
+ # :save_history - true if byebug's command history should be saved to a
111
+ # file on program termination so that it can be reloaded
112
+ # later.
113
113
  #
114
114
  def start(options={}, &block)
115
115
  options = Byebug::DEFAULT_START_SETTINGS.merge(options)
116
- if options[:init]
117
- Byebug.const_set('ARGV', ARGV.clone) unless defined? Byebug::ARGV
118
- Byebug.const_set('PROG_SCRIPT', $0) unless defined? Byebug::PROG_SCRIPT
119
- Byebug.const_set('INITIAL_DIR', Dir.pwd) unless defined? Byebug::INITIAL_DIR
120
- end
121
- Byebug.tracing = options[:tracing] unless options[:tracing].nil?
116
+ Byebug.tracing = options[:tracing]
117
+
122
118
  retval = Byebug._start(&block)
119
+
123
120
  post_mortem if options[:post_mortem]
121
+ at_exit { Byebug::History.save } if options[:save_history]
122
+
124
123
  return retval
125
124
  end
126
125
 
@@ -139,7 +138,7 @@ module Byebug
139
138
 
140
139
  home_script = File.expand_path(File.join(ENV['HOME'].to_s, INITFILE))
141
140
  if File.exist?(home_script) and cwd_script != home_script
142
- run_script(home_script, out)
141
+ run_script(home_script, out)
143
142
  end
144
143
  end
145
144
 
@@ -161,17 +160,17 @@ module Byebug
161
160
  #
162
161
  def post_mortem
163
162
  return if self.post_mortem?
164
- at_exit { handle_post_mortem($!) if post_mortem? }
165
163
  self.post_mortem = true
164
+ at_exit { handle_post_mortem if post_mortem? }
166
165
  end
167
166
 
168
- def handle_post_mortem(exp)
169
- return if !exp
170
- Byebug.last_exception = exp
171
- return if !exp.__bb_context || !exp.__bb_context.calced_stack_size
167
+ def handle_post_mortem
168
+ context = raised_exception.__bb_context
169
+ file = raised_exception.__bb_file
170
+ line = raised_exception.__bb_line
172
171
  orig_tracing = Byebug.tracing?
173
172
  Byebug.tracing = false
174
- handler.at_line(exp.__bb_context, exp.__bb_file, exp.__bb_line)
173
+ handler.at_line(context, file, line)
175
174
  ensure
176
175
  Byebug.tracing = orig_tracing
177
176
  end
@@ -185,16 +184,13 @@ end
185
184
 
186
185
  module Kernel
187
186
  #
188
- # Enters byebug after _steps_into_ line events and _steps_out_ return events
189
- # occur. Before entering byebug startup, the init script is read.
187
+ # Enters byebug right before (or right after if _before_ is false) return
188
+ # events occur. Before entering byebug the init script is read.
190
189
  #
191
- def byebug(steps_into = 1, steps_out = 2)
190
+ def byebug(steps_out = 1, before = true)
192
191
  Byebug.start
193
192
  Byebug.run_init_script(StringIO.new)
194
- if Byebug.current_context.calced_stack_size > 2
195
- Byebug.current_context.stop_return steps_out if steps_out >= 1
196
- end
197
- Byebug.current_context.step_into steps_into if steps_into >= 0
193
+ Byebug.current_context.step_out(steps_out, before)
198
194
  end
199
195
 
200
196
  alias_method :debugger, :byebug
@@ -1,6 +1,6 @@
1
1
  require 'columnize'
2
2
  require 'forwardable'
3
- require_relative 'helper'
3
+ require 'byebug/helper'
4
4
 
5
5
  module Byebug
6
6
 
@@ -23,7 +23,7 @@ module Byebug
23
23
  @commands ||= []
24
24
  end
25
25
 
26
- attr_accessor :allow_in_control, :unknown, :need_context
26
+ attr_accessor :allow_in_control, :unknown
27
27
  attr_writer :allow_in_post_mortem, :always_run
28
28
 
29
29
  def allow_in_post_mortem
@@ -143,6 +143,7 @@ module Byebug
143
143
  end
144
144
 
145
145
  # Register default settings
146
+ register_setting_var(:autosave, true)
146
147
  register_setting_var(:basename, false)
147
148
  register_setting_var(:callstyle, :long)
148
149
  register_setting_var(:testing, false)
@@ -217,6 +218,7 @@ module Byebug
217
218
  # :autolist - automatically calls 'list' command on breakpoint
218
219
  # :autoreload - makes 'list' command always display up-to-date source
219
220
  # code
221
+ # :autosave - automatic saving of command history on exit
220
222
  # :frame_class_names - displays method's class name when showing frame stack
221
223
  # :forcestep - stepping command always move to the new line
222
224
  # :fullpath - displays full paths when showing frame stack
@@ -3,7 +3,6 @@ module Byebug
3
3
  # Implements byebug "continue" command.
4
4
  class ContinueCommand < Command
5
5
  self.allow_in_post_mortem = true
6
- self.need_context = false
7
6
 
8
7
  def regexp
9
8
  /^\s* c(?:ont(?:inue)?)? (?:\s+(\S+))? \s*$/x
@@ -66,7 +66,6 @@ module Byebug
66
66
  class InterruptCommand < Command
67
67
  self.allow_in_control = true
68
68
  self.allow_in_post_mortem = false
69
- self.need_context = true
70
69
 
71
70
  def regexp
72
71
  /^\s*i(?:nterrupt)?\s*$/
@@ -1,6 +1,6 @@
1
1
  module Byebug
2
2
 
3
- class Edit < Command
3
+ class EditCommand < Command
4
4
  self.allow_in_control = true
5
5
 
6
6
  def regexp
@@ -3,21 +3,18 @@ module Byebug
3
3
  # Implements byebug's 'finish' command.
4
4
  class FinishCommand < Command
5
5
  self.allow_in_post_mortem = false
6
- self.need_context = true
7
6
 
8
7
  def regexp
9
8
  /^\s* fin(?:ish)? (?:\s+(\S+))? \s*$/x
10
9
  end
11
10
 
12
11
  def execute
13
- if not @match[1]
14
- frame_pos = @state.frame_pos
15
- else
16
- max_frame = Context.stack_size - @state.frame_pos
17
- frame_pos = get_int(@match[1], "finish", 0, max_frame-1, 0)
18
- return nil unless frame_pos
19
- end
20
- @state.context.step_out frame_pos
12
+ max_frames = Context.stack_size - @state.frame_pos
13
+ n_frames = get_int(@match[1], "finish", 0, max_frames - 1, 1)
14
+ return nil unless n_frames
15
+
16
+ force = n_frames == 0 ? true : false
17
+ @state.context.step_out(@state.frame_pos + n_frames, force)
21
18
  @state.frame_pos = 0
22
19
  @state.proceed
23
20
  end
@@ -28,14 +25,11 @@ module Byebug
28
25
  end
29
26
 
30
27
  def description
31
- %{fin[ish][ frame-number]\tExecute until selected stack frame returns.
32
-
33
- If no frame number is given, we run until the currently selected frame
34
- returns. The currently selected frame starts out the most-recent frame
35
- or 0 if no frame positioning (e.g "up", "down" or "frame") has been
36
- performed.
28
+ %{fin[ish][ n_frames]\tExecute until frame returns.
37
29
 
38
- If a frame number is given we run until that frame returns.}
30
+ If no number is given, we run until the current frame returns. If a
31
+ number of frames `n_frames` is given, then we run until `n_frames`
32
+ return from the current position.}
39
33
  end
40
34
  end
41
35
  end
@@ -21,7 +21,7 @@ module Byebug
21
21
  help.pop if help.last && help.last.empty?
22
22
  return print help.join("\n") + "\n"
23
23
  else
24
- return errmsg "Undefined command: \"#{args[0]}\". Try \"help\".\n" if
24
+ return errmsg "Undefined command: \"#{args[0]}\". Try \"help\".\n" if
25
25
  args[0]
26
26
  end
27
27
  end
@@ -16,7 +16,7 @@ module Byebug
16
16
  return false
17
17
  end
18
18
  if 'KILL' == signame
19
- @state.interface.finalize
19
+ @state.interface.close
20
20
  end
21
21
  else
22
22
  if not confirm("Really kill? (y/n) ")
@@ -10,7 +10,7 @@ module Byebug
10
10
 
11
11
  def execute
12
12
  if @match[1] or confirm("Really quit? (y/n) ")
13
- @state.interface.finalize
13
+ @state.interface.close
14
14
  exit! # exit -> exit!: No graceful way to stop...
15
15
  end
16
16
  end
@@ -50,12 +50,12 @@ end
50
50
  module Byebug
51
51
 
52
52
  # Implements byebug's "irb" command.
53
- class IRBCommand < Command
53
+ class IrbCommand < Command
54
54
  register_setting_get(:autoirb) do
55
- IRBCommand.always_run
55
+ IrbCommand.always_run
56
56
  end
57
57
  register_setting_set(:autoirb) do |value|
58
- IRBCommand.always_run = value
58
+ IrbCommand.always_run = value
59
59
  end
60
60
 
61
61
  def regexp