debug 1.0.0.alpha1 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +20 -19
- data/README.md +353 -51
- data/Rakefile +21 -1
- data/debug.gemspec +6 -11
- data/exe/rdbg +32 -1
- data/ext/debug/debug.c +118 -0
- data/ext/debug/extconf.rb +2 -0
- data/ext/debug/iseq_collector.c +91 -0
- data/lib/debug.rb +1 -1
- data/lib/debug/breakpoint.rb +310 -36
- data/lib/debug/client.rb +4 -11
- data/lib/debug/config.rb +100 -7
- data/lib/debug/console.rb +89 -0
- data/lib/debug/open.rb +10 -0
- data/lib/debug/run.rb +2 -0
- data/lib/debug/server.rb +128 -21
- data/lib/debug/session.rb +605 -170
- data/lib/debug/source_repository.rb +27 -20
- data/lib/debug/thread_client.rb +294 -119
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +325 -0
- metadata +22 -42
- data/lib/debug/repl.rb +0 -69
- data/lib/debug/tcpserver.rb +0 -22
- data/lib/debug/unixserver.rb +0 -18
@@ -1,20 +1,27 @@
|
|
1
|
-
module DEBUGGER__
|
2
|
-
class SourceRepository
|
3
|
-
def initialize
|
4
|
-
@files = {} # filename => [src, iseq]
|
5
|
-
end
|
6
|
-
|
7
|
-
def add iseq, src
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
module DEBUGGER__
|
2
|
+
class SourceRepository
|
3
|
+
def initialize
|
4
|
+
@files = {} # filename => [src, iseq]
|
5
|
+
end
|
6
|
+
|
7
|
+
def add iseq, src
|
8
|
+
path = iseq.absolute_path
|
9
|
+
path = '-e' if iseq.path == '-e'
|
10
|
+
|
11
|
+
case
|
12
|
+
when path = iseq.absolute_path
|
13
|
+
src = File.read(path)
|
14
|
+
when iseq.path == '-e'
|
15
|
+
path = '-e'
|
16
|
+
else
|
17
|
+
src = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
@files[path] = src.lines if src
|
21
|
+
end
|
22
|
+
|
23
|
+
def get path
|
24
|
+
@files[path]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/debug/thread_client.rb
CHANGED
@@ -1,25 +1,31 @@
|
|
1
|
+
require 'objspace'
|
2
|
+
require 'pp'
|
3
|
+
|
1
4
|
module DEBUGGER__
|
2
5
|
class ThreadClient
|
3
6
|
def self.current
|
4
7
|
Thread.current[:DEBUGGER__ThreadClient] || begin
|
5
|
-
tc = SESSION.thread_client
|
8
|
+
tc = ::DEBUGGER__::SESSION.thread_client
|
6
9
|
Thread.current[:DEBUGGER__ThreadClient] = tc
|
7
10
|
end
|
8
11
|
end
|
9
12
|
|
10
|
-
attr_reader :location, :thread
|
13
|
+
attr_reader :location, :thread, :mode, :id
|
11
14
|
|
12
|
-
def initialize q_evt, q_cmd, thr = Thread.current
|
15
|
+
def initialize id, q_evt, q_cmd, thr = Thread.current
|
16
|
+
@id = id
|
13
17
|
@thread = thr
|
14
18
|
@q_evt = q_evt
|
15
19
|
@q_cmd = q_cmd
|
16
20
|
@step_tp = nil
|
17
21
|
@output = []
|
18
|
-
@
|
22
|
+
@src_lines_on_stop = (DEBUGGER__::CONFIG[:show_src_lines] || 10).to_i
|
23
|
+
@show_frames_on_stop = (DEBUGGER__::CONFIG[:show_frames] || 2).to_i
|
24
|
+
set_mode nil
|
19
25
|
end
|
20
26
|
|
21
27
|
def inspect
|
22
|
-
"#<
|
28
|
+
"#<DBG:TC #{self.id}:#{self.mode}@#{@thread.backtrace[-1]}>"
|
23
29
|
end
|
24
30
|
|
25
31
|
def puts str = ''
|
@@ -44,11 +50,11 @@ module DEBUGGER__
|
|
44
50
|
|
45
51
|
## events
|
46
52
|
|
47
|
-
def on_trap
|
48
|
-
if
|
49
|
-
raise Interrupt
|
53
|
+
def on_trap sig
|
54
|
+
if self.mode == :wait_next_action
|
55
|
+
# raise Interrupt
|
50
56
|
else
|
51
|
-
on_suspend :trap
|
57
|
+
on_suspend :trap, sig: sig
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
@@ -56,18 +62,24 @@ module DEBUGGER__
|
|
56
62
|
on_suspend :pause
|
57
63
|
end
|
58
64
|
|
65
|
+
def on_thread_begin th
|
66
|
+
event! :thread_begin, th
|
67
|
+
wait_next_action
|
68
|
+
end
|
69
|
+
|
59
70
|
def on_load iseq, eval_src
|
60
71
|
event! :load, iseq, eval_src
|
61
72
|
wait_next_action
|
62
73
|
end
|
63
74
|
|
64
|
-
def on_breakpoint tp
|
65
|
-
on_suspend tp.event, tp
|
75
|
+
def on_breakpoint tp, bp
|
76
|
+
on_suspend tp.event, tp, bp: bp
|
66
77
|
end
|
67
78
|
|
68
|
-
def on_suspend event, tp = nil
|
79
|
+
def on_suspend event, tp = nil, bp: nil, sig: nil
|
69
80
|
@current_frame_index = 0
|
70
|
-
@target_frames =
|
81
|
+
@target_frames = DEBUGGER__.capture_frames __dir__
|
82
|
+
|
71
83
|
cf = @target_frames.first
|
72
84
|
if cf
|
73
85
|
@location = cf.location
|
@@ -79,85 +91,140 @@ module DEBUGGER__
|
|
79
91
|
end
|
80
92
|
|
81
93
|
if event != :pause
|
82
|
-
show_src
|
83
|
-
|
84
|
-
|
94
|
+
show_src max_lines: @src_lines_on_stop
|
95
|
+
show_frames @show_frames_on_stop
|
96
|
+
|
97
|
+
if bp
|
98
|
+
event! :suspend, :breakpoint, bp.key
|
99
|
+
elsif sig
|
100
|
+
event! :suspend, :trap, sig
|
101
|
+
else
|
102
|
+
event! :suspend, event
|
103
|
+
end
|
85
104
|
end
|
86
105
|
|
87
106
|
wait_next_action
|
88
107
|
end
|
89
|
-
|
108
|
+
|
90
109
|
## control all
|
91
110
|
|
111
|
+
begin
|
112
|
+
TracePoint.new(:raise){}.enable(target_thread: Thread.current)
|
113
|
+
SUPPORT_TARGET_THREAD = true
|
114
|
+
rescue ArgumentError
|
115
|
+
SUPPORT_TARGET_THREAD = false
|
116
|
+
end
|
117
|
+
|
92
118
|
def step_tp
|
93
119
|
@step_tp.disable if @step_tp
|
94
|
-
@step_tp = TracePoint.new(:line, :b_return, :return){|tp|
|
95
|
-
next if SESSION.break? tp.path, tp.lineno
|
96
|
-
next if !yield
|
97
|
-
tp.disable
|
98
|
-
on_suspend tp.event, tp
|
99
|
-
}
|
100
|
-
|
101
|
-
@step_tp.enable(target_thread: Thread.current)
|
102
|
-
end
|
103
|
-
|
104
|
-
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :has_return_value, :return_value)
|
105
|
-
|
106
|
-
def target_frames
|
107
|
-
RubyVM::DebugInspector.open{|dc|
|
108
|
-
locs = dc.backtrace_locations
|
109
|
-
locs.map.with_index{|e, i|
|
110
|
-
unless File.dirname(e.path) == File.dirname(__FILE__)
|
111
|
-
FrameInfo.new(
|
112
|
-
e,
|
113
|
-
dc.frame_self(i),
|
114
|
-
dc.frame_binding(i),
|
115
|
-
dc.frame_iseq(i),
|
116
|
-
dc.frame_class(i))
|
117
|
-
end
|
118
|
-
}.compact
|
119
|
-
}
|
120
|
-
end
|
121
120
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
121
|
+
thread = Thread.current
|
122
|
+
|
123
|
+
if SUPPORT_TARGET_THREAD
|
124
|
+
@step_tp = TracePoint.new(:line, :b_return, :return){|tp|
|
125
|
+
next if SESSION.break? tp.path, tp.lineno
|
126
|
+
next if !yield
|
127
|
+
next if tp.path.start_with?(__dir__)
|
128
|
+
tp.disable
|
129
|
+
on_suspend tp.event, tp
|
130
|
+
}
|
131
|
+
@step_tp.enable(target_thread: thread)
|
132
|
+
else
|
133
|
+
@step_tp = TracePoint.new(:line, :b_return, :return){|tp|
|
134
|
+
next if thread != Thread.current
|
135
|
+
next if SESSION.break? tp.path, tp.lineno
|
136
|
+
next if !yield
|
137
|
+
tp.disable
|
138
|
+
on_suspend tp.event, tp
|
127
139
|
}
|
128
|
-
|
140
|
+
@step_tp.enable
|
141
|
+
end
|
129
142
|
end
|
130
143
|
|
131
144
|
def current_frame
|
132
|
-
@target_frames
|
145
|
+
if @target_frames
|
146
|
+
@target_frames[@current_frame_index]
|
147
|
+
else
|
148
|
+
nil
|
149
|
+
end
|
133
150
|
end
|
134
151
|
|
135
152
|
def file_lines path
|
136
|
-
if (
|
137
|
-
|
153
|
+
if (src_lines = SESSION.source(path))
|
154
|
+
src_lines
|
138
155
|
elsif File.exist?(path)
|
139
156
|
File.readlines(path)
|
140
157
|
end
|
141
158
|
end
|
142
159
|
|
143
|
-
def show_src
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
160
|
+
def show_src(frame_index: @current_frame_index,
|
161
|
+
update_line: false,
|
162
|
+
max_lines: 10,
|
163
|
+
start_line: nil,
|
164
|
+
end_line: nil,
|
165
|
+
dir: +1)
|
166
|
+
#
|
167
|
+
if @target_frames && frame = @target_frames[frame_index]
|
168
|
+
if file_lines = file_lines(path = frame.location.path)
|
169
|
+
frame_line = frame.location.lineno - 1
|
170
|
+
|
171
|
+
lines = file_lines.map.with_index do |e, i|
|
172
|
+
if i == frame_line
|
150
173
|
"=> #{'%4d' % (i+1)}| #{e}"
|
151
174
|
else
|
152
175
|
" #{'%4d' % (i+1)}| #{e}"
|
153
176
|
end
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
177
|
+
end
|
178
|
+
|
179
|
+
unless start_line
|
180
|
+
if frame.show_line
|
181
|
+
if dir > 0
|
182
|
+
start_line = frame.show_line
|
183
|
+
else
|
184
|
+
end_line = frame.show_line - max_lines
|
185
|
+
start_line = [end_line - max_lines, 0].max
|
186
|
+
end
|
187
|
+
else
|
188
|
+
start_line = [frame_line - max_lines/2, 0].max
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
unless end_line
|
193
|
+
end_line = [start_line + max_lines, lines.size].min
|
194
|
+
end
|
195
|
+
|
196
|
+
if update_line
|
197
|
+
frame.show_line = end_line
|
198
|
+
end
|
199
|
+
|
200
|
+
if start_line != end_line
|
201
|
+
puts "[#{start_line+1}, #{end_line}] in #{path}" unless update_line
|
202
|
+
puts lines[start_line ... end_line]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def show_by_editor path = nil
|
209
|
+
unless path
|
210
|
+
if @target_frames && frame = @target_frames[@current_frame_index]
|
211
|
+
path = frame.location.path
|
212
|
+
else
|
213
|
+
return # can't get path
|
159
214
|
end
|
160
215
|
end
|
216
|
+
|
217
|
+
if File.exist?(path)
|
218
|
+
if editor = (ENV['RUBY_DEBUG_EDITOR'] || ENV['EDITOR'])
|
219
|
+
puts "command: #{editor}"
|
220
|
+
puts " path: #{path}"
|
221
|
+
system(editor, path)
|
222
|
+
else
|
223
|
+
puts "can not find editor setting: ENV['RUBY_DEBUG_EDITOR'] or ENV['EDITOR']"
|
224
|
+
end
|
225
|
+
else
|
226
|
+
puts "Can not find file: #{path}"
|
227
|
+
end
|
161
228
|
end
|
162
229
|
|
163
230
|
def show_locals
|
@@ -176,39 +243,48 @@ module DEBUGGER__
|
|
176
243
|
|
177
244
|
def show_ivars
|
178
245
|
if s = current_frame&.self
|
179
|
-
|
180
|
-
s.instance_variables.eaach{|iv|
|
246
|
+
s.instance_variables.each{|iv|
|
181
247
|
puts " #{iv} => #{s.instance_variable_get(iv)}"
|
182
248
|
}
|
183
249
|
end
|
184
250
|
end
|
185
251
|
|
186
|
-
def frame_eval src,
|
252
|
+
def frame_eval src, re_raise: false
|
187
253
|
begin
|
254
|
+
@success_last_eval = false
|
255
|
+
|
188
256
|
b = current_frame.binding
|
189
|
-
if b
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
257
|
+
result = if b
|
258
|
+
f, l = b.source_location
|
259
|
+
b.eval(src, "(rdbg)/#{f}")
|
260
|
+
else
|
261
|
+
frame_self = current_frame.self
|
262
|
+
frame_self.instance_eval(src)
|
263
|
+
end
|
264
|
+
@success_last_eval = true
|
265
|
+
result
|
266
|
+
|
196
267
|
rescue Exception => e
|
197
|
-
return
|
268
|
+
return yield(e) if block_given?
|
269
|
+
|
270
|
+
puts "eval error: #{e}"
|
198
271
|
|
199
|
-
puts "Error: #{e}"
|
200
272
|
e.backtrace_locations.each do |loc|
|
201
273
|
break if loc.path == __FILE__
|
202
274
|
puts " #{loc}"
|
203
275
|
end
|
204
|
-
|
276
|
+
raise if re_raise
|
205
277
|
end
|
206
278
|
end
|
207
279
|
|
208
280
|
def parameters_info b, vars
|
209
281
|
vars.map{|var|
|
210
|
-
|
211
|
-
|
282
|
+
begin
|
283
|
+
"#{var}=#{short_inspect(b.local_variable_get(var))}"
|
284
|
+
rescue NameError, TypeError
|
285
|
+
nil
|
286
|
+
end
|
287
|
+
}.compact.join(', ')
|
212
288
|
end
|
213
289
|
|
214
290
|
def klass_sig frame
|
@@ -246,13 +322,12 @@ module DEBUGGER__
|
|
246
322
|
if b && (iseq = frame.iseq)
|
247
323
|
if iseq.type == :block
|
248
324
|
if (argc = iseq.argc) > 0
|
249
|
-
args = parameters_info b, iseq.locals[0...
|
325
|
+
args = parameters_info b, iseq.locals[0...argc]
|
250
326
|
buff << " {|#{args}|}"
|
251
327
|
end
|
252
328
|
else
|
253
|
-
callee = b.eval('__callee__')
|
254
|
-
|
255
|
-
args = parameters_info b, m.parameters.map{|type, v| v}
|
329
|
+
if (callee = b.eval('__callee__', __FILE__, __LINE__)) && (argc = iseq.argc) > 0
|
330
|
+
args = parameters_info b, iseq.locals[0...argc]
|
256
331
|
ksig = klass_sig frame
|
257
332
|
buff << " #{ksig}#{callee}(#{args})"
|
258
333
|
end
|
@@ -268,30 +343,67 @@ module DEBUGGER__
|
|
268
343
|
buff
|
269
344
|
end
|
270
345
|
|
271
|
-
def
|
272
|
-
@target_frames
|
273
|
-
|
274
|
-
|
346
|
+
def show_frames max = (@target_frames || []).size
|
347
|
+
if max > 0 && frames = @target_frames
|
348
|
+
size = @target_frames.size
|
349
|
+
max += 1 if size == max + 1
|
350
|
+
max.times{|i|
|
351
|
+
break if i >= size
|
352
|
+
puts frame_str(i)
|
353
|
+
}
|
354
|
+
puts " # and #{size - max} frames (use `bt' command for all frames)" if max < size
|
355
|
+
end
|
275
356
|
end
|
276
357
|
|
277
|
-
def
|
358
|
+
def show_frame i=0
|
278
359
|
puts frame_str(i)
|
279
360
|
end
|
280
361
|
|
281
|
-
def
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
362
|
+
def show_object_info expr
|
363
|
+
begin
|
364
|
+
result = frame_eval(expr, re_raise: true)
|
365
|
+
rescue Exception
|
366
|
+
# ignore
|
367
|
+
else
|
368
|
+
klass = ObjectSpace.internal_class_of(result)
|
369
|
+
exists = []
|
370
|
+
klass.ancestors.each{|k|
|
371
|
+
puts "= #{k}"
|
372
|
+
if (ms = (k.instance_methods(false) - exists)).size > 0
|
373
|
+
puts ms.sort.join("\t")
|
374
|
+
exists |= ms
|
375
|
+
end
|
376
|
+
}
|
288
377
|
end
|
289
378
|
end
|
290
379
|
|
380
|
+
def add_breakpoint args
|
381
|
+
case args.first
|
382
|
+
when :method
|
383
|
+
klass_name, op, method_name, cond = args[1..]
|
384
|
+
bp = MethodBreakpoint.new(current_frame.binding, klass_name, op, method_name, cond)
|
385
|
+
begin
|
386
|
+
bp.enable
|
387
|
+
rescue Exception => e
|
388
|
+
puts e.message
|
389
|
+
::DEBUGGER__::METHOD_ADDED_TRACKER.enable
|
390
|
+
end
|
391
|
+
event! :result, :method_breakpoint, bp
|
392
|
+
else
|
393
|
+
raise "unknown breakpoint: #{args}"
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def set_mode mode
|
398
|
+
@mode = mode
|
399
|
+
end
|
400
|
+
|
291
401
|
def wait_next_action
|
292
|
-
|
402
|
+
set_mode :wait_next_action
|
293
403
|
|
294
404
|
while cmds = @q_cmd.pop
|
405
|
+
# pp [self, cmds: cmds]
|
406
|
+
|
295
407
|
cmd, *args = *cmds
|
296
408
|
|
297
409
|
case cmd
|
@@ -303,20 +415,43 @@ module DEBUGGER__
|
|
303
415
|
when :in
|
304
416
|
step_tp{true}
|
305
417
|
when :next
|
306
|
-
|
418
|
+
frame = @target_frames.first
|
419
|
+
path = frame.location.absolute_path || "!eval:#{frame.location.path}"
|
420
|
+
line = frame.location.lineno
|
421
|
+
frame.iseq.traceable_lines_norec(lines = {})
|
422
|
+
next_line = lines.keys.bsearch{|e| e > line}
|
423
|
+
if !next_line && (last_line = frame.iseq.last_line) > line
|
424
|
+
next_line = last_line
|
425
|
+
end
|
426
|
+
depth = @target_frames.first.frame_depth
|
427
|
+
|
307
428
|
step_tp{
|
308
|
-
|
429
|
+
loc = caller_locations(2, 1).first
|
430
|
+
loc_path = loc.absolute_path || "!eval:#{loc.path}"
|
431
|
+
|
432
|
+
(next_line && loc_path == path &&
|
433
|
+
(loc_lineno = loc.lineno) > line && loc_lineno <= next_line) ||
|
434
|
+
(DEBUGGER__.frame_depth - 3 < depth)
|
309
435
|
}
|
310
436
|
when :finish
|
311
|
-
|
312
|
-
step_tp{
|
437
|
+
depth = @target_frames.first.frame_depth
|
438
|
+
step_tp{
|
439
|
+
# 3 is debugger's frame count
|
440
|
+
DEBUGGER__.frame_depth - 3 < depth
|
441
|
+
}
|
313
442
|
else
|
314
443
|
raise
|
315
444
|
end
|
316
445
|
break
|
317
446
|
when :eval
|
318
447
|
eval_type, eval_src = *args
|
319
|
-
|
448
|
+
|
449
|
+
case eval_type
|
450
|
+
when :display, :try_display
|
451
|
+
else
|
452
|
+
result = frame_eval(eval_src)
|
453
|
+
end
|
454
|
+
result_type = nil
|
320
455
|
|
321
456
|
case eval_type
|
322
457
|
when :p
|
@@ -327,15 +462,31 @@ module DEBUGGER__
|
|
327
462
|
puts out
|
328
463
|
when :call
|
329
464
|
result = frame_eval(eval_src)
|
330
|
-
when :display
|
465
|
+
when :display, :try_display
|
466
|
+
failed_results = []
|
331
467
|
eval_src.each_with_index{|src, i|
|
332
|
-
|
468
|
+
result = frame_eval(src){|e|
|
469
|
+
failed_results << [i, e.message]
|
470
|
+
"<error: #{e.message}>"
|
471
|
+
}
|
472
|
+
puts "#{i}: #{src} = #{result}"
|
333
473
|
}
|
334
|
-
|
474
|
+
|
475
|
+
result_type = eval_type
|
476
|
+
result = failed_results
|
477
|
+
when :watch
|
478
|
+
if @success_last_eval
|
479
|
+
puts "#{eval_src} = #{result}"
|
480
|
+
result = WatchExprBreakpoint.new(eval_src, result)
|
481
|
+
result_type = :watch
|
482
|
+
else
|
483
|
+
result = nil
|
484
|
+
end
|
335
485
|
else
|
336
|
-
raise "unknown error option: #{args.
|
486
|
+
raise "unknown error option: #{args.inspect}"
|
337
487
|
end
|
338
|
-
|
488
|
+
|
489
|
+
event! :result, result_type, result
|
339
490
|
when :frame
|
340
491
|
type, arg = *args
|
341
492
|
case type
|
@@ -343,13 +494,13 @@ module DEBUGGER__
|
|
343
494
|
if @current_frame_index + 1 < @target_frames.size
|
344
495
|
@current_frame_index += 1
|
345
496
|
show_src max_lines: 1
|
346
|
-
|
497
|
+
show_frame(@current_frame_index)
|
347
498
|
end
|
348
499
|
when :down
|
349
500
|
if @current_frame_index > 0
|
350
501
|
@current_frame_index -= 1
|
351
502
|
show_src max_lines: 1
|
352
|
-
|
503
|
+
show_frame(@current_frame_index)
|
353
504
|
end
|
354
505
|
when :set
|
355
506
|
if arg
|
@@ -361,28 +512,43 @@ module DEBUGGER__
|
|
361
512
|
end
|
362
513
|
end
|
363
514
|
show_src max_lines: 1
|
364
|
-
|
515
|
+
show_frame(@current_frame_index)
|
365
516
|
else
|
366
517
|
raise "unsupported frame operation: #{arg.inspect}"
|
367
518
|
end
|
368
519
|
event! :result, nil
|
369
520
|
when :show
|
370
|
-
type
|
521
|
+
type = args.shift
|
522
|
+
|
371
523
|
case type
|
372
524
|
when :backtrace
|
373
|
-
|
525
|
+
show_frames
|
526
|
+
|
374
527
|
when :list
|
375
|
-
show_src
|
376
|
-
|
528
|
+
show_src(update_line: true, **(args.first || {}))
|
529
|
+
|
530
|
+
when :edit
|
531
|
+
show_by_editor(args.first)
|
532
|
+
|
533
|
+
when :local
|
534
|
+
show_frame
|
377
535
|
show_locals
|
378
|
-
when :ivars
|
379
536
|
show_ivars
|
537
|
+
|
538
|
+
when :object_info
|
539
|
+
expr = args.shift
|
540
|
+
show_object_info expr
|
541
|
+
|
380
542
|
else
|
381
|
-
raise "unknown show param: " + args.inspect
|
543
|
+
raise "unknown show param: " + [type, *args].inspect
|
382
544
|
end
|
545
|
+
|
383
546
|
event! :result, nil
|
547
|
+
|
548
|
+
when :breakpoint
|
549
|
+
add_breakpoint args
|
384
550
|
else
|
385
|
-
raise [
|
551
|
+
raise [cmd, *args].inspect
|
386
552
|
end
|
387
553
|
end
|
388
554
|
|
@@ -392,11 +558,20 @@ module DEBUGGER__
|
|
392
558
|
pp [__FILE__, __LINE__, e, e.backtrace]
|
393
559
|
raise
|
394
560
|
ensure
|
395
|
-
|
561
|
+
set_mode nil
|
396
562
|
end
|
397
563
|
|
398
564
|
def to_s
|
399
|
-
|
565
|
+
loc = current_frame&.location
|
566
|
+
|
567
|
+
if loc
|
568
|
+
str = "(#{@thread.name || @thread.status})@#{loc}"
|
569
|
+
else
|
570
|
+
str = "(#{@thread.name || @thread.status})@#{@thread.to_s}"
|
571
|
+
end
|
572
|
+
|
573
|
+
str += " (not under control)" unless self.mode
|
574
|
+
str
|
400
575
|
end
|
401
576
|
end
|
402
577
|
end
|