byebug 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +1 -1
  4. data/bin/byebug +1 -2
  5. data/byebug.gemspec +1 -1
  6. data/ext/byebug/byebug.c +50 -35
  7. data/ext/byebug/context.c +99 -45
  8. data/lib/byebug.rb +5 -10
  9. data/lib/byebug/command.rb +20 -12
  10. data/lib/byebug/commands/breakpoints.rb +1 -1
  11. data/lib/byebug/commands/control.rb +14 -21
  12. data/lib/byebug/commands/display.rb +4 -4
  13. data/lib/byebug/commands/enable.rb +20 -19
  14. data/lib/byebug/commands/eval.rb +1 -1
  15. data/lib/byebug/commands/finish.rb +4 -5
  16. data/lib/byebug/commands/info.rb +118 -116
  17. data/lib/byebug/commands/list.rb +72 -48
  18. data/lib/byebug/commands/reload.rb +4 -3
  19. data/lib/byebug/commands/set.rb +7 -16
  20. data/lib/byebug/commands/show.rb +2 -2
  21. data/lib/byebug/commands/threads.rb +7 -6
  22. data/lib/byebug/context.rb +10 -2
  23. data/lib/byebug/helper.rb +3 -3
  24. data/lib/byebug/processor.rb +1 -1
  25. data/lib/byebug/version.rb +1 -1
  26. data/old_doc/byebug.texi +45 -51
  27. data/test/breakpoints_test.rb +180 -195
  28. data/test/display_test.rb +59 -53
  29. data/test/eval_test.rb +0 -2
  30. data/test/examples/info.rb +5 -5
  31. data/test/examples/info_threads.rb +1 -1
  32. data/test/finish_test.rb +16 -15
  33. data/test/info_test.rb +9 -10
  34. data/test/irb_test.rb +64 -65
  35. data/test/list_test.rb +76 -50
  36. data/test/method_test.rb +10 -5
  37. data/test/post_mortem_test.rb +27 -25
  38. data/test/reload_test.rb +31 -31
  39. data/test/restart_test.rb +106 -110
  40. data/test/show_test.rb +8 -16
  41. data/test/stepping_test.rb +4 -2
  42. data/test/support/test_dsl.rb +37 -76
  43. data/test/test_helper.rb +0 -1
  44. data/test/variables_test.rb +9 -12
  45. metadata +4 -4
@@ -22,7 +22,7 @@ module Byebug
22
22
  if expr
23
23
  if expr !~ /^\s*if\s+(.+)/
24
24
  if file or line
25
- errmsg "Expecting 'if' in breakpoint condition; got: #{expr}.\n"
25
+ errmsg "Expecting \"if\" in breakpoint condition; got: #{expr}.\n"
26
26
  else
27
27
  errmsg "Invalid breakpoint location: #{expr}.\n"
28
28
  end
@@ -1,6 +1,6 @@
1
1
  module Byebug
2
2
 
3
- class RestartCommand < Command # :nodoc:
3
+ class RestartCommand < Command
4
4
  self.allow_in_control = true
5
5
 
6
6
  def regexp
@@ -12,28 +12,24 @@ module Byebug
12
12
  end
13
13
 
14
14
  def execute
15
- if not defined? Byebug::PROG_SCRIPT
16
- errmsg "Don't know name of debugged program\n"
17
- return
18
- end
15
+ return errmsg "Don't know name of debugged program\n" unless
16
+ defined? Byebug::PROG_SCRIPT
19
17
 
20
- if not File.exist?(File.expand_path(Byebug::PROG_SCRIPT))
21
- errmsg "Ruby program #{Byebug::PROG_SCRIPT} doesn't exist\n"
22
- return
23
- end
18
+ return errmsg "Ruby program #{Byebug::PROG_SCRIPT} doesn't exist\n" unless
19
+ File.exist?(File.expand_path(Byebug::PROG_SCRIPT))
24
20
 
25
- if not defined? Byebug::RDEBUG_SCRIPT
21
+ if not defined? Byebug::BYEBUG_SCRIPT
26
22
  print "Byebug was not called from the outset...\n"
27
23
  if not File.executable?(Byebug::PROG_SCRIPT)
28
24
  print "Ruby program #{Byebug::PROG_SCRIPT} not executable... " \
29
25
  "We'll add a call to Ruby.\n"
30
26
  ruby = begin defined?(Gem) ? Gem.ruby : "ruby" rescue "ruby" end
31
- byebug_script = "#{ruby} -I#{$:.join(' -I')} #{Byebug::PROG_SCRIPT}"
27
+ cmd = "#{ruby} -I#{$:.join(' -I')} #{Byebug::PROG_SCRIPT}"
32
28
  else
33
- byebug_script = Byebug::PROG_SCRIPT
29
+ cmd = Byebug::PROG_SCRIPT
34
30
  end
35
31
  else
36
- byebug_script = Byebug::RDEBUG_SCRIPT
32
+ cmd = Byebug::BYEBUG_SCRIPT
37
33
  end
38
34
 
39
35
  begin
@@ -43,16 +39,13 @@ module Byebug
43
39
  end
44
40
 
45
41
  if @match[1]
46
- argv = [Byebug::PROG_SCRIPT] + @match[1].split(/[ \t]+/)
42
+ cmd += " #{@match[1]}"
43
+ elsif not defined? Command.settings[:argv]
44
+ return errmsg "Arguments not set. Use 'set args' to set them.\n"
47
45
  else
48
- if not defined? Command.settings[:argv]
49
- errmsg "Arguments have not been set. Use 'set args' to set them.\n"
50
- return
51
- else
52
- argv = Command.settings[:argv]
53
- end
46
+ require 'shellwords'
47
+ cmd += " #{Command.settings[:argv].compact.shelljoin}"
54
48
  end
55
- cmd = "#{byebug_script} #{argv.compact.join(' ')}"
56
49
 
57
50
  # An execv would be preferable to the "exec" below.
58
51
  print "Re exec'ing:\n\t#{cmd}\n"
@@ -1,6 +1,6 @@
1
1
  module Byebug
2
2
 
3
- module DisplayFunctions # :nodoc:
3
+ module DisplayFunctions
4
4
 
5
5
  def display_expression(exp)
6
6
  print "%s = %s\n", exp, debug_silent_eval(exp).to_s
@@ -22,7 +22,7 @@ module Byebug
22
22
  end
23
23
  end
24
24
 
25
- class AddDisplayCommand < Command # :nodoc:
25
+ class AddDisplayCommand < Command
26
26
  def regexp
27
27
  /^\s*disp(?:lay)?\s+(.+)$/
28
28
  end
@@ -47,7 +47,7 @@ module Byebug
47
47
  end
48
48
  end
49
49
 
50
- class DisplayCommand < Command # :nodoc:
50
+ class DisplayCommand < Command
51
51
  def self.always_run
52
52
  Byebug.annotate = 0 unless Byebug.annotate
53
53
  if Byebug.annotate > 1
@@ -78,7 +78,7 @@ module Byebug
78
78
  end
79
79
  end
80
80
 
81
- class DeleteDisplayCommand < Command # :nodoc:
81
+ class DeleteDisplayCommand < Command
82
82
 
83
83
  def regexp
84
84
  /^\s* undisp(?:lay)? \s* (?:(\S+))?$/x
@@ -16,14 +16,15 @@ module Byebug
16
16
  return nil unless pos
17
17
  breakpoints.each do |b|
18
18
  if b.id == pos
19
- enabled = ("Enable" == is_enable)
19
+ enabled = ('Enable' == is_enable)
20
20
  if enabled
21
21
  unless syntax_valid?(b.expr)
22
- errmsg("Expression \"#{b.expr}\" syntactically incorrect; breakpoint remains disabled.\n")
22
+ errmsg "Expression \"#{b.expr}\" syntactically incorrect; " \
23
+ "breakpoint remains disabled.\n"
23
24
  break
24
25
  end
25
26
  end
26
- b.enabled = ("Enable" == is_enable)
27
+ b.enabled = ('Enable' == is_enable)
27
28
  break
28
29
  end
29
30
  end
@@ -38,7 +39,7 @@ module Byebug
38
39
  args.each do |pos|
39
40
  pos = get_int(pos, "#{is_enable} display", 1, @state.display.size)
40
41
  return nil unless pos
41
- @state.display[pos-1][0] = ("Enable" == is_enable)
42
+ @state.display[pos-1][0] = ('Enable' == is_enable)
42
43
  end
43
44
  end
44
45
 
@@ -49,11 +50,11 @@ module Byebug
49
50
  [
50
51
  ['breakpoints', 2, 'Enable specified breakpoints',
51
52
  'Give breakpoint numbers (separated by spaces) as arguments. This is ' \
52
- 'used to cancel the effect of the \"disable\" command.'],
53
+ 'used to cancel the effect of the "disable" command.'],
53
54
  ['display', 2,
54
55
  'Enable some expressions to be displayed when program stops',
55
56
  'Arguments are the code numbers of the expressions to resume ' \
56
- 'displaying. Do \"info display\" to see the current list of code ' \
57
+ 'displaying. Do "info display" to see the current list of code ' \
57
58
  'numbers.'],
58
59
  ].map do |name, min, short_help, long_help|
59
60
  SubcmdStruct.new(name, min, short_help, long_help)
@@ -65,8 +66,8 @@ module Byebug
65
66
 
66
67
  def execute
67
68
  if not @match[1]
68
- errmsg "\"enable\" must be followed \"display\", \"breakpoints\"" +
69
- " or breakpoint numbers.\n"
69
+ errmsg "\"enable\" must be followed by \"display\", \"breakpoints\" " \
70
+ "or breakpoint numbers.\n"
70
71
  else
71
72
  args = @match[1].split(/[ \t]+/)
72
73
  param = args.shift
@@ -74,17 +75,17 @@ module Byebug
74
75
  if subcmd
75
76
  send("enable_#{subcmd.name}", args)
76
77
  else
77
- send("enable_breakpoints", args.unshift(param))
78
+ send('enable_breakpoints', args.unshift(param))
78
79
  end
79
80
  end
80
81
  end
81
82
 
82
83
  def enable_breakpoints(args)
83
- enable_disable_breakpoints("Enable", args)
84
+ enable_disable_breakpoints('Enable', args)
84
85
  end
85
86
 
86
87
  def enable_display(args)
87
- enable_disable_display("Enable", args)
88
+ enable_disable_display('Enable', args)
88
89
  end
89
90
 
90
91
  class << self
@@ -99,7 +100,7 @@ module Byebug
99
100
  return "Invalid \"enable\" subcommand \"#{args[1]}\"." unless subcmd
100
101
 
101
102
  str = subcmd.short_help + '.'
102
- str += "\n" + subcmd.long_help if subcmd.long_help
103
+ str += '\n' + subcmd.long_help if subcmd.long_help
103
104
  return str
104
105
  end
105
106
 
@@ -127,7 +128,7 @@ module Byebug
127
128
  'breakpoint is not forgotten, but has no effect until reenabled.'],
128
129
  ['display', 1, 'Disable some display expressions when program stops',
129
130
  'Arguments are the code numbers of the expressions to stop ' \
130
- 'displaying. Do \"info display\" to see the current list of code ' \
131
+ 'displaying. Do "info display" to see the current list of code ' \
131
132
  'numbers.'],
132
133
  ].map do |name, min, short_help, long_help|
133
134
  SubcmdStruct.new(name, min, short_help, long_help)
@@ -139,8 +140,8 @@ module Byebug
139
140
 
140
141
  def execute
141
142
  if not @match[1]
142
- errmsg "\"disable\" must be followed \"display\", \"breakpoints\"" +
143
- " or breakpoint numbers.\n"
143
+ errmsg "\"disable\" must be followed by \"display\", \"breakpoints\" " \
144
+ "or breakpoint numbers.\n"
144
145
  else
145
146
  args = @match[1].split(/[ \t]+/)
146
147
  param = args.shift
@@ -148,17 +149,17 @@ module Byebug
148
149
  if subcmd
149
150
  send("disable_#{subcmd.name}", args)
150
151
  else
151
- send("disable_breakpoints", args.unshift(param))
152
+ send('disable_breakpoints', args.unshift(param))
152
153
  end
153
154
  end
154
155
  end
155
156
 
156
157
  def disable_breakpoints(args)
157
- enable_disable_breakpoints("Disable", args)
158
+ enable_disable_breakpoints('Disable', args)
158
159
  end
159
160
 
160
161
  def disable_display(args)
161
- enable_disable_display("Disable", args)
162
+ enable_disable_display('Disable', args)
162
163
  end
163
164
 
164
165
  class << self
@@ -173,7 +174,7 @@ module Byebug
173
174
  return "Invalid \"disable\" subcommand \"#{args[1]}\"." unless subcmd
174
175
 
175
176
  str = subcmd.short_help + '.'
176
- str += "\n" + subcmd.long_help if subcmd.long_help
177
+ str += '\n' + subcmd.long_help if subcmd.long_help
177
178
  return str
178
179
  end
179
180
 
@@ -23,7 +23,7 @@ module Byebug
23
23
  end
24
24
  end
25
25
 
26
- class EvalCommand < Command # :nodoc:
26
+ class EvalCommand < Command
27
27
  self.allow_in_control = true
28
28
 
29
29
  register_setting_get(:autoeval) do
@@ -31,11 +31,10 @@ module Byebug
31
31
  %{
32
32
  fin[ish] [frame-number]\tExecute until selected stack frame returns.
33
33
 
34
- If no frame number is given, we run until the currently selected frame
35
- returns. The currently selected frame starts out the most-recent
36
- frame or 0 if no frame positioning (e.g "up", "down" or "frame") has
37
- been performed. If a frame number is given we run until that frame
38
- returns.
34
+ If no frame number is given, we run until the currently selected frame returns.
35
+ The currently selected frame starts out the most-recent frame or 0 if no frame
36
+ positioning (e.g "up", "down" or "frame") has been performed. If a frame number
37
+ is given we run until that frame returns.
39
38
  }
40
39
  end
41
40
  end
@@ -41,18 +41,18 @@ module Byebug
41
41
  ['locals', 2, 'Local variables of the current stack frame'],
42
42
  ['program', 2, 'Execution status of the program'],
43
43
  ['stack', 2, 'Backtrace of the stack'],
44
- # ['thread', 6, 'List info about thread NUM',
45
- # 'If no thread number is given, we list info for all threads. "terse"' \
46
- # ' and "verbose" options are possible. If "terse", just give summary ' \
47
- # 'thread name information. See "help info threads" for more detail ' \
48
- # 'about this summary information. If "verbose" is appended to the end' \
49
- # ' of the command, then the entire stack trace is given for each ' \
50
- # 'thread.'],
51
- # ['threads', 7, 'information of currently-known threads',
52
- # 'This information includes whether the thread is the current thread ' \
53
- # '(+), it\'s suspended ($) or it\'s ignored (!), plus the thread ' \
54
- # 'number and the top stack item. If "verbose" is given then the ' \
55
- # 'entire stack frame is shown.'],
44
+ ['thread', 6, 'List info about thread NUM',
45
+ 'If no thread number is given, we list info for all threads. "terse"' \
46
+ ' and "verbose" options are possible. If "terse", just give summary ' \
47
+ 'thread name information. See "help info threads" for more detail ' \
48
+ 'about this summary information. If "verbose" is appended to the end' \
49
+ ' of the command, then the entire stack trace is given for each ' \
50
+ 'thread.'],
51
+ ['threads', 7, 'information of currently-known threads',
52
+ 'This information includes whether the thread is the current thread ' \
53
+ '(+), it\'s suspended ($) or it\'s ignored (!), plus the thread ' \
54
+ 'number and the top stack item. If "verbose" is given then the ' \
55
+ 'entire stack frame is shown.'],
56
56
  ['variables', 1,
57
57
  'Local and instance variables of the current stack frame']
58
58
  ].map do |name, min, short_help, long_help|
@@ -114,37 +114,30 @@ module Byebug
114
114
  end
115
115
 
116
116
  def info_breakpoints(*args)
117
- unless @state.context
118
- print "info breakpoints not available here.\n"
119
- return
117
+ return print "\"info breakpoints\" not available here.\n" unless
118
+ @state.context
119
+
120
+ return print "No breakpoints.\n" if Byebug.breakpoints.empty?
121
+
122
+ brkpts = Byebug.breakpoints.sort_by{|b| b.id}
123
+ unless args.empty?
124
+ indices = args.map{|a| a.to_i}
125
+ brkpts = brkpts.select{|b| indices.member?(b.id)}
126
+ return errmsg "No breakpoints found among list given.\n" if
127
+ brkpts.empty?
120
128
  end
121
- unless Byebug.breakpoints.empty?
122
- brkpts = Byebug.breakpoints.sort_by{|b| b.id}
123
- unless args.empty?
124
- indices = args.map{|a| a.to_i}
125
- brkpts = brkpts.select{|b| indices.member?(b.id)}
126
- if brkpts.empty?
127
- errmsg "No breakpoints found among list given.\n"
128
- return
129
- end
129
+ print "Num Enb What\n"
130
+ brkpts.each do |b|
131
+ print "%-3d %-3s at %s:%s%s\n", b.id,
132
+ b.enabled? ? 'y' : 'n',
133
+ b.source,
134
+ b.pos,
135
+ b.expr.nil? ? '' : " if #{b.expr}"
136
+ hits = b.hit_count
137
+ if hits > 0
138
+ s = (hits > 1) ? 's' : ''
139
+ print "\tbreakpoint already hit #{hits} time#{s}\n"
130
140
  end
131
- print "Num Enb What\n"
132
- brkpts.each do |b|
133
- if b.expr.nil?
134
- print "%3d %s at %s:%s\n",
135
- b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos
136
- else
137
- print "%3d %s at %s:%s if %s\n",
138
- b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr
139
- end
140
- hits = b.hit_count
141
- if hits > 0
142
- s = (hits > 1) ? 's' : ''
143
- print "\tbreakpoint already hit #{hits} time#{s}\n"
144
- end
145
- end
146
- else
147
- print "No breakpoints.\n"
148
141
  end
149
142
  end
150
143
 
@@ -167,6 +160,35 @@ module Byebug
167
160
  end
168
161
  end
169
162
 
163
+ def info_file_path(file)
164
+ path = LineCache.path(file)
165
+ if path != file
166
+ print " - #{path}"
167
+ end
168
+ end
169
+
170
+ def info_file_lines(file)
171
+ lines = LineCache.size(file)
172
+ print "\t %d lines\n", lines if lines
173
+ end
174
+
175
+ def info_file_breakpoints(file)
176
+ breakpoints = LineCache.trace_line_numbers(file)
177
+ if breakpoints
178
+ print "\tbreakpoint line numbers:\n"
179
+ print columnize(breakpoints.to_a.sort, self.class.settings[:width])
180
+ end
181
+ end
182
+
183
+ def info_file_mtime(file)
184
+ stat = LineCache.stat(file)
185
+ print "\t%s\n", stat.mtime if stat
186
+ end
187
+
188
+ def info_file_sha1(file)
189
+ print "\t%s\n", LineCache.sha1(file)
190
+ end
191
+
170
192
  def info_file(*args)
171
193
  return info_files unless args[0]
172
194
  file = args[0]
@@ -184,33 +206,13 @@ module Byebug
184
206
  end
185
207
 
186
208
  print "File #{file}"
187
- path = LineCache.path(file)
188
- if %w(all basic path).member?(subcmd.name) and path != file
189
- print " - #{path}"
190
- end
209
+ info_file_path(file) if %w(all basic path).member?(subcmd.name)
191
210
  print "\n"
192
211
 
193
- if %w(all basic lines).member?(subcmd.name)
194
- lines = LineCache.size(file)
195
- print "\t %d lines\n", lines if lines
196
- end
197
-
198
- if %w(all breakpoints).member?(subcmd.name)
199
- breakpoints = LineCache.trace_line_numbers(file)
200
- if breakpoints
201
- print "\tbreakpoint line numbers:\n"
202
- print columnize(breakpoints.to_a.sort, self.class.settings[:width])
203
- end
204
- end
205
-
206
- if %w(all mtime).member?(subcmd.name)
207
- stat = LineCache.stat(file)
208
- print "\t%s\n", stat.mtime if stat
209
- end
210
-
211
- if %w(all sha1).member?(subcmd.name)
212
- print "\t%s\n", LineCache.sha1(file)
213
- end
212
+ info_file_lines(file) if %w(all basic lines).member?(subcmd.name)
213
+ info_file_breakpoints(file) if %w(all breakpoints).member?(subcmd.name)
214
+ info_file_mtime(file) if %w(all mtime).member?(subcmd.name)
215
+ info_file_sha1(file) if %w(all sha1).member?(subcmd.name)
214
216
  end
215
217
 
216
218
  def info_files(*args)
@@ -301,56 +303,56 @@ module Byebug
301
303
  print_backtrace
302
304
  end
303
305
 
304
- # def info_thread_preamble(arg)
305
- # if not @state.context
306
- # errmsg "info threads not available here.\n"
307
- # return false, false
308
- # end
309
- # verbose = if arg
310
- # subcmd = find(InfoThreadSubcommands, arg)
311
- # unless subcmd
312
- # errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
313
- # return false, false
314
- # end
315
- # 'verbose' == subcmd.name
316
- # else
317
- # false
318
- # end
319
- # return true, verbose
320
- # end
321
- # private :info_thread_preamble
322
-
323
- # def info_threads(*args)
324
- # ok, verbose = info_thread_preamble(args[0])
325
- # return unless ok
326
- # threads = Byebug.contexts.sort_by{|c| c.thnum}.each do |c|
327
- # display_context(c, !verbose)
328
- # if verbose and not c.ignored?
329
- # (0...c.stack_size).each do |idx|
330
- # print "\t"
331
- # print_frame(idx, false, c)
332
- # end
333
- # end
334
- # end
335
- # end
336
-
337
- # def info_thread(*args)
338
- # unless args[0]
339
- # info_threads(args[0])
340
- # return
341
- # end
342
- # ok, verbose = info_thread_preamble(args[1])
343
- # return unless ok
344
- # c = parse_thread_num("info thread" , args[0])
345
- # return unless c
346
- # display_context(c, !verbose)
347
- # if verbose and not c.ignored?
348
- # (0...c.stack_size).each do |idx|
349
- # print "\t"
350
- # print_frame(idx, false, c)
351
- # end
352
- # end
353
- # end
306
+ def info_thread_preamble(arg)
307
+ if not @state.context
308
+ errmsg "info threads not available here.\n"
309
+ return false, false
310
+ end
311
+ verbose = if arg
312
+ subcmd = find(InfoThreadSubcommands, arg)
313
+ unless subcmd
314
+ errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
315
+ return false, false
316
+ end
317
+ 'verbose' == subcmd.name
318
+ else
319
+ false
320
+ end
321
+ return true, verbose
322
+ end
323
+ private :info_thread_preamble
324
+
325
+ def info_threads(*args)
326
+ ok, verbose = info_thread_preamble(args[0])
327
+ return unless ok
328
+ threads = Byebug.contexts.sort_by{|c| c.thnum}.each do |c|
329
+ display_context(c, !verbose)
330
+ if verbose and not c.ignored?
331
+ (0...c.stack_size).each do |idx|
332
+ print "\t"
333
+ print_frame(idx, false, c)
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ def info_thread(*args)
340
+ unless args[0]
341
+ info_threads(args[0])
342
+ return
343
+ end
344
+ ok, verbose = info_thread_preamble(args[1])
345
+ return unless ok
346
+ c = parse_thread_num("info thread" , args[0])
347
+ return unless c
348
+ display_context(c, !verbose)
349
+ if verbose and not c.ignored?
350
+ (0...c.stack_size).each do |idx|
351
+ print "\t"
352
+ print_frame(idx, false, c)
353
+ end
354
+ end
355
+ end
354
356
 
355
357
  def info_global_variables(*args)
356
358
  unless @state.context