debug 1.3.4 → 1.6.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.
- 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)
|