debug 1.3.4 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +234 -9
- data/Gemfile +1 -0
- data/README.md +81 -31
- data/Rakefile +28 -10
- data/debug.gemspec +7 -5
- data/exe/rdbg +7 -3
- data/ext/debug/debug.c +80 -15
- data/ext/debug/extconf.rb +22 -0
- data/lib/debug/breakpoint.rb +141 -67
- data/lib/debug/client.rb +77 -20
- data/lib/debug/color.rb +29 -19
- data/lib/debug/config.rb +61 -27
- data/lib/debug/console.rb +59 -18
- data/lib/debug/frame_info.rb +41 -40
- data/lib/debug/local.rb +1 -1
- data/lib/debug/prelude.rb +2 -2
- data/lib/debug/server.rb +136 -103
- data/lib/debug/server_cdp.rb +880 -162
- data/lib/debug/server_dap.rb +445 -164
- data/lib/debug/session.rb +540 -269
- data/lib/debug/source_repository.rb +103 -52
- data/lib/debug/thread_client.rb +306 -138
- data/lib/debug/tracer.rb +8 -13
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +44 -16
- metadata +6 -15
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -24
- data/.github/ISSUE_TEMPLATE/custom.md +0 -10
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -14
- data/.github/workflows/ruby.yml +0 -34
- data/.gitignore +0 -12
- data/bin/console +0 -14
- data/bin/gentest +0 -22
- data/bin/setup +0 -8
- data/lib/debug/bp.vim +0 -68
data/lib/debug/color.rb
CHANGED
@@ -48,33 +48,29 @@ module DEBUGGER__
|
|
48
48
|
|
49
49
|
if defined? IRB::ColorPrinter.pp
|
50
50
|
def color_pp obj, width
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
with_inspection_error_guard do
|
52
|
+
if !CONFIG[:no_color]
|
53
|
+
IRB::ColorPrinter.pp(obj, "".dup, width)
|
54
|
+
else
|
55
|
+
obj.pretty_inspect
|
56
|
+
end
|
55
57
|
end
|
56
58
|
end
|
57
59
|
else
|
58
60
|
def color_pp obj, width
|
59
|
-
|
61
|
+
with_inspection_error_guard do
|
62
|
+
obj.pretty_inspect
|
63
|
+
end
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
63
67
|
def colored_inspect obj, width: SESSION.width, no_color: false
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
err_msg = "#{ex.inspect} rescued during inspection"
|
71
|
-
string_result = obj.to_s rescue nil
|
72
|
-
|
73
|
-
# don't colorize the string here because it's not from user's application
|
74
|
-
if string_result
|
75
|
-
%Q{"#{string_result}" from #to_s because #{err_msg}}
|
76
|
-
else
|
77
|
-
err_msg
|
68
|
+
with_inspection_error_guard do
|
69
|
+
if !no_color
|
70
|
+
color_pp obj, width
|
71
|
+
else
|
72
|
+
obj.pretty_inspect
|
73
|
+
end
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
@@ -109,5 +105,19 @@ module DEBUGGER__
|
|
109
105
|
def colorize_dim(str)
|
110
106
|
colorize(str, [:DIM])
|
111
107
|
end
|
108
|
+
|
109
|
+
def with_inspection_error_guard
|
110
|
+
yield
|
111
|
+
rescue Exception => ex
|
112
|
+
err_msg = "#{ex.inspect} rescued during inspection"
|
113
|
+
string_result = obj.to_s rescue nil
|
114
|
+
|
115
|
+
# don't colorize the string here because it's not from user's application
|
116
|
+
if string_result
|
117
|
+
%Q{"#{string_result}" from #to_s because #{err_msg}}
|
118
|
+
else
|
119
|
+
err_msg
|
120
|
+
end
|
121
|
+
end
|
112
122
|
end
|
113
123
|
end
|
data/lib/debug/config.rb
CHANGED
@@ -7,60 +7,79 @@ module DEBUGGER__
|
|
7
7
|
ERROR: 2,
|
8
8
|
WARN: 3,
|
9
9
|
INFO: 4,
|
10
|
+
DEBUG: 5
|
10
11
|
}.freeze
|
11
12
|
|
12
13
|
CONFIG_SET = {
|
13
14
|
# UI setting
|
14
|
-
log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger
|
15
|
-
show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint
|
16
|
-
show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint
|
17
|
-
use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)",
|
18
|
-
no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize
|
19
|
-
no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT
|
20
|
-
no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library
|
15
|
+
log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger", :loglevel, "WARN"],
|
16
|
+
show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint", :int, "10"],
|
17
|
+
show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint", :int, "2"],
|
18
|
+
use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool, "false"],
|
19
|
+
no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize", :bool, "false"],
|
20
|
+
no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT", :bool, "false"],
|
21
|
+
no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library", :bool, "false"],
|
22
|
+
no_hint: ['RUBY_DEBUG_NO_HINT', "UI: Do not show the hint on the REPL", :bool, "false"],
|
21
23
|
|
22
24
|
# control setting
|
23
|
-
skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths
|
24
|
-
skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines
|
25
|
-
keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it
|
26
|
-
postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug
|
27
|
-
fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child)
|
28
|
-
sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal
|
25
|
+
skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths", :path],
|
26
|
+
skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines", :bool, "false"],
|
27
|
+
keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it", :bool, "false"],
|
28
|
+
postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug", :bool, "false"],
|
29
|
+
fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child)", :forkmode, "both"],
|
30
|
+
sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal", :bool, "false"],
|
29
31
|
|
30
32
|
# boot setting
|
31
|
-
nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool],
|
32
|
-
stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool],
|
33
|
+
nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool, "false"],
|
34
|
+
stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool, "false"],
|
33
35
|
init_script: ['RUBY_DEBUG_INIT_SCRIPT', "BOOT: debug command script path loaded at first stop"],
|
34
36
|
commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. commands should be separated by ';;'"],
|
35
|
-
no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool],
|
36
|
-
history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file
|
37
|
-
save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines
|
37
|
+
no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool, "false"],
|
38
|
+
history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file", :string, "~/.rdbg_history"],
|
39
|
+
save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines", :int, "10000"],
|
38
40
|
|
39
41
|
# remote setting
|
40
42
|
port: ['RUBY_DEBUG_PORT', "REMOTE: TCP/IP remote debugging: port"],
|
41
|
-
host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host
|
43
|
+
host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
|
42
44
|
sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
|
43
45
|
sock_dir: ['RUBY_DEBUG_SOCK_DIR', "REMOTE: UNIX Domain Socket remote debugging: socket directory"],
|
46
|
+
local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
|
47
|
+
skip_bp: ['RUBY_DEBUG_SKIP_BP', "REMOTE: Skip breakpoints if no clients are attached", :bool, 'false'],
|
44
48
|
cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
|
45
49
|
open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."],
|
50
|
+
chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
|
46
51
|
|
47
52
|
# obsolete
|
48
|
-
parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork
|
53
|
+
parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork", :bool, "false"],
|
49
54
|
}.freeze
|
50
55
|
|
51
|
-
CONFIG_MAP = CONFIG_SET.map{|k, (ev,
|
56
|
+
CONFIG_MAP = CONFIG_SET.map{|k, (ev, _)| [k, ev]}.to_h.freeze
|
52
57
|
|
53
58
|
class Config
|
59
|
+
@config = nil
|
60
|
+
|
54
61
|
def self.config
|
55
62
|
@config
|
56
63
|
end
|
57
64
|
|
58
65
|
def initialize argv
|
59
|
-
|
66
|
+
@skip_all = false
|
67
|
+
|
68
|
+
if self.class.config
|
60
69
|
raise 'Can not make multiple configurations in one process'
|
61
70
|
end
|
62
71
|
|
63
|
-
|
72
|
+
config = self.class.parse_argv(argv)
|
73
|
+
|
74
|
+
# apply defaults
|
75
|
+
CONFIG_SET.each do |k, config_detail|
|
76
|
+
unless config.key?(k)
|
77
|
+
default_value = config_detail[3]
|
78
|
+
config[k] = parse_config_value(k, default_value)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
update config
|
64
83
|
end
|
65
84
|
|
66
85
|
def inspect
|
@@ -75,6 +94,14 @@ module DEBUGGER__
|
|
75
94
|
set_config(key => val)
|
76
95
|
end
|
77
96
|
|
97
|
+
def skip_all
|
98
|
+
@skip_all = true
|
99
|
+
end
|
100
|
+
|
101
|
+
def skip?
|
102
|
+
@skip_all
|
103
|
+
end
|
104
|
+
|
78
105
|
def set_config(**kw)
|
79
106
|
conf = config.dup
|
80
107
|
kw.each{|k, v|
|
@@ -111,11 +138,13 @@ module DEBUGGER__
|
|
111
138
|
self.class.instance_variable_set(:@config, conf.freeze)
|
112
139
|
|
113
140
|
# Post process
|
114
|
-
if_updated old_conf, conf, :keep_alloc_site do |
|
141
|
+
if_updated old_conf, conf, :keep_alloc_site do |old, new|
|
115
142
|
if new
|
116
143
|
require 'objspace'
|
117
144
|
ObjectSpace.trace_object_allocations_start
|
118
|
-
|
145
|
+
end
|
146
|
+
|
147
|
+
if old && !new
|
119
148
|
ObjectSpace.trace_object_allocations_stop
|
120
149
|
end
|
121
150
|
end
|
@@ -212,6 +241,8 @@ module DEBUGGER__
|
|
212
241
|
e
|
213
242
|
end
|
214
243
|
}
|
244
|
+
when :path_map
|
245
|
+
valstr.split(',').map{|e| e.split(':')}
|
215
246
|
else
|
216
247
|
valstr
|
217
248
|
end
|
@@ -220,6 +251,7 @@ module DEBUGGER__
|
|
220
251
|
def self.parse_argv argv
|
221
252
|
config = {
|
222
253
|
mode: :start,
|
254
|
+
no_color: (nc = ENV['NO_COLOR']) && !nc.empty?,
|
223
255
|
}
|
224
256
|
CONFIG_MAP.each{|key, evname|
|
225
257
|
if val = ENV[evname]
|
@@ -358,6 +390,8 @@ module DEBUGGER__
|
|
358
390
|
case CONFIG_SET[key][2]
|
359
391
|
when :path
|
360
392
|
valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':')
|
393
|
+
when :path_map
|
394
|
+
valstr = config[key].map{|e| e.join(':')}.join(',')
|
361
395
|
else
|
362
396
|
valstr = config[key].to_s
|
363
397
|
end
|
@@ -425,7 +459,7 @@ module DEBUGGER__
|
|
425
459
|
end
|
426
460
|
|
427
461
|
def self.create_unix_domain_socket_name_prefix(base_dir = unix_domain_socket_dir)
|
428
|
-
user = ENV['USER'] || '
|
462
|
+
user = ENV['USER'] || 'UnknownUser'
|
429
463
|
File.join(base_dir, "ruby-debug-#{user}")
|
430
464
|
end
|
431
465
|
|
@@ -480,7 +514,7 @@ module DEBUGGER__
|
|
480
514
|
self.helps.each{|cat, cmds|
|
481
515
|
r << "### #{cat}"
|
482
516
|
r << ''
|
483
|
-
cmds.each{|
|
517
|
+
cmds.each{|_, desc|
|
484
518
|
r << desc
|
485
519
|
}
|
486
520
|
r << ''
|
data/lib/debug/console.rb
CHANGED
@@ -30,10 +30,38 @@ module DEBUGGER__
|
|
30
30
|
prepend m
|
31
31
|
end if SIGWINCH_SUPPORTED
|
32
32
|
|
33
|
+
def parse_input buff, commands
|
34
|
+
c, rest = get_command buff
|
35
|
+
case
|
36
|
+
when commands.keys.include?(c)
|
37
|
+
:command
|
38
|
+
when !rest && /\A\s*[a-z]*\z/ =~ c
|
39
|
+
nil
|
40
|
+
else
|
41
|
+
:ruby
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
33
45
|
def readline_setup prompt
|
34
46
|
load_history_if_not_loaded
|
35
47
|
commands = DEBUGGER__.commands
|
36
48
|
|
49
|
+
prev_completion_proc = Reline.completion_proc
|
50
|
+
prev_output_modifier_proc = Reline.output_modifier_proc
|
51
|
+
prev_prompt_proc = Reline.prompt_proc
|
52
|
+
|
53
|
+
# prompt state
|
54
|
+
state = nil # :command, :ruby, nil (unknown)
|
55
|
+
|
56
|
+
Reline.prompt_proc = -> args, *kw do
|
57
|
+
case state = parse_input(args.first, commands)
|
58
|
+
when nil, :command
|
59
|
+
[prompt, prompt]
|
60
|
+
when :ruby
|
61
|
+
[prompt.sub('rdbg'){colorize('ruby', [:RED])}] * 2
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
37
65
|
Reline.completion_proc = -> given do
|
38
66
|
buff = Reline.line_buffer
|
39
67
|
Reline.completion_append_character= ' '
|
@@ -46,17 +74,16 @@ module DEBUGGER__
|
|
46
74
|
end
|
47
75
|
files
|
48
76
|
else
|
49
|
-
commands.keys.grep(/\A#{given}/)
|
77
|
+
commands.keys.grep(/\A#{Regexp.escape(given)}/)
|
50
78
|
end
|
51
79
|
end
|
52
80
|
|
53
81
|
Reline.output_modifier_proc = -> buff, **kw do
|
54
82
|
c, rest = get_command buff
|
55
83
|
|
56
|
-
case
|
57
|
-
when
|
58
|
-
|
59
|
-
cmd = colorize(c.strip, [:CYAN, :UNDERLINE])
|
84
|
+
case state
|
85
|
+
when :command
|
86
|
+
cmd = colorize(c, [:CYAN, :UNDERLINE])
|
60
87
|
|
61
88
|
if commands[c] == c
|
62
89
|
rprompt = colorize(" # command", [:DIM])
|
@@ -64,28 +91,36 @@ module DEBUGGER__
|
|
64
91
|
rprompt = colorize(" # #{commands[c]} command", [:DIM])
|
65
92
|
end
|
66
93
|
|
67
|
-
rest =
|
68
|
-
cmd + rest
|
69
|
-
when
|
94
|
+
rest = rest ? colorize_code(rest) : ''
|
95
|
+
cmd + rest + rprompt
|
96
|
+
when nil
|
70
97
|
buff
|
71
|
-
|
72
|
-
colorize_code(buff.chomp)
|
98
|
+
when :ruby
|
99
|
+
colorize_code(buff.chomp)
|
73
100
|
end
|
74
|
-
end
|
101
|
+
end unless CONFIG[:no_hint]
|
102
|
+
|
103
|
+
yield
|
104
|
+
|
105
|
+
ensure
|
106
|
+
Reline.completion_proc = prev_completion_proc
|
107
|
+
Reline.output_modifier_proc = prev_output_modifier_proc
|
108
|
+
Reline.prompt_proc = prev_prompt_proc
|
75
109
|
end
|
76
110
|
|
77
111
|
private def get_command line
|
78
112
|
case line.chomp
|
79
113
|
when /\A(\s*[a-z]+)(\s.*)?\z$/
|
80
|
-
return $1, $2
|
114
|
+
return $1.strip, $2
|
81
115
|
else
|
82
|
-
line.
|
116
|
+
line.strip
|
83
117
|
end
|
84
118
|
end
|
85
119
|
|
86
120
|
def readline prompt
|
87
|
-
readline_setup prompt
|
88
|
-
|
121
|
+
readline_setup prompt do
|
122
|
+
Reline.readmultiline(prompt, true){ true }
|
123
|
+
end
|
89
124
|
end
|
90
125
|
|
91
126
|
def history
|
@@ -139,13 +174,19 @@ module DEBUGGER__
|
|
139
174
|
end
|
140
175
|
|
141
176
|
def history_file
|
142
|
-
CONFIG[:history_file]
|
177
|
+
history_file = CONFIG[:history_file]
|
178
|
+
|
179
|
+
if !history_file.empty?
|
180
|
+
File.expand_path(history_file)
|
181
|
+
else
|
182
|
+
history_file
|
183
|
+
end
|
143
184
|
end
|
144
185
|
|
145
186
|
FH = "# Today's OMIKUJI: "
|
146
187
|
|
147
188
|
def read_history_file
|
148
|
-
if history && File.
|
189
|
+
if history && File.exist?(path = history_file)
|
149
190
|
f = (['', 'DAI-', 'CHU-', 'SHO-'].map{|e| e+'KICHI'}+['KYO']).sample
|
150
191
|
["#{FH}#{f}".dup] + File.readlines(path)
|
151
192
|
else
|
@@ -167,7 +208,7 @@ module DEBUGGER__
|
|
167
208
|
if history && @init_history_lines
|
168
209
|
added_records = history.to_a[@init_history_lines .. -1]
|
169
210
|
path = history_file
|
170
|
-
max = CONFIG[:save_history]
|
211
|
+
max = CONFIG[:save_history]
|
171
212
|
|
172
213
|
if !added_records.empty? && !path.empty?
|
173
214
|
orig_records = read_history_file
|
data/lib/debug/frame_info.rb
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module DEBUGGER__
|
4
4
|
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
|
5
|
-
:has_return_value,
|
5
|
+
:has_return_value, :return_value,
|
6
6
|
:has_raised_exception, :raised_exception,
|
7
7
|
:show_line,
|
8
|
-
:_local_variables, :_callee # for recorder
|
8
|
+
:_local_variables, :_callee, # for recorder
|
9
|
+
:dupped_binding,
|
9
10
|
)
|
10
11
|
|
11
12
|
# extend FrameInfo with debug.so
|
@@ -26,12 +27,12 @@ module DEBUGGER__
|
|
26
27
|
location.absolute_path
|
27
28
|
end
|
28
29
|
|
29
|
-
def pretty_path
|
30
|
-
return '#<none>' unless path
|
30
|
+
def self.pretty_path path
|
31
|
+
return '#<none>' unless path
|
31
32
|
use_short_path = CONFIG[:use_short_path]
|
32
33
|
|
33
34
|
case
|
34
|
-
when use_short_path && path.start_with?(dir = CONFIG["rubylibdir"] + '/')
|
35
|
+
when use_short_path && path.start_with?(dir = RbConfig::CONFIG["rubylibdir"] + '/')
|
35
36
|
path.sub(dir, '$(rubylibdir)/')
|
36
37
|
when use_short_path && Gem.path.any? do |gp|
|
37
38
|
path.start_with?(dir = gp + '/gems/')
|
@@ -44,15 +45,18 @@ module DEBUGGER__
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
def pretty_path
|
49
|
+
FrameInfo.pretty_path path
|
50
|
+
end
|
51
|
+
|
47
52
|
def name
|
48
53
|
# p frame_type: frame_type, self: self
|
49
54
|
case frame_type
|
50
55
|
when :block
|
51
|
-
level, block_loc
|
56
|
+
level, block_loc = block_identifier
|
52
57
|
"block in #{block_loc}#{level}"
|
53
58
|
when :method
|
54
|
-
|
55
|
-
"#{ci}"
|
59
|
+
method_identifier
|
56
60
|
when :c
|
57
61
|
c_identifier
|
58
62
|
when :other
|
@@ -82,16 +86,13 @@ module DEBUGGER__
|
|
82
86
|
|
83
87
|
def block_identifier
|
84
88
|
return unless frame_type == :block
|
85
|
-
args = parameters_info(iseq.argc)
|
86
89
|
_, level, block_loc = location.label.match(BLOCK_LABL_REGEXP).to_a
|
87
|
-
[level || "", block_loc
|
90
|
+
[level || "", block_loc]
|
88
91
|
end
|
89
92
|
|
90
93
|
def method_identifier
|
91
94
|
return unless frame_type == :method
|
92
|
-
|
93
|
-
ci = "#{klass_sig}#{callee}"
|
94
|
-
[ci, args]
|
95
|
+
"#{klass_sig}#{callee}"
|
95
96
|
end
|
96
97
|
|
97
98
|
def c_identifier
|
@@ -105,32 +106,34 @@ module DEBUGGER__
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def callee
|
108
|
-
self._callee ||=
|
109
|
+
self._callee ||= begin
|
110
|
+
self.binding&.eval('__callee__')
|
111
|
+
rescue NameError # BasicObject
|
112
|
+
nil
|
113
|
+
end
|
109
114
|
end
|
110
115
|
|
111
116
|
def return_str
|
112
117
|
if self.binding && iseq && has_return_value
|
113
|
-
DEBUGGER__.
|
118
|
+
DEBUGGER__.safe_inspect(return_value, short: true)
|
114
119
|
end
|
115
120
|
end
|
116
121
|
|
117
|
-
def
|
118
|
-
|
122
|
+
def matchable_location
|
123
|
+
# realpath can sometimes be nil so we can't use it here
|
124
|
+
"#{path}:#{location.lineno}"
|
119
125
|
end
|
120
126
|
|
121
|
-
|
122
|
-
|
123
|
-
self.local_variables.each{|var, val|
|
124
|
-
__newb__.local_variable_set(var, val)
|
125
|
-
}
|
126
|
-
__newb__
|
127
|
+
def location_str
|
128
|
+
"#{pretty_path}:#{location.lineno}"
|
127
129
|
end
|
128
130
|
|
129
131
|
def eval_binding
|
130
|
-
if b = self.
|
132
|
+
if b = self.dupped_binding
|
131
133
|
b
|
132
|
-
|
133
|
-
|
134
|
+
else
|
135
|
+
b = self.binding || TOPLEVEL_BINDING
|
136
|
+
self.dupped_binding = b.dup
|
134
137
|
end
|
135
138
|
end
|
136
139
|
|
@@ -144,9 +147,18 @@ module DEBUGGER__
|
|
144
147
|
end
|
145
148
|
end
|
146
149
|
|
147
|
-
|
150
|
+
def parameters_info
|
151
|
+
vars = iseq.parameters_symbols
|
152
|
+
vars.map{|var|
|
153
|
+
begin
|
154
|
+
{ name: var, value: DEBUGGER__.safe_inspect(local_variable_get(var), short: true) }
|
155
|
+
rescue NameError, TypeError
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
}.compact
|
159
|
+
end
|
148
160
|
|
149
|
-
def get_singleton_class obj
|
161
|
+
private def get_singleton_class obj
|
150
162
|
obj.singleton_class # TODO: don't use it
|
151
163
|
rescue TypeError
|
152
164
|
nil
|
@@ -156,18 +168,7 @@ module DEBUGGER__
|
|
156
168
|
local_variables[var]
|
157
169
|
end
|
158
170
|
|
159
|
-
def
|
160
|
-
vars = iseq.locals[0...argc]
|
161
|
-
vars.map{|var|
|
162
|
-
begin
|
163
|
-
{ name: var, value: DEBUGGER__.short_inspect(local_variable_get(var)) }
|
164
|
-
rescue NameError, TypeError
|
165
|
-
nil
|
166
|
-
end
|
167
|
-
}.compact
|
168
|
-
end
|
169
|
-
|
170
|
-
def klass_sig
|
171
|
+
private def klass_sig
|
171
172
|
if self.class == get_singleton_class(self.self)
|
172
173
|
"#{self.self}."
|
173
174
|
else
|
data/lib/debug/local.rb
CHANGED
data/lib/debug/prelude.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
return if defined?(::DEBUGGER__)
|
4
4
|
|
5
|
+
# Put the following line in your login script (e.g. ~/.bash_profile) with modified path:
|
5
6
|
#
|
6
|
-
#
|
7
|
-
# export RUBYOPT="-r .../debug/prelude $(RUBYOPT)"
|
7
|
+
# export RUBYOPT="-r /path/to/debug/prelude $(RUBYOPT)"
|
8
8
|
#
|
9
9
|
module Kernel
|
10
10
|
def debugger(*a, up_level: 0, **kw)
|