debug 1.0.0.beta4 → 1.0.0.beta5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +1 -0
- data/CONTRIBUTING.md +48 -0
- data/Gemfile +1 -1
- data/README.md +72 -37
- data/debug.gemspec +2 -0
- data/exe/rdbg +8 -1
- data/ext/debug/debug.c +9 -8
- data/lib/debug/breakpoint.rb +71 -24
- data/lib/debug/client.rb +49 -6
- data/lib/debug/color.rb +70 -0
- data/lib/debug/config.rb +39 -5
- data/lib/debug/console.rb +8 -1
- data/lib/debug/frame_info.rb +61 -30
- data/lib/debug/open.rb +2 -0
- data/lib/debug/run.rb +2 -0
- data/lib/debug/server.rb +72 -19
- data/lib/debug/server_dap.rb +605 -0
- data/lib/debug/session.rb +181 -86
- data/lib/debug/source_repository.rb +53 -33
- data/lib/debug/test_console.rb +0 -0
- data/lib/debug/thread_client.rb +91 -23
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +51 -28
- metadata +21 -3
File without changes
|
data/lib/debug/thread_client.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'objspace'
|
2
2
|
require 'pp'
|
3
|
-
|
3
|
+
|
4
4
|
require_relative 'frame_info'
|
5
|
+
require_relative 'color'
|
5
6
|
|
6
7
|
module DEBUGGER__
|
7
8
|
class ThreadClient
|
@@ -12,23 +13,46 @@ module DEBUGGER__
|
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
16
|
+
include Color
|
17
|
+
|
15
18
|
attr_reader :location, :thread, :mode, :id
|
16
19
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
str
|
22
|
-
end
|
20
|
+
def assemble_arguments(args)
|
21
|
+
args.map do |arg|
|
22
|
+
"#{colorize_cyan(arg[:name])}=#{arg[:value]}"
|
23
|
+
end.join(", ")
|
23
24
|
end
|
24
25
|
|
25
26
|
def default_frame_formatter frame
|
26
|
-
call_identifier_str =
|
27
|
-
|
27
|
+
call_identifier_str =
|
28
|
+
case frame.frame_type
|
29
|
+
when :block
|
30
|
+
level, block_loc, args = frame.block_identifier
|
31
|
+
|
32
|
+
if !args.empty?
|
33
|
+
args_str = " {|#{assemble_arguments(args)}|}"
|
34
|
+
end
|
35
|
+
|
36
|
+
"#{colorize_blue("block")}#{args_str} in #{colorize_blue(block_loc + level)}"
|
37
|
+
when :method
|
38
|
+
ci, args = frame.method_identifier
|
39
|
+
|
40
|
+
if !args.empty?
|
41
|
+
args_str = "(#{assemble_arguments(args)})"
|
42
|
+
end
|
43
|
+
|
44
|
+
"#{colorize_blue(ci)}#{args_str}"
|
45
|
+
when :c
|
46
|
+
colorize_blue(frame.c_identifier)
|
47
|
+
when :other
|
48
|
+
colorize_blue(frame.other_identifier)
|
49
|
+
end
|
50
|
+
|
51
|
+
location_str = colorize(frame.location_str, [:GREEN])
|
28
52
|
result = "#{call_identifier_str} at #{location_str}"
|
29
53
|
|
30
54
|
if return_str = frame.return_str
|
31
|
-
return_str = colorize(frame.return_str, [:MAGENTA])
|
55
|
+
return_str = colorize(frame.return_str, [:MAGENTA, :BOLD])
|
32
56
|
result += " #=> #{return_str}"
|
33
57
|
end
|
34
58
|
|
@@ -38,6 +62,7 @@ module DEBUGGER__
|
|
38
62
|
def initialize id, q_evt, q_cmd, thr = Thread.current
|
39
63
|
@id = id
|
40
64
|
@thread = thr
|
65
|
+
@target_frames = nil
|
41
66
|
@q_evt = q_evt
|
42
67
|
@q_cmd = q_cmd
|
43
68
|
@step_tp = nil
|
@@ -45,9 +70,14 @@ module DEBUGGER__
|
|
45
70
|
@src_lines_on_stop = (::DEBUGGER__::CONFIG[:show_src_lines] || 10).to_i
|
46
71
|
@show_frames_on_stop = (::DEBUGGER__::CONFIG[:show_frames] || 2).to_i
|
47
72
|
@frame_formatter = method(:default_frame_formatter)
|
73
|
+
@var_map = {} # { thread_local_var_id => obj } for DAP
|
48
74
|
set_mode nil
|
49
75
|
end
|
50
76
|
|
77
|
+
def name
|
78
|
+
"##{@id} #{@thread.name || @thread.backtrace.last}"
|
79
|
+
end
|
80
|
+
|
51
81
|
def close
|
52
82
|
@q_cmd.close
|
53
83
|
end
|
@@ -71,8 +101,14 @@ module DEBUGGER__
|
|
71
101
|
@q_cmd << req
|
72
102
|
end
|
73
103
|
|
104
|
+
def generate_info
|
105
|
+
return unless current_frame
|
106
|
+
|
107
|
+
{ location: current_frame.location_str, line: current_frame.location.lineno }
|
108
|
+
end
|
109
|
+
|
74
110
|
def event! ev, *args
|
75
|
-
@q_evt << [self, @output, ev, *args]
|
111
|
+
@q_evt << [self, @output, ev, generate_info, *args]
|
76
112
|
@output = []
|
77
113
|
end
|
78
114
|
|
@@ -116,6 +152,11 @@ module DEBUGGER__
|
|
116
152
|
cf.has_return_value = true
|
117
153
|
cf.return_value = tp.return_value
|
118
154
|
end
|
155
|
+
|
156
|
+
if CatchBreakpoint === bp
|
157
|
+
cf.has_raised_exception = true
|
158
|
+
cf.raised_exception = bp.last_exc
|
159
|
+
end
|
119
160
|
end
|
120
161
|
|
121
162
|
if event != :pause
|
@@ -187,7 +228,6 @@ module DEBUGGER__
|
|
187
228
|
start_line: nil,
|
188
229
|
end_line: nil,
|
189
230
|
dir: +1)
|
190
|
-
|
191
231
|
if @target_frames && frame = @target_frames[frame_index]
|
192
232
|
if file_lines = frame.file_lines
|
193
233
|
frame_line = frame.location.lineno - 1
|
@@ -229,6 +269,10 @@ module DEBUGGER__
|
|
229
269
|
puts "# No sourcefile available for #{frame.path}"
|
230
270
|
end
|
231
271
|
end
|
272
|
+
rescue Exception => e
|
273
|
+
p e
|
274
|
+
pp e.backtrace
|
275
|
+
exit!
|
232
276
|
end
|
233
277
|
|
234
278
|
def show_by_editor path = nil
|
@@ -255,14 +299,18 @@ module DEBUGGER__
|
|
255
299
|
|
256
300
|
def show_locals
|
257
301
|
if s = current_frame&.self
|
258
|
-
puts " %self => #{s}"
|
302
|
+
puts " #{colorize_cyan("%self")} => #{colored_inspect(s)}"
|
259
303
|
end
|
260
304
|
if current_frame&.has_return_value
|
261
|
-
puts " %return => #{current_frame.return_value}"
|
305
|
+
puts " #{colorize_cyan("%return")} => #{colored_inspect(current_frame.return_value)}"
|
306
|
+
end
|
307
|
+
if current_frame&.has_raised_exception
|
308
|
+
puts " #{colorize_cyan("%raised")} => #{colored_inspect(current_frame.raised_exception)}"
|
262
309
|
end
|
263
310
|
if b = current_frame&.binding
|
264
311
|
b.local_variables.each{|loc|
|
265
|
-
|
312
|
+
value = b.local_variable_get(loc)
|
313
|
+
puts " #{colorize_cyan(loc)} => #{colored_inspect(value)}"
|
266
314
|
}
|
267
315
|
end
|
268
316
|
end
|
@@ -270,7 +318,8 @@ module DEBUGGER__
|
|
270
318
|
def show_ivars
|
271
319
|
if s = current_frame&.self
|
272
320
|
s.instance_variables.each{|iv|
|
273
|
-
|
321
|
+
value = s.instance_variable_get(iv)
|
322
|
+
puts " #{colorize_cyan(iv)} => #{colored_inspect(value)}"
|
274
323
|
}
|
275
324
|
end
|
276
325
|
end
|
@@ -281,7 +330,7 @@ module DEBUGGER__
|
|
281
330
|
|
282
331
|
b = current_frame.binding
|
283
332
|
result = if b
|
284
|
-
f,
|
333
|
+
f, _l = b.source_location
|
285
334
|
b.eval(src, "(rdbg)/#{f}")
|
286
335
|
else
|
287
336
|
frame_self = current_frame.self
|
@@ -312,7 +361,7 @@ module DEBUGGER__
|
|
312
361
|
end
|
313
362
|
|
314
363
|
def show_frames max = (@target_frames || []).size
|
315
|
-
if max > 0 &&
|
364
|
+
if max > 0 && @target_frames
|
316
365
|
size = @target_frames.size
|
317
366
|
max += 1 if size == max + 1
|
318
367
|
max.times{|i|
|
@@ -369,6 +418,8 @@ module DEBUGGER__
|
|
369
418
|
def wait_next_action
|
370
419
|
set_mode :wait_next_action
|
371
420
|
|
421
|
+
SESSION.check_forked
|
422
|
+
|
372
423
|
while cmds = @q_cmd.pop
|
373
424
|
# pp [self, cmds: cmds]
|
374
425
|
|
@@ -397,9 +448,13 @@ module DEBUGGER__
|
|
397
448
|
loc = caller_locations(2, 1).first
|
398
449
|
loc_path = loc.absolute_path || "!eval:#{loc.path}"
|
399
450
|
|
451
|
+
# same stack depth
|
452
|
+
(DEBUGGER__.frame_depth - 3 <= depth) ||
|
453
|
+
|
454
|
+
# different frame
|
400
455
|
(next_line && loc_path == path &&
|
401
|
-
|
402
|
-
|
456
|
+
(loc_lineno = loc.lineno) > line &&
|
457
|
+
loc_lineno <= next_line)
|
403
458
|
}
|
404
459
|
when :finish
|
405
460
|
depth = @target_frames.first.frame_depth
|
@@ -426,7 +481,7 @@ module DEBUGGER__
|
|
426
481
|
puts "=> " + result.inspect
|
427
482
|
when :pp
|
428
483
|
puts "=> "
|
429
|
-
PP.pp(result, out = ''.dup)
|
484
|
+
PP.pp(result, out = ''.dup, SESSION.width)
|
430
485
|
puts out
|
431
486
|
when :call
|
432
487
|
result = frame_eval(eval_src)
|
@@ -444,8 +499,17 @@ module DEBUGGER__
|
|
444
499
|
result = failed_results
|
445
500
|
when :watch
|
446
501
|
if @success_last_eval
|
447
|
-
|
448
|
-
|
502
|
+
if eval_src.match?(/@\w+/)
|
503
|
+
object =
|
504
|
+
if b = current_frame.binding
|
505
|
+
b.receiver
|
506
|
+
else
|
507
|
+
current_frame.self
|
508
|
+
end
|
509
|
+
puts "#{object} #{eval_src} = #{result}"
|
510
|
+
result = WatchIVarBreakpoint.new(eval_src, object, result)
|
511
|
+
end
|
512
|
+
|
449
513
|
result_type = :watch
|
450
514
|
else
|
451
515
|
result = nil
|
@@ -515,6 +579,10 @@ module DEBUGGER__
|
|
515
579
|
|
516
580
|
when :breakpoint
|
517
581
|
add_breakpoint args
|
582
|
+
|
583
|
+
when :dap
|
584
|
+
process_dap args
|
585
|
+
|
518
586
|
else
|
519
587
|
raise [cmd, *args].inspect
|
520
588
|
end
|
data/lib/debug/version.rb
CHANGED
data/misc/README.md.erb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[![Ruby](https://github.com/ruby/debug/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster)
|
2
|
+
|
1
3
|
# debug.rb
|
2
4
|
|
3
5
|
This library provides debugging functionality to Ruby.
|
@@ -49,28 +51,33 @@ To use debugging feature, you can have 3 ways.
|
|
49
51
|
|
50
52
|
### Local debug console
|
51
53
|
|
54
|
+
#### (1) Use `rdbg` command
|
55
|
+
|
52
56
|
```
|
53
|
-
# (1) Use `rdbg` command
|
54
57
|
$ rdbg target.rb
|
55
58
|
$ rdbg -- -r foo -e expr # -- is required to make clear rdbg options and ruby's options
|
59
|
+
```
|
56
60
|
|
57
|
-
|
61
|
+
#### (2) Use `-r debug/run` command line option
|
58
62
|
|
63
|
+
```
|
59
64
|
$ ruby -r debug/run target.rb
|
65
|
+
```
|
60
66
|
|
61
|
-
|
67
|
+
#### (3) Write `require 'debug...'` in .rb files
|
62
68
|
|
63
|
-
|
69
|
+
```ruby
|
70
|
+
# target.rb
|
64
71
|
require 'debug/run' # start the debug console
|
65
|
-
... rest of program ...
|
66
72
|
|
67
73
|
# or
|
68
74
|
|
69
|
-
$ cat target.rb
|
70
75
|
require 'debug/session' # introduce the functionality
|
71
76
|
DEBUGGER__.console # and start the debug console
|
72
|
-
... rest of program ...
|
77
|
+
# ... rest of program ...
|
78
|
+
```
|
73
79
|
|
80
|
+
```
|
74
81
|
$ ruby target.rb
|
75
82
|
```
|
76
83
|
|
@@ -144,33 +151,36 @@ $ rdbg ~/src/rb/target.rb
|
|
144
151
|
|
145
152
|
### Remote debug (1) UNIX domain socket
|
146
153
|
|
154
|
+
#### (1) Use `rdbg` command
|
155
|
+
|
147
156
|
```
|
148
|
-
# (1) Use `rdbg` command
|
149
157
|
$ rdbg --open target.rb # or rdbg -O target.rb for shorthand
|
150
158
|
Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
|
151
|
-
|
159
|
+
```
|
152
160
|
|
153
|
-
|
161
|
+
#### (2) Use `-r debug/open` command line option
|
154
162
|
|
163
|
+
```
|
155
164
|
$ ruby -r debug/open target.rb
|
156
165
|
Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
|
157
|
-
|
166
|
+
```
|
167
|
+
|
168
|
+
#### (3) Write `require 'debug/open'` in .rb files
|
158
169
|
|
159
|
-
|
160
|
-
|
170
|
+
```ruby
|
171
|
+
# target.rb
|
161
172
|
require 'debug/open' # open the debugger entry point by UNIX domain socket.
|
162
|
-
...
|
163
173
|
|
164
174
|
# or
|
165
175
|
|
166
|
-
$ cat target.rb
|
167
176
|
require 'debug/server' # introduce remote debugging feature
|
168
177
|
DEBUGGER__.open # open the debugger entry point by UNIX domain socket.
|
169
178
|
# or DEBUGGER__.open_unix to specify UNIX domain socket.
|
179
|
+
```
|
170
180
|
|
181
|
+
```
|
171
182
|
$ ruby target.rb
|
172
183
|
Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
|
173
|
-
...
|
174
184
|
```
|
175
185
|
|
176
186
|
It runs target.rb and accept debugger connection within UNIX domain socket.
|
@@ -234,40 +244,49 @@ The socket file is located at
|
|
234
244
|
|
235
245
|
You can open the TCP/IP port instead of using UNIX domain socket.
|
236
246
|
|
247
|
+
#### (1) Use `rdbg` command
|
248
|
+
|
237
249
|
```
|
238
|
-
# (1) Use `rdbg` command
|
239
250
|
$ rdbg -O --port=12345 target.rb
|
240
251
|
# or
|
241
252
|
$ rdbg --open --port=12345 target.rb
|
242
253
|
Debugger can attach via TCP/IP (localhost:12345)
|
243
|
-
|
254
|
+
```
|
255
|
+
|
256
|
+
#### (2) Use `-r debug/open` command line option
|
244
257
|
|
245
|
-
# (2) Use `-r debug/open` command line option
|
246
258
|
|
259
|
+
```
|
247
260
|
$ RUBY_DEBUG_PORT=12345 ruby -r debug/open target.rb
|
248
261
|
Debugger can attach via TCP/IP (localhost:12345)
|
249
|
-
|
262
|
+
```
|
250
263
|
|
251
|
-
|
252
|
-
|
264
|
+
#### (3) Write `require 'debug/open'` in .rb files
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
# target.rb
|
253
268
|
require 'debug/open' # open the debugger entry point.
|
254
|
-
|
269
|
+
```
|
270
|
+
|
271
|
+
and run with environment variable RUBY_DEBUG_PORT
|
255
272
|
|
256
|
-
|
273
|
+
```
|
257
274
|
$ RUBY_DEBUG_PORT=12345 ruby target.rb
|
258
275
|
Debugger can attach via TCP/IP (localhost:12345)
|
259
|
-
|
276
|
+
```
|
260
277
|
|
261
|
-
|
278
|
+
or
|
262
279
|
|
263
|
-
|
280
|
+
```ruby
|
281
|
+
# target.rb
|
264
282
|
require 'debug/server' # introduce remote debugging feature
|
265
283
|
DEBUGGER__.open(port: 12345)
|
266
284
|
# or DEBUGGER__.open_tcp(port: 12345)
|
285
|
+
```
|
267
286
|
|
287
|
+
```
|
268
288
|
$ ruby target.rb
|
269
289
|
Debugger can attach via TCP/IP (localhost:12345)
|
270
|
-
...
|
271
290
|
```
|
272
291
|
|
273
292
|
You can also specify the host with the `RUBY_DEBUG_HOST` environment variable. And also `DEBUGGER__.open` method accepts a `host:` keyword parameter. If the host is not given, `localhost` will be used.
|
@@ -325,3 +344,7 @@ The `<...>` notation means the argument.
|
|
325
344
|
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/debug.
|
326
345
|
|
327
346
|
Please also check the [contributing guideline](/CONTRIBUTING.md).
|
347
|
+
|
348
|
+
# Acknowledgement
|
349
|
+
|
350
|
+
* Some tests are based on [deivid-rodriguez/byebug: Debugging in Ruby 2](https://github.com/deivid-rodriguez/byebug)
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Sasada
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
12
|
-
dependencies:
|
11
|
+
date: 2021-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: irb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: Debugging functionality for Ruby. This is completely rewritten debug.rb
|
14
28
|
which was contained by the encient Ruby versions.
|
15
29
|
email:
|
@@ -20,6 +34,7 @@ extensions:
|
|
20
34
|
- ext/debug/extconf.rb
|
21
35
|
extra_rdoc_files: []
|
22
36
|
files:
|
37
|
+
- ".github/workflows/ruby.yml"
|
23
38
|
- ".gitignore"
|
24
39
|
- CONTRIBUTING.md
|
25
40
|
- Gemfile
|
@@ -38,14 +53,17 @@ files:
|
|
38
53
|
- lib/debug/bp.vim
|
39
54
|
- lib/debug/breakpoint.rb
|
40
55
|
- lib/debug/client.rb
|
56
|
+
- lib/debug/color.rb
|
41
57
|
- lib/debug/config.rb
|
42
58
|
- lib/debug/console.rb
|
43
59
|
- lib/debug/frame_info.rb
|
44
60
|
- lib/debug/open.rb
|
45
61
|
- lib/debug/run.rb
|
46
62
|
- lib/debug/server.rb
|
63
|
+
- lib/debug/server_dap.rb
|
47
64
|
- lib/debug/session.rb
|
48
65
|
- lib/debug/source_repository.rb
|
66
|
+
- lib/debug/test_console.rb
|
49
67
|
- lib/debug/thread_client.rb
|
50
68
|
- lib/debug/version.rb
|
51
69
|
- misc/README.md.erb
|