byebug 2.3.1 → 2.4.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +3 -11
  4. data/Rakefile +10 -3
  5. data/bin/byebug +16 -2
  6. data/byebug.gemspec +1 -0
  7. data/ext/byebug/byebug.c +0 -54
  8. data/ext/byebug/byebug.h +3 -4
  9. data/ext/byebug/extconf.rb +1 -1
  10. data/lib/byebug.rb +15 -42
  11. data/lib/byebug/command.rb +12 -28
  12. data/lib/byebug/commands/breakpoints.rb +2 -0
  13. data/lib/byebug/commands/catchpoint.rb +1 -1
  14. data/lib/byebug/commands/condition.rb +1 -0
  15. data/lib/byebug/commands/display.rb +6 -0
  16. data/lib/byebug/commands/frame.rb +10 -3
  17. data/lib/byebug/commands/info.rb +5 -3
  18. data/lib/byebug/commands/reload.rb +1 -0
  19. data/lib/byebug/commands/set.rb +5 -1
  20. data/lib/byebug/commands/threads.rb +5 -4
  21. data/lib/byebug/commands/trace.rb +5 -5
  22. data/lib/byebug/context.rb +3 -3
  23. data/lib/byebug/interface.rb +3 -187
  24. data/lib/byebug/interfaces/local_interface.rb +88 -0
  25. data/lib/byebug/interfaces/remote_interface.rb +55 -0
  26. data/lib/byebug/interfaces/script_interface.rb +45 -0
  27. data/lib/byebug/processor.rb +15 -13
  28. data/lib/byebug/version.rb +1 -1
  29. data/test/breakpoints_test.rb +23 -25
  30. data/test/conditions_test.rb +6 -8
  31. data/test/continue_test.rb +4 -6
  32. data/test/debugger_alias_test.rb +5 -0
  33. data/test/display_test.rb +9 -11
  34. data/test/edit_test.rb +0 -2
  35. data/test/eval_test.rb +1 -3
  36. data/test/finish_test.rb +12 -12
  37. data/test/frame_test.rb +38 -40
  38. data/test/help_test.rb +1 -3
  39. data/test/info_test.rb +12 -14
  40. data/test/kill_test.rb +0 -2
  41. data/test/list_test.rb +1 -3
  42. data/test/method_test.rb +0 -2
  43. data/test/post_mortem_test.rb +77 -96
  44. data/test/quit_test.rb +0 -2
  45. data/test/reload_test.rb +0 -2
  46. data/test/repl_test.rb +3 -5
  47. data/test/restart_test.rb +0 -2
  48. data/test/save_test.rb +1 -3
  49. data/test/set_test.rb +3 -5
  50. data/test/show_test.rb +0 -2
  51. data/test/source_test.rb +0 -2
  52. data/test/stepping_test.rb +17 -19
  53. data/test/support/test_dsl.rb +21 -13
  54. data/test/test_helper.rb +23 -1
  55. data/test/thread_test.rb +19 -21
  56. data/test/trace_test.rb +12 -14
  57. data/test/variables_test.rb +6 -6
  58. metadata +22 -3
@@ -102,10 +102,17 @@ module Byebug
102
102
  realsize = Context.stack_size
103
103
  calcedsize = @state.context.calced_stack_size
104
104
  if calcedsize != realsize
105
- errmsg "Byebug's stacksize (#{calcedsize}) should be #{realsize}. " \
106
- "This might be a bug in byebug or ruby's debugging API's\n"
105
+ if Byebug.post_mortem?
106
+ stacksize = calcedsize
107
+ else
108
+ errmsg "Byebug's stacksize (#{calcedsize}) should be #{realsize}. " \
109
+ "This might be a bug in byebug or ruby's debugging API's\n"
110
+ stacksize = realsize
111
+ end
112
+ else
113
+ stacksize = calcedsize
107
114
  end
108
- (0...realsize).each do |idx|
115
+ (0...stacksize).each do |idx|
109
116
  print_frame(idx)
110
117
  end
111
118
  end
@@ -240,9 +240,11 @@ module Byebug
240
240
  private :info_stop_reason
241
241
 
242
242
  def info_program(*args)
243
- return print "The program crashed.\n" + Byebug.last_exception ?
244
- "Exception: #{Byebug.last_exception.inspect}" : "" + "\n" if
245
- @state.context.dead?
243
+ if @state.context.dead?
244
+ print "The program crashed.\n"
245
+ print "Exception: #{Byebug.last_exception.inspect}\n" if Byebug.last_exception
246
+ return
247
+ end
246
248
 
247
249
  print "Program stopped. "
248
250
  info_stop_reason @state.context.stop_reason
@@ -14,6 +14,7 @@ module Byebug
14
14
  # Implements byebug "reload" command.
15
15
  class ReloadCommand < Command
16
16
  self.allow_in_control = true
17
+ self.allow_in_post_mortem = false
17
18
 
18
19
  register_setting_get(:autoreload) do
19
20
  Byebug.class_variable_get(:@@autoreload)
@@ -51,7 +51,11 @@ module Byebug
51
51
  return unless width = get_int(setting_args[0], "Set width", 10, nil, 80)
52
52
  Command.settings[:width] = width
53
53
  when /^post_mortem$/
54
- Byebug.post_mortem = setting_value
54
+ if setting_value == true
55
+ Byebug.post_mortem
56
+ else
57
+ return print 'Sorry... not implemented yet. Restart byebug'
58
+ end
55
59
  when /^autoeval|autoreload|basename|forcestep|fullpath|linetrace_plus|
56
60
  testing|stack_on_error$/x
57
61
  Command.settings[setting_name.to_sym] = setting_value
@@ -14,9 +14,9 @@ module Byebug
14
14
  end
15
15
  debug_flag = context.ignored? ? '!' : ' '
16
16
  if should_show_top_frame
17
- if context.thread == Thread.current
18
- file = @state.context.frame_file(0)
19
- line = @state.context.frame_line(0)
17
+ if context.thread == Thread.current && !context.dead?
18
+ file = context.frame_file(0)
19
+ line = context.frame_line(0)
20
20
  else
21
21
  if context.thread.backtrace_locations &&
22
22
  context.thread.backtrace_locations[0]
@@ -72,7 +72,8 @@ module Byebug
72
72
  end
73
73
 
74
74
  def execute
75
- Byebug.contexts.sort_by(&:thnum).each { |c| display_context(c) }
75
+ Byebug.contexts.select { |c| Thread.list.include?(c.thread) }
76
+ .sort_by(&:thnum).each { |c| display_context(c) }
76
77
  end
77
78
 
78
79
  class << self
@@ -15,19 +15,19 @@ module Byebug
15
15
  print "#{show_setting('linetrace')}\n"
16
16
  elsif @match[1] =~ /var(?:iable)?/
17
17
  varname = @match[2]
18
- if bb_eval("defined?(#{varname})")
18
+ if global_variables.include?("$#{varname}".to_sym)
19
19
  if @match[3] && @match[3] !~ /(:?no)?stop/
20
20
  errmsg "expecting \"stop\" or \"nostop\"; got \"#{@match[3]}\"\n"
21
21
  else
22
22
  dbg_cmd = (@match[3] && @match[3] !~ /nostop/) ? 'byebug(1,0)' : ''
23
23
  end
24
- eval("trace_var(:\"#{varname}\") do |val|
25
- print \"traced variable \#{varname} has value \#{val}\n\"
24
+ eval("trace_var(:\"\$#{varname}\") do |val|
25
+ print \"traced global variable '#{varname}' has value '\#{val}'\"\n
26
26
  #{dbg_cmd}
27
27
  end")
28
- print "Tracing variable \"#{varname}\".\n"
28
+ print "Tracing global variable \"#{varname}\".\n"
29
29
  else
30
- errmsg "#{varname} is not a global variable.\n"
30
+ errmsg "'#{varname}' is not a global variable.\n"
31
31
  end
32
32
  else
33
33
  errmsg "expecting \"on\", \"off\", \"var\" or \"variable\"; got: " \
@@ -4,18 +4,18 @@ module Byebug
4
4
 
5
5
  class << self
6
6
  def stack_size
7
- if backtrace = Thread.current.backtrace_locations
7
+ if backtrace = Thread.current.backtrace_locations(1)
8
8
  backtrace.drop_while { |l| ignored(l.path) || l.path == '(eval)' }
9
9
  .take_while { |l| !ignored(l.path) }
10
10
  .size
11
11
  else
12
12
  print 'No backtrace available!!'
13
- return 0
13
+ 0
14
14
  end
15
15
  end
16
16
 
17
17
  def real_stack_size
18
- if backtrace = Thread.current.backtrace_locations
18
+ if backtrace = Thread.current.backtrace_locations(1)
19
19
  backtrace.size
20
20
  end
21
21
  end
@@ -1,5 +1,4 @@
1
1
  module Byebug
2
-
3
2
  class Interface
4
3
  attr_writer :have_readline
5
4
 
@@ -29,190 +28,7 @@ module Byebug
29
28
  end
30
29
  end
31
30
 
32
- class LocalInterface < Interface
33
- attr_accessor :command_queue, :history_length, :history_save, :histfile
34
- attr_accessor :restart_file
35
-
36
- FILE_HISTORY = ".byebug_hist" unless defined?(FILE_HISTORY)
37
-
38
- def initialize()
39
- super
40
- @command_queue = []
41
- @have_readline = false
42
- @history_save = true
43
- @history_length = ENV["HISTSIZE"] ? ENV["HISTSIZE"].to_i : 256
44
- @histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", FILE_HISTORY)
45
- open(@histfile, 'r') do |file|
46
- file.each do |line|
47
- line.chomp!
48
- Readline::HISTORY << line
49
- end
50
- end if File.exist?(@histfile)
51
- @restart_file = nil
52
- end
53
-
54
- def read_command(prompt)
55
- readline(prompt, true)
56
- end
57
-
58
- def confirm(prompt)
59
- readline(prompt, false)
60
- end
61
-
62
- def print(*args)
63
- STDOUT.printf(escape(format(*args)))
64
- end
65
-
66
- def close
67
- end
68
-
69
- # Things to do before quitting
70
- def finalize
71
- if Byebug.respond_to?(:save_history)
72
- Byebug.save_history
73
- end
74
- end
75
-
76
- def readline_support?
77
- @have_readline
78
- end
79
-
80
- private
81
-
82
- begin
83
- require 'readline'
84
- class << Byebug
85
- @have_readline = true
86
- define_method(:save_history) do
87
- iface = self.handler.interface
88
- iface.histfile ||= File.join(ENV["HOME"]||ENV["HOMEPATH"]||".",
89
- FILE_HISTORY)
90
- open(iface.histfile, 'w') do |file|
91
- Readline::HISTORY.to_a.last(iface.history_length).each do |line|
92
- file.puts line unless line.strip.empty?
93
- end if defined?(iface.history_save) and iface.history_save
94
- end rescue nil
95
- end
96
- public :save_history
97
- end
98
-
99
- def readline(prompt, hist)
100
- Readline::readline(prompt, hist)
101
- rescue Interrupt
102
- print "^C\n"
103
- retry
104
- end
105
- rescue LoadError
106
- def readline(prompt, hist)
107
- @histfile = ''
108
- @hist_save = false
109
- STDOUT.print prompt
110
- STDOUT.flush
111
- line = STDIN.gets
112
- exit unless line
113
- line.chomp!
114
- line
115
- end
116
- end
117
- end
118
-
119
- class RemoteInterface < Interface
120
- attr_accessor :command_queue, :history_length, :history_save, :histfile
121
- attr_accessor :restart_file
122
-
123
- def initialize(socket)
124
- @command_queue = []
125
- @socket = socket
126
- @history_save = false
127
- @history_length = 256
128
- @histfile = ''
129
- # Do we read the histfile?
130
- # open(@histfile, 'r') do |file|
131
- # file.each do |line|
132
- # line.chomp!
133
- # Readline::HISTORY << line
134
- # end
135
- # end if File.exist?(@histfile)
136
- @restart_file = nil
137
- end
138
-
139
- def close
140
- @socket.close
141
- rescue Exception
142
- end
143
-
144
- def confirm(prompt)
145
- send_command "CONFIRM #{prompt}"
146
- end
147
-
148
- def finalize
149
- end
150
-
151
- def read_command(prompt)
152
- send_command "PROMPT #{prompt}"
153
- end
154
-
155
- def readline_support?
156
- false
157
- end
158
-
159
- def print(*args)
160
- @socket.printf(escape(format(*args)))
161
- end
162
-
163
- private
164
-
165
- def send_command(msg)
166
- @socket.puts msg
167
- result = @socket.gets
168
- raise IOError unless result
169
- result.chomp
170
- end
171
- end
172
-
173
- class ScriptInterface < Interface
174
- attr_accessor :command_queue, :history_length, :history_save, :histfile
175
- attr_accessor :restart_file
176
-
177
- def initialize(file, out, verbose=false)
178
- super()
179
- @command_queue = []
180
- @file = file.respond_to?(:gets) ? file : open(file)
181
- @out = out
182
- @verbose = verbose
183
- @history_save = false
184
- @history_length = 256
185
- @histfile = ''
186
- end
187
-
188
- def finalize
189
- end
190
-
191
- def read_command(prompt)
192
- while result = @file.gets
193
- puts "# #{result}" if @verbose
194
- next if result =~ /^\s*#/
195
- next if result.strip.empty?
196
- break
197
- end
198
- raise IOError unless result
199
- result.chomp!
200
- end
201
-
202
- def readline_support?
203
- false
204
- end
205
-
206
- def confirm(prompt)
207
- 'y'
208
- end
209
-
210
- def print(*args)
211
- @out.printf(*args)
212
- end
213
-
214
- def close
215
- @file.close
216
- end
217
- end
31
+ require_relative 'interfaces/local_interface'
32
+ require_relative 'interfaces/script_interface'
33
+ require_relative 'interfaces/remote_interface'
218
34
  end
@@ -0,0 +1,88 @@
1
+ module Byebug
2
+ class LocalInterface < Interface
3
+ attr_accessor :command_queue, :history_length, :history_save, :histfile
4
+ attr_accessor :restart_file
5
+
6
+ FILE_HISTORY = ".byebug_hist" unless defined?(FILE_HISTORY)
7
+
8
+ def initialize()
9
+ super
10
+ @command_queue = []
11
+ @have_readline = false
12
+ @history_save = true
13
+ @history_length = ENV["HISTSIZE"] ? ENV["HISTSIZE"].to_i : 256
14
+ @histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", FILE_HISTORY)
15
+ open(@histfile, 'r') do |file|
16
+ file.each do |line|
17
+ line.chomp!
18
+ Readline::HISTORY << line
19
+ end
20
+ end if File.exist?(@histfile)
21
+ @restart_file = nil
22
+ end
23
+
24
+ def read_command(prompt)
25
+ readline(prompt, true)
26
+ end
27
+
28
+ def confirm(prompt)
29
+ readline(prompt, false)
30
+ end
31
+
32
+ def print(*args)
33
+ STDOUT.printf(escape(format(*args)))
34
+ end
35
+
36
+ def close
37
+ end
38
+
39
+ # Things to do before quitting
40
+ def finalize
41
+ if Byebug.respond_to?(:save_history)
42
+ Byebug.save_history
43
+ end
44
+ end
45
+
46
+ def readline_support?
47
+ @have_readline
48
+ end
49
+
50
+ private
51
+
52
+ begin
53
+ require 'readline'
54
+ class << Byebug
55
+ @have_readline = true
56
+ define_method(:save_history) do
57
+ iface = self.handler.interface
58
+ iface.histfile ||= File.join(ENV["HOME"]||ENV["HOMEPATH"]||".",
59
+ FILE_HISTORY)
60
+ open(iface.histfile, 'w') do |file|
61
+ Readline::HISTORY.to_a.last(iface.history_length).each do |line|
62
+ file.puts line unless line.strip.empty?
63
+ end if defined?(iface.history_save) and iface.history_save
64
+ end rescue nil
65
+ end
66
+ public :save_history
67
+ end
68
+
69
+ def readline(prompt, hist)
70
+ Readline::readline(prompt, hist)
71
+ rescue Interrupt
72
+ print "^C\n"
73
+ retry
74
+ end
75
+ rescue LoadError
76
+ def readline(prompt, hist)
77
+ @histfile = ''
78
+ @hist_save = false
79
+ STDOUT.print prompt
80
+ STDOUT.flush
81
+ line = STDIN.gets
82
+ exit unless line
83
+ line.chomp!
84
+ line
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,55 @@
1
+ module Byebug
2
+ class RemoteInterface < Interface
3
+ attr_accessor :command_queue, :history_length, :history_save, :histfile
4
+ attr_accessor :restart_file
5
+
6
+ def initialize(socket)
7
+ @command_queue = []
8
+ @socket = socket
9
+ @history_save = false
10
+ @history_length = 256
11
+ @histfile = ''
12
+ # Do we read the histfile?
13
+ # open(@histfile, 'r') do |file|
14
+ # file.each do |line|
15
+ # line.chomp!
16
+ # Readline::HISTORY << line
17
+ # end
18
+ # end if File.exist?(@histfile)
19
+ @restart_file = nil
20
+ end
21
+
22
+ def close
23
+ @socket.close
24
+ rescue Exception
25
+ end
26
+
27
+ def confirm(prompt)
28
+ send_command "CONFIRM #{prompt}"
29
+ end
30
+
31
+ def finalize
32
+ end
33
+
34
+ def read_command(prompt)
35
+ send_command "PROMPT #{prompt}"
36
+ end
37
+
38
+ def readline_support?
39
+ false
40
+ end
41
+
42
+ def print(*args)
43
+ @socket.printf(escape(format(*args)))
44
+ end
45
+
46
+ private
47
+
48
+ def send_command(msg)
49
+ @socket.puts msg
50
+ result = @socket.gets
51
+ raise IOError unless result
52
+ result.chomp
53
+ end
54
+ end
55
+ end