byebug 2.7.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -6
- data/.travis.yml +1 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile +9 -0
- data/README.md +35 -32
- data/Rakefile +1 -3
- data/byebug.gemspec +0 -6
- data/ext/byebug/byebug.c +64 -51
- data/ext/byebug/byebug.h +12 -13
- data/ext/byebug/context.c +28 -43
- data/ext/byebug/extconf.rb +6 -6
- data/lib/byebug.rb +34 -38
- data/lib/byebug/command.rb +4 -2
- data/lib/byebug/commands/continue.rb +0 -1
- data/lib/byebug/commands/control.rb +0 -1
- data/lib/byebug/commands/edit.rb +1 -1
- data/lib/byebug/commands/finish.rb +10 -16
- data/lib/byebug/commands/help.rb +1 -1
- data/lib/byebug/commands/kill.rb +1 -1
- data/lib/byebug/commands/quit.rb +1 -1
- data/lib/byebug/commands/repl.rb +3 -3
- data/lib/byebug/commands/set.rb +24 -39
- data/lib/byebug/commands/show.rb +39 -112
- data/lib/byebug/commands/stepping.rb +0 -2
- data/lib/byebug/commands/threads.rb +0 -5
- data/lib/byebug/commands/trace.rb +1 -1
- data/lib/byebug/commands/variables.rb +1 -1
- data/lib/byebug/context.rb +8 -12
- data/lib/byebug/helper.rb +1 -1
- data/lib/byebug/history.rb +46 -0
- data/lib/byebug/interface.rb +5 -5
- data/lib/byebug/interfaces/local_interface.rb +11 -62
- data/lib/byebug/interfaces/remote_interface.rb +6 -22
- data/lib/byebug/interfaces/script_interface.rb +2 -17
- data/lib/byebug/processor.rb +4 -4
- data/lib/byebug/{command_processor.rb → processors/command_processor.rb} +7 -14
- data/lib/byebug/{control_command_processor.rb → processors/control_command_processor.rb} +3 -7
- data/lib/byebug/version.rb +1 -1
- data/test/edit_test.rb +6 -6
- data/test/examples/breakpoint_deep.rb +1 -1
- data/test/finish_test.rb +6 -6
- data/test/help_test.rb +1 -1
- data/test/info_test.rb +0 -1
- data/test/kill_test.rb +2 -2
- data/test/post_mortem_test.rb +35 -219
- data/test/quit_test.rb +2 -2
- data/test/restart_test.rb +12 -33
- data/test/set_test.rb +80 -107
- data/test/show_test.rb +42 -77
- data/test/stepping_test.rb +1 -1
- data/test/support/test_dsl.rb +4 -25
- data/test/support/test_interface.rb +40 -48
- data/test/test_helper.rb +1 -3
- data/test/timeout_test.rb +9 -0
- metadata +8 -75
data/ext/byebug/context.c
CHANGED
@@ -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->
|
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("
|
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,
|
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,
|
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
|
-
|
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
|
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
|
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 (
|
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->
|
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
|
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 ,
|
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);
|
data/ext/byebug/extconf.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
|
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(
|
16
|
+
dir_config('ruby')
|
17
17
|
create_makefile('byebug/byebug')
|
data/lib/byebug.rb
CHANGED
@@ -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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
# :
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
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
|
-
|
117
|
-
|
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
|
-
|
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
|
169
|
-
|
170
|
-
|
171
|
-
|
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(
|
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
|
189
|
-
# occur. Before entering byebug
|
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(
|
190
|
+
def byebug(steps_out = 1, before = true)
|
192
191
|
Byebug.start
|
193
192
|
Byebug.run_init_script(StringIO.new)
|
194
|
-
|
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
|
data/lib/byebug/command.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'columnize'
|
2
2
|
require 'forwardable'
|
3
|
-
|
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
|
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
|
data/lib/byebug/commands/edit.rb
CHANGED
@@ -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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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][
|
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
|
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
|
data/lib/byebug/commands/help.rb
CHANGED
@@ -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]}\".
|
24
|
+
return errmsg "Undefined command: \"#{args[0]}\". Try \"help\".\n" if
|
25
25
|
args[0]
|
26
26
|
end
|
27
27
|
end
|
data/lib/byebug/commands/kill.rb
CHANGED
data/lib/byebug/commands/quit.rb
CHANGED
data/lib/byebug/commands/repl.rb
CHANGED
@@ -50,12 +50,12 @@ end
|
|
50
50
|
module Byebug
|
51
51
|
|
52
52
|
# Implements byebug's "irb" command.
|
53
|
-
class
|
53
|
+
class IrbCommand < Command
|
54
54
|
register_setting_get(:autoirb) do
|
55
|
-
|
55
|
+
IrbCommand.always_run
|
56
56
|
end
|
57
57
|
register_setting_set(:autoirb) do |value|
|
58
|
-
|
58
|
+
IrbCommand.always_run = value
|
59
59
|
end
|
60
60
|
|
61
61
|
def regexp
|