byebug 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -2
  3. data/CHANGELOG.md +15 -0
  4. data/GUIDE.md +17 -35
  5. data/Gemfile +8 -5
  6. data/LICENSE +1 -1
  7. data/README.md +10 -22
  8. data/Rakefile +1 -1
  9. data/ext/byebug/byebug.c +3 -2
  10. data/lib/byebug.rb +3 -38
  11. data/lib/byebug/commands/break.rb +83 -0
  12. data/lib/byebug/commands/catchpoint.rb +0 -1
  13. data/lib/byebug/commands/condition.rb +10 -6
  14. data/lib/byebug/commands/continue.rb +3 -6
  15. data/lib/byebug/commands/delete.rb +38 -0
  16. data/lib/byebug/commands/edit.rb +0 -2
  17. data/lib/byebug/commands/enable.rb +7 -8
  18. data/lib/byebug/commands/finish.rb +0 -2
  19. data/lib/byebug/commands/frame.rb +13 -15
  20. data/lib/byebug/commands/help.rb +1 -3
  21. data/lib/byebug/commands/history.rb +3 -3
  22. data/lib/byebug/commands/info.rb +4 -13
  23. data/lib/byebug/commands/interrupt.rb +25 -0
  24. data/lib/byebug/commands/kill.rb +0 -2
  25. data/lib/byebug/commands/list.rb +2 -4
  26. data/lib/byebug/commands/method.rb +2 -8
  27. data/lib/byebug/commands/quit.rb +0 -2
  28. data/lib/byebug/commands/reload.rb +2 -15
  29. data/lib/byebug/commands/repl.rb +0 -3
  30. data/lib/byebug/commands/{control.rb → restart.rb} +2 -26
  31. data/lib/byebug/commands/save.rb +0 -1
  32. data/lib/byebug/commands/set.rb +4 -7
  33. data/lib/byebug/commands/show.rb +0 -3
  34. data/lib/byebug/commands/source.rb +0 -3
  35. data/lib/byebug/commands/stepping.rb +3 -4
  36. data/lib/byebug/commands/trace.rb +0 -1
  37. data/lib/byebug/commands/variables.rb +3 -4
  38. data/lib/byebug/context.rb +0 -1
  39. data/lib/byebug/helper.rb +23 -0
  40. data/lib/byebug/interfaces/script_interface.rb +1 -1
  41. data/lib/byebug/processors/command_processor.rb +9 -9
  42. data/lib/byebug/remote.rb +2 -2
  43. data/lib/byebug/setting.rb +3 -1
  44. data/lib/byebug/settings/autoeval.rb +3 -1
  45. data/lib/byebug/settings/autoirb.rb +3 -1
  46. data/lib/byebug/settings/autolist.rb +3 -1
  47. data/lib/byebug/settings/autoreload.rb +1 -3
  48. data/lib/byebug/settings/autosave.rb +1 -3
  49. data/lib/byebug/settings/callstyle.rb +2 -4
  50. data/lib/byebug/settings/fullpath.rb +1 -3
  51. data/lib/byebug/settings/histfile.rb +1 -3
  52. data/lib/byebug/settings/histsize.rb +0 -4
  53. data/lib/byebug/settings/listsize.rb +1 -3
  54. data/lib/byebug/settings/post_mortem.rb +14 -1
  55. data/lib/byebug/settings/width.rb +1 -17
  56. data/lib/byebug/version.rb +1 -1
  57. data/test/break_test.rb +376 -0
  58. data/test/condition_test.rb +82 -0
  59. data/test/continue_test.rb +27 -30
  60. data/test/debugger_alias_test.rb +4 -4
  61. data/test/delete_test.rb +26 -0
  62. data/test/display_test.rb +80 -102
  63. data/test/edit_test.rb +28 -31
  64. data/test/eval_test.rb +50 -80
  65. data/test/finish_test.rb +23 -23
  66. data/test/frame_test.rb +172 -186
  67. data/test/help_test.rb +27 -37
  68. data/test/history_test.rb +32 -41
  69. data/test/info_test.rb +198 -230
  70. data/test/interrupt_test.rb +17 -36
  71. data/test/irb_test.rb +47 -0
  72. data/test/kill_test.rb +19 -19
  73. data/test/list_test.rb +126 -133
  74. data/test/method_test.rb +21 -54
  75. data/test/post_mortem_test.rb +44 -46
  76. data/test/pry_test.rb +42 -0
  77. data/test/quit_test.rb +17 -15
  78. data/test/reload_test.rb +23 -28
  79. data/test/restart_test.rb +35 -63
  80. data/test/save_test.rb +46 -62
  81. data/test/set_test.rb +93 -144
  82. data/test/show_test.rb +50 -71
  83. data/test/source_test.rb +23 -26
  84. data/test/stepping_test.rb +125 -153
  85. data/test/support/matchers.rb +1 -6
  86. data/test/support/test_interface.rb +1 -1
  87. data/test/support/{test_dsl.rb → utils.rb} +17 -64
  88. data/test/test_helper.rb +25 -7
  89. data/test/thread_test.rb +101 -89
  90. data/test/trace_test.rb +48 -85
  91. data/test/variables_test.rb +43 -80
  92. metadata +18 -13
  93. data/lib/byebug/commands/breakpoints.rb +0 -137
  94. data/lib/byebug/commands/skip.rb +0 -30
  95. data/test/breakpoints_test.rb +0 -474
  96. data/test/conditions_test.rb +0 -82
  97. data/test/repl_test.rb +0 -75
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug "continue" command.
4
2
  class ContinueCommand < Command
5
3
  self.allow_in_post_mortem = true
6
4
 
@@ -12,10 +10,9 @@ module Byebug
12
10
  if @match[1] && !@state.context.dead?
13
11
  filename = File.expand_path(@state.file)
14
12
  return unless line_number = get_int(@match[1], "Continue", 0, nil, 0)
15
- return errmsg "Line #{line_number} is not a stopping point in file " \
16
- "\"#{filename}\"\n" unless
17
- LineCache.trace_line_numbers(filename).member?(line_number)
18
-
13
+ unless LineCache.trace_line_numbers(filename).member?(line_number)
14
+ return errmsg "Line #{line_number} is not a valid stopping point in file\n"
15
+ end
19
16
  Byebug.add_breakpoint filename, line_number
20
17
  end
21
18
  @state.proceed
@@ -0,0 +1,38 @@
1
+ module Byebug
2
+ class DeleteCommand < Command
3
+ self.allow_in_post_mortem = false
4
+ self.allow_in_control = true
5
+
6
+ def regexp
7
+ /^\s* del(?:ete)? (?:\s+(.*))?$/x
8
+ end
9
+
10
+ def execute
11
+ return errmsg "We are not in a state we can delete breakpoints.\n" unless
12
+ @state.context
13
+
14
+ if not @match[1]
15
+ Byebug.breakpoints.clear if confirm("Delete all breakpoints? (y or n) ")
16
+ else
17
+ @match[1].split(/[ \t]+/).each do |pos|
18
+ return unless pos = get_int(pos, "Delete", 1)
19
+ errmsg "No breakpoint number %d\n", pos unless
20
+ Byebug.remove_breakpoint(pos)
21
+ end
22
+ end
23
+ end
24
+
25
+ class << self
26
+ def names
27
+ %w(delete)
28
+ end
29
+
30
+ def description
31
+ %{del[ete][ nnn...]
32
+
33
+ Without and argument, deletes all breakpoints. With integer arguments,
34
+ it deletes specific breakpoints.}
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,4 @@
1
1
  module Byebug
2
-
3
2
  class EditCommand < Command
4
3
  self.allow_in_control = true
5
4
 
@@ -46,5 +45,4 @@ module Byebug
46
45
  end
47
46
  end
48
47
  end
49
-
50
48
  end
@@ -1,9 +1,10 @@
1
1
  module Byebug
2
-
3
- # Mix-in module to assist in command parsing.
2
+ #
3
+ # Mixin to assist command parsing
4
+ #
4
5
  module EnableDisableFunctions
5
6
  def enable_disable_breakpoints(is_enable, args)
6
- return errmsg "No breakpoints have been set." if Byebug.breakpoints.empty?
7
+ return errmsg "No breakpoints have been set" if Byebug.breakpoints.empty?
7
8
 
8
9
  all_breakpoints = Byebug.breakpoints.sort_by {|b| b.id }
9
10
  if args.empty?
@@ -32,8 +33,7 @@ module Byebug
32
33
 
33
34
  def enable_disable_display(is_enable, args)
34
35
  if 0 == @state.display.size
35
- errmsg "No display expressions have been set.\n"
36
- return
36
+ return errmsg "No display expressions have been set\n"
37
37
  end
38
38
  args.each do |pos|
39
39
  pos = get_int(pos, "#{is_enable} display", 1, @state.display.size)
@@ -64,7 +64,7 @@ module Byebug
64
64
 
65
65
  def execute
66
66
  return errmsg "\"enable\" must be followed by \"display\", " \
67
- "\"breakpoints\" or breakpoint numbers.\n" unless @match[1]
67
+ "\"breakpoints\" or breakpoint ids\n" unless @match[1]
68
68
 
69
69
  args = @match[1].split(/[ \t]+/)
70
70
  param = args.shift
@@ -118,7 +118,7 @@ module Byebug
118
118
 
119
119
  def execute
120
120
  return errmsg "\"disable\" must be followed by \"display\", " \
121
- "\"breakpoints\" or breakpoint numbers.\n" unless @match[1]
121
+ "\"breakpoints\" or breakpoint ids\n" unless @match[1]
122
122
 
123
123
  args = @match[1].split(/[ \t]+/)
124
124
  param = args.shift
@@ -151,5 +151,4 @@ module Byebug
151
151
  end
152
152
  end
153
153
  end
154
-
155
154
  end
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug's 'finish' command.
4
2
  class FinishCommand < Command
5
3
  self.allow_in_post_mortem = false
6
4
 
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
  module Byebug
3
-
4
- # Mix-in module to assist in command parsing.
3
+ #
4
+ # Mixin to assist command parsing
5
+ #
5
6
  module FrameFunctions
6
7
  def c_frame?(frame_no)
7
8
  @state.context.frame_binding(frame_no).nil?
@@ -52,7 +53,7 @@ module Byebug
52
53
  end
53
54
 
54
55
  def get_frame_class(style, pos)
55
- frame_class = style == :short ? '' : "#{@state.context.frame_class pos}"
56
+ frame_class = style == 'short' ? '' : "#{@state.context.frame_class pos}"
56
57
  return frame_class == '' ? '' : "#{frame_class}."
57
58
  end
58
59
 
@@ -67,7 +68,7 @@ module Byebug
67
68
  args = @state.context.frame_args pos
68
69
  return '' if args.empty?
69
70
 
70
- locals = @state.context.frame_locals pos if style == :long
71
+ locals = @state.context.frame_locals pos if style == 'long'
71
72
  my_args = args.map do |arg|
72
73
  case arg[0]
73
74
  when :block
@@ -77,7 +78,7 @@ module Byebug
77
78
  else
78
79
  prefix, default = '', nil
79
80
  end
80
- klass = style == :long && arg[1] ? "##{locals[arg[1]].class}" : ''
81
+ klass = style == 'long' && arg[1] ? "##{locals[arg[1]].class}" : ''
81
82
  "#{prefix}#{arg[1] || default}#{klass}"
82
83
  end
83
84
 
@@ -118,18 +119,16 @@ module Byebug
118
119
  end
119
120
  end
120
121
 
122
+ def shortpath(fullpath)
123
+ separator = File::ALT_SEPARATOR || File::SEPARATOR
124
+ "...#{separator}" + fullpath.split(separator)[-3..-1].join(separator)
125
+ end
126
+
121
127
  def print_frame(pos, mark_current = true)
122
- file = @state.context.frame_file pos
128
+ fullpath = @state.context.frame_file pos
129
+ file = Setting[:fullpath] ? fullpath : shortpath(fullpath)
123
130
  line = @state.context.frame_line pos
124
131
 
125
- unless Setting[:fullpath]
126
- path_components = file.split(/[\\\/]/)
127
- if path_components.size > 3
128
- path_components[0...-3] = '...'
129
- file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR)
130
- end
131
- end
132
-
133
132
  if mark_current
134
133
  frame_str = (pos == @state.frame_pos) ? '--> ' : ' '
135
134
  else
@@ -150,7 +149,6 @@ module Byebug
150
149
  end
151
150
  end
152
151
 
153
- # Implements byebug "where" or "backtrace" command.
154
152
  class WhereCommand < Command
155
153
  def regexp
156
154
  /^\s* (?:w(?:here)?|bt|backtrace) \s*$/x
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug "help" command.
4
2
  class HelpCommand < Command
5
3
  include Columnize
6
4
 
@@ -26,7 +24,7 @@ module Byebug
26
24
  end
27
25
  end
28
26
 
29
- print "byebug help v#{Byebug::VERSION}\n" unless Setting[:testing]
27
+ print "byebug help v#{VERSION}\n" unless Setting[:testing]
30
28
 
31
29
  print "Type \"help <command-name>\" for help on a specific command\n\n"
32
30
  print "Available commands:\n"
@@ -5,11 +5,11 @@ module Byebug
5
5
  end
6
6
 
7
7
  def execute
8
- if Byebug::Setting[:autosave]
8
+ if Setting[:autosave]
9
9
  if arg = @match[:num_cmds]
10
- size = get_int(arg, 'history', 1, Byebug::Setting[:histsize])
10
+ size = get_int(arg, 'history', 1, Setting[:histsize])
11
11
  end
12
- print Byebug::History.to_s(size || Byebug::Setting[:histsize])
12
+ print History.to_s(size || Setting[:histsize])
13
13
  else
14
14
  errmsg "Not currently saving history. Enable it with \"set autosave\"\n"
15
15
  end
@@ -1,5 +1,4 @@
1
1
  module Byebug
2
-
3
2
  module InfoFunctions
4
3
  def info_catch(*args)
5
4
  return print "No frame selected.\n" unless @state.context
@@ -14,7 +13,6 @@ module Byebug
14
13
  end
15
14
  end
16
15
 
17
- # Implements byebug "info" command.
18
16
  class InfoCommand < Command
19
17
  include Columnize
20
18
  self.allow_in_control = true
@@ -41,7 +39,6 @@ module Byebug
41
39
  'position in source file' ],
42
40
  ['locals' , 2, 'Local variables of the current stack frame' ],
43
41
  ['program' , 2, 'Execution status of the program' ],
44
- ['stack' , 2, 'Backtrace of the stack' ],
45
42
  ['variables' , 1, 'Local and instance variables of the ' \
46
43
  'current stack frame' ]
47
44
  ].map do |name, min, help|
@@ -141,8 +138,8 @@ module Byebug
141
138
  private :info_file_path
142
139
 
143
140
  def info_file_lines(file)
144
- lines = LineCache.size(file)
145
- print "\t #{lines} lines\n" if lines
141
+ lines = File.foreach(file)
142
+ print "\t#{lines.count} lines\n" if lines
146
143
  end
147
144
  private :info_file_lines
148
145
 
@@ -156,13 +153,13 @@ module Byebug
156
153
  private :info_file_breakpoints
157
154
 
158
155
  def info_file_mtime(file)
159
- stat = LineCache.stat(file)
156
+ stat = File.stat(file)
160
157
  print "\t#{stat.mtime}\n" if stat
161
158
  end
162
159
  private :info_file_mtime
163
160
 
164
161
  def info_file_sha1(file)
165
- print "\t#{LineCache.sha1(file)}\n"
162
+ print "\t#{Digest::SHA1.hexdigest(file)}\n"
166
163
  end
167
164
  private :info_file_sha1
168
165
 
@@ -250,10 +247,6 @@ module Byebug
250
247
  info_stop_reason @state.context.stop_reason
251
248
  end
252
249
 
253
- def info_stack(*args)
254
- print_backtrace
255
- end
256
-
257
250
  def info_global_variables(*args)
258
251
  var_global
259
252
  end
@@ -295,7 +288,5 @@ module Byebug
295
288
  return str
296
289
  end
297
290
  end
298
-
299
291
  end
300
-
301
292
  end
@@ -0,0 +1,25 @@
1
+ module Byebug
2
+ class InterruptCommand < Command
3
+ self.allow_in_control = true
4
+ self.allow_in_post_mortem = false
5
+
6
+ def regexp
7
+ /^\s*i(?:nterrupt)?\s*$/
8
+ end
9
+
10
+ def execute
11
+ context = Byebug.thread_context(Thread.main)
12
+ context.interrupt
13
+ end
14
+
15
+ class << self
16
+ def names
17
+ %w(interrupt)
18
+ end
19
+
20
+ def description
21
+ %{i|nterrupt\t interrupt the program}
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug "kill" command
4
2
  class KillCommand < Command
5
3
  self.allow_in_control = true
6
4
 
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug "list" command.
4
2
  class ListCommand < Command
5
3
  def regexp
6
4
  /^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
@@ -8,8 +6,8 @@ module Byebug
8
6
 
9
7
  def execute
10
8
  Byebug.source_reload if Setting[:autoreload]
11
- lines = getlines(@state.file, @state.line)
12
- if !lines
9
+
10
+ unless lines = get_lines(@state.file)
13
11
  errmsg "No sourcefile available for #{@state.file}\n"
14
12
  return @state.previous_line
15
13
  end
@@ -1,19 +1,14 @@
1
1
  module Byebug
2
- # Implements byebug's 'method' command.
3
2
  class MethodCommand < Command
4
3
  include Columnize
5
4
 
6
5
  def regexp
7
- /^\s* m(?:ethod)? \s+ ((iv)|(i(:?nstance)?)\s+)?/x
6
+ /^\s* m(?:ethod)? \s+ (i(:?nstance)?\s+)?/x
8
7
  end
9
8
 
10
9
  def execute
11
10
  obj = bb_eval(@match.post_match)
12
- if @match[1] == 'iv'
13
- obj.instance_variables.sort.each do |v|
14
- print "#{v} = #{obj.instance_variable_get(v).inspect}\n"
15
- end
16
- elsif @match[1]
11
+ if @match[1]
17
12
  print "#{columnize(obj.methods.sort(), Setting[:width])}\n"
18
13
  elsif !obj.kind_of?(Module)
19
14
  print "Should be Class/Module: #{@match.post_match}\n"
@@ -29,7 +24,6 @@ module Byebug
29
24
 
30
25
  def description
31
26
  %{m[ethod] i[nstance] <obj>\tshow methods of object
32
- m[ethod] iv <obj>\t\tshow instance variables of object
33
27
  m[ethod] <class|module>\t\tshow instance methods of class or module}
34
28
  end
35
29
  end
@@ -1,6 +1,4 @@
1
1
  module Byebug
2
-
3
- # Implements byebug "quit" command
4
2
  class QuitCommand < Command
5
3
  self.allow_in_control = true
6
4
 
@@ -1,17 +1,4 @@
1
1
  module Byebug
2
-
3
- module ReloadFunctions
4
- def getlines(file, line)
5
- unless (lines = SCRIPT_LINES__[file]) and lines != true
6
- Tracer::Single.get_line(file, line) if File.exist?(file)
7
- lines = SCRIPT_LINES__[file]
8
- lines = nil if lines == true
9
- end
10
- lines
11
- end
12
- end
13
-
14
- # Implements byebug "reload" command.
15
2
  class ReloadCommand < Command
16
3
  self.allow_in_control = true
17
4
  self.allow_in_post_mortem = false
@@ -22,8 +9,8 @@ module Byebug
22
9
 
23
10
  def execute
24
11
  Byebug.source_reload
25
- print "Source code is reloaded. Automatic reloading is " \
26
- "#{Setting[:autoreload] ? 'on' : 'off'}.\n"
12
+ onoff = Setting[:autoreload] ? 'on' : 'off'
13
+ print "Source code was reloaded. Automatic reloading is #{onoff}\n"
27
14
  end
28
15
 
29
16
  class << self
@@ -48,8 +48,6 @@ module IRB
48
48
  end
49
49
 
50
50
  module Byebug
51
-
52
- # Implements byebug's "irb" command.
53
51
  class IrbCommand < Command
54
52
  def regexp
55
53
  /^\s* irb \s*$/x
@@ -101,7 +99,6 @@ module Byebug
101
99
  has_pry = false
102
100
  end
103
101
 
104
- # Implements byebug's "pry" command
105
102
  class PryCommand < Command
106
103
  def regexp
107
104
  /^\s* pry \s*$/x
@@ -7,8 +7,8 @@ module Byebug
7
7
  end
8
8
 
9
9
  def execute
10
- prog = Byebug::PROG_SCRIPT if defined?(Byebug::PROG_SCRIPT)
11
- byebug_script = Byebug::BYEBUG_SCRIPT if defined?(Byebug::BYEBUG_SCRIPT)
10
+ prog = PROG_SCRIPT if defined?(PROG_SCRIPT)
11
+ byebug_script = BYEBUG_SCRIPT if defined?(BYEBUG_SCRIPT)
12
12
 
13
13
  return errmsg "Don't know name of debugged program\n" unless prog
14
14
 
@@ -55,28 +55,4 @@ module Byebug
55
55
  end
56
56
  end
57
57
  end
58
-
59
- class InterruptCommand < Command
60
- self.allow_in_control = true
61
- self.allow_in_post_mortem = false
62
-
63
- def regexp
64
- /^\s*i(?:nterrupt)?\s*$/
65
- end
66
-
67
- def execute
68
- context = Byebug.thread_context(Thread.main)
69
- context.interrupt
70
- end
71
-
72
- class << self
73
- def names
74
- %w(interrupt)
75
- end
76
-
77
- def description
78
- %{i|nterrupt\t interrupt the program}
79
- end
80
- end
81
- end
82
58
  end