ruby-debug-ide 0.6.1.beta4 → 0.6.1.beta6
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/bin/gdb_wrapper +8 -40
- data/bin/rdebug-ide +15 -1
- data/lib/ruby-debug-ide/attach/util.rb +71 -0
- data/lib/ruby-debug-ide/command.rb +1 -0
- data/lib/ruby-debug-ide/commands/variables.rb +1 -1
- data/lib/ruby-debug-ide/multiprocess/pre_child.rb +5 -1
- data/lib/ruby-debug-ide/multiprocess/starter.rb +1 -0
- data/lib/ruby-debug-ide/version.rb +1 -1
- data/lib/ruby-debug-ide/xml_printer.rb +163 -76
- metadata +7 -8
- data/lib/ruby-debug-ide/boo.sh +0 -1
- data/lib/ruby-debug-ide/foo.sh +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 565c9fc5c3cf0ae3477f3b944fbe90f956420302
|
4
|
+
data.tar.gz: 8ff67628c2d6b887e8651013f6744157bc65254a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbe3852ec8b2cbf4f221912c3e679d2610198af3316b15810ef963e6cab4115d0ef716cebeeb035ed26779d2347c58637ecf55815993fdb5c5bb9d8870bbbe74
|
7
|
+
data.tar.gz: 7ebf7eb3bc7e06c95661abf449777f513a25f510de3a3ad2d952edf54b64baa70aaca9b700e984129c58102d4755c5692c46829806c606f4b59d81f452adbb16
|
data/bin/gdb_wrapper
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
+
require 'thread'
|
4
5
|
require 'ostruct'
|
5
6
|
|
6
7
|
$stdout.sync = true
|
@@ -65,6 +66,7 @@ unless options.ruby_path
|
|
65
66
|
end
|
66
67
|
|
67
68
|
argv = '["' + ARGV * '", "' + '"]'
|
69
|
+
child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]'
|
68
70
|
debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader'
|
69
71
|
|
70
72
|
options.gems_to_include.each do |gem_path|
|
@@ -78,51 +80,17 @@ require 'ruby-debug-ide/attach/util'
|
|
78
80
|
require 'ruby-debug-ide/attach/native_debugger'
|
79
81
|
require 'ruby-debug-ide/attach/process_thread'
|
80
82
|
|
81
|
-
debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv)
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
process_threads = debugger.process_threads
|
87
|
-
if process_threads
|
88
|
-
process_threads.each do |thread|
|
89
|
-
$stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
debugger.exit
|
93
|
-
end
|
94
|
-
exit!
|
95
|
-
end
|
84
|
+
child_pids = get_child_pids(options.pid.to_s)
|
85
|
+
attach_threads = Array.new
|
86
|
+
attach_threads << attach_and_return_thread(options, options.pid, debugger_loader_path, argv)
|
96
87
|
|
97
|
-
|
98
|
-
debugger.set_flags
|
88
|
+
attach_threads << child_pids.map {|pid| attach_and_return_thread(options, pid, debugger_loader_path, child_argv)}
|
99
89
|
|
90
|
+
|
91
|
+
attach_threads.each {|thread| thread.join}
|
100
92
|
if options.uid
|
101
93
|
DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}")
|
102
94
|
Process::Sys.setuid(options.uid.to_i)
|
103
95
|
end
|
104
|
-
|
105
|
-
if debugger.check_already_under_debug
|
106
|
-
$stderr.puts "Process #{debugger.pid} is already under debug"
|
107
|
-
debugger.exit
|
108
|
-
exit!
|
109
|
-
end
|
110
|
-
|
111
|
-
should_check_threads_state = true
|
112
|
-
|
113
|
-
while should_check_threads_state
|
114
|
-
should_check_threads_state = false
|
115
|
-
debugger.update_threads.each do |thread|
|
116
|
-
thread.switch
|
117
|
-
while thread.need_finish_frame
|
118
|
-
should_check_threads_state = true
|
119
|
-
thread.finish
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
debugger.wait_line_event
|
125
|
-
debugger.load_debugger
|
126
|
-
debugger.exit
|
127
|
-
|
128
96
|
sleep
|
data/bin/rdebug-ide
CHANGED
@@ -36,8 +36,19 @@ Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or
|
|
36
36
|
EOB
|
37
37
|
opts.separator ""
|
38
38
|
opts.separator "Options:"
|
39
|
+
|
40
|
+
ENV['DEBUGGER_MEMORY_LIMIT'] = '10'
|
41
|
+
opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit|
|
42
|
+
ENV['DEBUGGER_MEMORY_LIMIT'] = limit
|
43
|
+
end
|
44
|
+
|
45
|
+
ENV['INSPECT_TIME_LIMIT'] = '100'
|
46
|
+
opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit|
|
47
|
+
ENV['INSPECT_TIME_LIMIT'] = limit
|
48
|
+
end
|
49
|
+
|
39
50
|
opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host}
|
40
|
-
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
|
51
|
+
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
|
41
52
|
opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp|
|
42
53
|
options.dispatcher_port = dp
|
43
54
|
end
|
@@ -60,6 +71,9 @@ EOB
|
|
60
71
|
opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do
|
61
72
|
options.attach_mode = true
|
62
73
|
end
|
74
|
+
opts.on("--ignore-port", "Generate another port") do
|
75
|
+
options.ignore_port = true
|
76
|
+
end
|
63
77
|
opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
|
64
78
|
opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false}
|
65
79
|
opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do
|
@@ -1,5 +1,76 @@
|
|
1
1
|
require 'ruby-debug-ide/attach/lldb'
|
2
2
|
require 'ruby-debug-ide/attach/gdb'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
def attach_and_return_thread(options, pid, debugger_loader_path, argv)
|
6
|
+
Thread.new(argv) do |argv|
|
7
|
+
|
8
|
+
debugger = choose_debugger(options.ruby_path, pid, options.gems_to_include, debugger_loader_path, argv)
|
9
|
+
|
10
|
+
trap('INT') do
|
11
|
+
unless debugger.exited?
|
12
|
+
$stderr.puts "backtraces for threads:\n\n"
|
13
|
+
process_threads = debugger.process_threads
|
14
|
+
if process_threads
|
15
|
+
process_threads.each do |thread|
|
16
|
+
$stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
debugger.exit
|
20
|
+
end
|
21
|
+
exit!
|
22
|
+
end
|
23
|
+
|
24
|
+
debugger.attach_to_process
|
25
|
+
debugger.set_flags
|
26
|
+
|
27
|
+
if debugger.check_already_under_debug
|
28
|
+
$stderr.puts "Process #{debugger.pid} is already under debug"
|
29
|
+
debugger.exit
|
30
|
+
exit!
|
31
|
+
end
|
32
|
+
|
33
|
+
should_check_threads_state = true
|
34
|
+
|
35
|
+
while should_check_threads_state
|
36
|
+
should_check_threads_state = false
|
37
|
+
debugger.update_threads.each do |thread|
|
38
|
+
thread.switch
|
39
|
+
while thread.need_finish_frame
|
40
|
+
should_check_threads_state = true
|
41
|
+
thread.finish
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
debugger.wait_line_event
|
47
|
+
debugger.load_debugger
|
48
|
+
debugger.exit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_child_pids(pid)
|
53
|
+
return [] unless command_exists 'pgrep'
|
54
|
+
|
55
|
+
pids = Array.new
|
56
|
+
|
57
|
+
q = Queue.new
|
58
|
+
q.push(pid)
|
59
|
+
|
60
|
+
while (!q.empty?) do
|
61
|
+
pid = q.pop
|
62
|
+
|
63
|
+
pipe = IO.popen("pgrep -P #{pid}")
|
64
|
+
|
65
|
+
pipe.readlines.each do |child|
|
66
|
+
child_pid = child.strip.to_i
|
67
|
+
q.push(child_pid)
|
68
|
+
pids << child_pid
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
pids
|
73
|
+
end
|
3
74
|
|
4
75
|
def command_exists(command)
|
5
76
|
checking_command = "checking command #{command} for existence\n"
|
@@ -118,6 +118,7 @@ module Debugger
|
|
118
118
|
def debug_eval(str, b = get_binding)
|
119
119
|
begin
|
120
120
|
str = str.to_s
|
121
|
+
str.force_encoding('UTF-8') if(RUBY_VERSION > '2.0')
|
121
122
|
to_inspect = Command.unescape_incoming(str)
|
122
123
|
max_time = Debugger.evaluation_timeout
|
123
124
|
@printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time)
|
@@ -129,7 +129,7 @@ module Debugger
|
|
129
129
|
locals = @state.context.frame_locals(@state.frame_pos)
|
130
130
|
_self = @state.context.frame_self(@state.frame_pos)
|
131
131
|
begin
|
132
|
-
locals['self'] = _self unless
|
132
|
+
locals['self'] = _self unless TOPLEVEL_BINDING.eval('self') == _self
|
133
133
|
rescue => ex
|
134
134
|
locals['self'] = "<Cannot evaluate self>"
|
135
135
|
$stderr << "Cannot evaluate self\n#{ex.class.name}: #{ex.message}\n #{ex.backtrace.join("\n ")}"
|
@@ -19,6 +19,11 @@ module Debugger
|
|
19
19
|
'notify_dispatcher' => true
|
20
20
|
)
|
21
21
|
|
22
|
+
if(options.ignore_port)
|
23
|
+
options.port = find_free_port(options.host)
|
24
|
+
options.notify_dispatcher = true
|
25
|
+
end
|
26
|
+
|
22
27
|
start_debugger(options)
|
23
28
|
end
|
24
29
|
|
@@ -39,7 +44,6 @@ module Debugger
|
|
39
44
|
Debugger.keep_frame_binding = options.frame_bind
|
40
45
|
Debugger.tracing = options.tracing
|
41
46
|
Debugger.cli_debug = options.cli_debug
|
42
|
-
|
43
47
|
Debugger.prepare_debugger(options)
|
44
48
|
end
|
45
49
|
|
@@ -1,12 +1,39 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
require 'cgi'
|
3
3
|
require 'monitor'
|
4
|
+
require 'objspace'
|
4
5
|
|
5
6
|
module Debugger
|
6
7
|
|
8
|
+
module OverflowMessageType
|
9
|
+
NIL_MESSAGE = lambda {|e| nil}
|
10
|
+
EXCEPTION_MESSAGE = lambda {|e| e.message}
|
11
|
+
SPECIAL_SYMBOL_MESSAGE = lambda {|e| '<?>'}
|
12
|
+
end
|
13
|
+
|
14
|
+
class MemoryLimitError < StandardError
|
15
|
+
attr_reader :message
|
16
|
+
attr_reader :backtrace
|
17
|
+
|
18
|
+
def initialize(message, backtrace = '')
|
19
|
+
@message = message
|
20
|
+
@backtrace = backtrace
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class TimeLimitError < StandardError
|
25
|
+
attr_reader :message
|
26
|
+
attr_reader :backtrace
|
27
|
+
|
28
|
+
def initialize(message, backtrace = '')
|
29
|
+
@message = message
|
30
|
+
@backtrace = backtrace
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
7
34
|
class XmlPrinter # :nodoc:
|
8
35
|
class ExceptionProxy
|
9
|
-
instance_methods.each {
|
36
|
+
instance_methods.each {|m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/}
|
10
37
|
|
11
38
|
def initialize(exception)
|
12
39
|
@exception = exception
|
@@ -14,9 +41,9 @@ module Debugger
|
|
14
41
|
@backtrace = Debugger.cleanup_backtrace(exception.backtrace)
|
15
42
|
end
|
16
43
|
|
17
|
-
private
|
18
|
-
def method_missing(called, *args, &block)
|
19
|
-
@exception.__send__(called, *args, &block)
|
44
|
+
private
|
45
|
+
def method_missing(called, *args, &block)
|
46
|
+
@exception.__send__(called, *args, &block)
|
20
47
|
end
|
21
48
|
end
|
22
49
|
|
@@ -31,15 +58,15 @@ module Debugger
|
|
31
58
|
end
|
32
59
|
end
|
33
60
|
}
|
34
|
-
end
|
61
|
+
end
|
35
62
|
|
36
63
|
@@monitor = Monitor.new
|
37
64
|
attr_accessor :interface
|
38
|
-
|
65
|
+
|
39
66
|
def initialize(interface)
|
40
67
|
@interface = interface
|
41
68
|
end
|
42
|
-
|
69
|
+
|
43
70
|
def print_msg(*args)
|
44
71
|
msg, *args = args
|
45
72
|
xml_message = CGI.escapeHTML(msg % args)
|
@@ -62,7 +89,7 @@ module Debugger
|
|
62
89
|
print CGI.escapeHTML(msg % args)
|
63
90
|
end
|
64
91
|
end
|
65
|
-
|
92
|
+
|
66
93
|
def print_frames(context, current_frame_id)
|
67
94
|
print_element("frames") do
|
68
95
|
(0...context.stack_size).each do |id|
|
@@ -70,18 +97,18 @@ module Debugger
|
|
70
97
|
end
|
71
98
|
end
|
72
99
|
end
|
73
|
-
|
100
|
+
|
74
101
|
def print_current_frame(frame_pos)
|
75
102
|
print_debug "Selected frame no #{frame_pos}"
|
76
103
|
end
|
77
|
-
|
104
|
+
|
78
105
|
def print_frame(context, frame_id, current_frame_id)
|
79
106
|
# idx + 1: one-based numbering as classic-debugger
|
80
107
|
file = context.frame_file(frame_id)
|
81
108
|
print "<frame no=\"%s\" file=\"%s\" line=\"%s\" #{"current='true' " if frame_id == current_frame_id}/>",
|
82
|
-
|
109
|
+
frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id)
|
83
110
|
end
|
84
|
-
|
111
|
+
|
85
112
|
def print_contexts(contexts)
|
86
113
|
print_element("threads") do
|
87
114
|
contexts.each do |c|
|
@@ -89,11 +116,11 @@ module Debugger
|
|
89
116
|
end
|
90
117
|
end
|
91
118
|
end
|
92
|
-
|
119
|
+
|
93
120
|
def print_context(context)
|
94
121
|
print "<thread id=\"%s\" status=\"%s\" pid=\"%s\" #{current_thread_attr(context)}/>", context.thnum, context.thread.status, Process.pid
|
95
122
|
end
|
96
|
-
|
123
|
+
|
97
124
|
def print_variables(vars, kind)
|
98
125
|
print_element("variables") do
|
99
126
|
# print self at top position
|
@@ -103,26 +130,26 @@ module Debugger
|
|
103
130
|
end
|
104
131
|
end
|
105
132
|
end
|
106
|
-
|
133
|
+
|
107
134
|
def print_array(array)
|
108
135
|
print_element("variables") do
|
109
|
-
index = 0
|
110
|
-
array.each {
|
111
|
-
print_variable('[' + index.to_s + ']', e, 'instance')
|
112
|
-
index += 1
|
136
|
+
index = 0
|
137
|
+
array.each {|e|
|
138
|
+
print_variable('[' + index.to_s + ']', e, 'instance')
|
139
|
+
index += 1
|
113
140
|
}
|
114
141
|
end
|
115
142
|
end
|
116
|
-
|
143
|
+
|
117
144
|
def print_hash(hash)
|
118
145
|
print_element("variables") do
|
119
|
-
hash.keys.each {
|
146
|
+
hash.keys.each {|k|
|
120
147
|
if k.class.name == "String"
|
121
148
|
name = '\'' + k + '\''
|
122
149
|
else
|
123
|
-
name = k.to_s
|
150
|
+
name = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE)
|
124
151
|
end
|
125
|
-
print_variable(name, hash[k], 'instance')
|
152
|
+
print_variable(name, hash[k], 'instance')
|
126
153
|
}
|
127
154
|
end
|
128
155
|
end
|
@@ -134,10 +161,55 @@ module Debugger
|
|
134
161
|
InspectCommand.reference_result(bytes)
|
135
162
|
print_variable('bytes', bytes, 'instance')
|
136
163
|
end
|
137
|
-
print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding')
|
164
|
+
print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding')
|
138
165
|
end
|
139
166
|
end
|
140
|
-
|
167
|
+
|
168
|
+
def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type)
|
169
|
+
check_memory_limit = true
|
170
|
+
if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0)
|
171
|
+
check_memory_limit = false
|
172
|
+
end
|
173
|
+
curr_thread = Thread.current
|
174
|
+
result = nil
|
175
|
+
inspect_thread = DebugThread.start {
|
176
|
+
|
177
|
+
start_alloc_size = ObjectSpace.memsize_of_all if (check_memory_limit)
|
178
|
+
start_time = Time.now.to_f
|
179
|
+
|
180
|
+
trace = TracePoint.new(:c_call, :call) do |tp|
|
181
|
+
|
182
|
+
if (rand > 0.75)
|
183
|
+
curr_time = Time.now.to_f
|
184
|
+
|
185
|
+
if ((curr_time - start_time) * 1e3 > time_limit)
|
186
|
+
curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map {|l| "\t#{l}"}.join("\n")}")
|
187
|
+
inspect_thread.kill
|
188
|
+
end
|
189
|
+
|
190
|
+
if (check_memory_limit)
|
191
|
+
curr_alloc_size = ObjectSpace.memsize_of_all
|
192
|
+
start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size)
|
193
|
+
|
194
|
+
if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit)
|
195
|
+
curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map {|l| "\t#{l}"}.join("\n")}")
|
196
|
+
inspect_thread.kill
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end.enable {
|
201
|
+
result = value.send exec_method
|
202
|
+
}
|
203
|
+
}
|
204
|
+
inspect_thread.join
|
205
|
+
inspect_thread.kill
|
206
|
+
return result
|
207
|
+
rescue MemoryLimitError, TimeLimitError => e
|
208
|
+
print_debug(e.message + "\n" + e.backtrace)
|
209
|
+
|
210
|
+
return overflow_message_type.call(e)
|
211
|
+
end
|
212
|
+
|
141
213
|
def print_variable(name, value, kind)
|
142
214
|
name = name.to_s
|
143
215
|
if value.nil?
|
@@ -147,7 +219,7 @@ module Debugger
|
|
147
219
|
if value.is_a?(Array) || value.is_a?(Hash)
|
148
220
|
has_children = !value.empty?
|
149
221
|
if has_children
|
150
|
-
size
|
222
|
+
size = value.size
|
151
223
|
value_str = "#{value.class} (#{value.size} element#{size > 1 ? "s" : "" })"
|
152
224
|
else
|
153
225
|
value_str = "Empty #{value.class}"
|
@@ -155,27 +227,29 @@ module Debugger
|
|
155
227
|
elsif value.is_a?(String)
|
156
228
|
has_children = value.respond_to?('bytes') || value.respond_to?('encoding')
|
157
229
|
value_str = value
|
158
|
-
else
|
230
|
+
else
|
159
231
|
has_children = !value.instance_variables.empty? || !value.class.class_variables.empty?
|
160
|
-
|
232
|
+
|
233
|
+
value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>"
|
234
|
+
|
161
235
|
unless value_str.is_a?(String)
|
162
|
-
value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String."
|
236
|
+
value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String."
|
163
237
|
end
|
164
238
|
end
|
165
239
|
|
166
240
|
if value_str.respond_to?('encode')
|
167
241
|
# noinspection RubyEmptyRescueBlockInspection
|
168
242
|
begin
|
169
|
-
|
243
|
+
value_str = value_str.encode("UTF-8")
|
170
244
|
rescue
|
171
245
|
end
|
172
246
|
end
|
173
247
|
value_str = handle_binary_data(value_str)
|
174
248
|
escaped_value_str = CGI.escapeHTML(value_str)
|
175
249
|
print("<variable name=\"%s\" %s kind=\"%s\" %s type=\"%s\" hasChildren=\"%s\" objectId=\"%#+x\">",
|
176
|
-
|
177
|
-
|
178
|
-
|
250
|
+
CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind,
|
251
|
+
build_value_attr(escaped_value_str), value.class,
|
252
|
+
has_children, value.respond_to?(:object_id) ? value.object_id : value.id)
|
179
253
|
print("<value><![CDATA[%s]]></value>", escaped_value_str) if Debugger.value_as_nested_element
|
180
254
|
print('</variable>')
|
181
255
|
rescue StandardError => e
|
@@ -198,28 +272,28 @@ module Debugger
|
|
198
272
|
|
199
273
|
def print_breakpoints(breakpoints)
|
200
274
|
print_element 'breakpoints' do
|
201
|
-
breakpoints.sort_by{|b| b.id
|
275
|
+
breakpoints.sort_by {|b| b.id}.each do |b|
|
202
276
|
print "<breakpoint n=\"%d\" file=\"%s\" line=\"%s\" />", b.id, CGI.escapeHTML(b.source), b.pos.to_s
|
203
277
|
end
|
204
278
|
end
|
205
279
|
end
|
206
|
-
|
280
|
+
|
207
281
|
def print_breakpoint_added(b)
|
208
282
|
print "<breakpointAdded no=\"%s\" location=\"%s:%s\"/>", b.id, CGI.escapeHTML(b.source), b.pos
|
209
283
|
end
|
210
|
-
|
284
|
+
|
211
285
|
def print_breakpoint_deleted(b)
|
212
286
|
print "<breakpointDeleted no=\"%s\"/>", b.id
|
213
287
|
end
|
214
|
-
|
288
|
+
|
215
289
|
def print_breakpoint_enabled(b)
|
216
290
|
print "<breakpointEnabled bp_id=\"%s\"/>", b.id
|
217
291
|
end
|
218
|
-
|
292
|
+
|
219
293
|
def print_breakpoint_disabled(b)
|
220
294
|
print "<breakpointDisabled bp_id=\"%s\"/>", b.id
|
221
295
|
end
|
222
|
-
|
296
|
+
|
223
297
|
def print_contdition_set(bp_id)
|
224
298
|
print "<conditionSet bp_id=\"%d\"/>", bp_id
|
225
299
|
end
|
@@ -239,37 +313,37 @@ module Debugger
|
|
239
313
|
def print_expressions(exps)
|
240
314
|
print_element "expressions" do
|
241
315
|
exps.each_with_index do |(exp, value), idx|
|
242
|
-
print_expression(exp, value, idx+1)
|
316
|
+
print_expression(exp, value, idx + 1)
|
243
317
|
end
|
244
318
|
end unless exps.empty?
|
245
319
|
end
|
246
|
-
|
320
|
+
|
247
321
|
def print_expression(exp, value, idx)
|
248
322
|
print "<dispay name=\"%s\" value=\"%s\" no=\"%d\" />", exp, value, idx
|
249
323
|
end
|
250
324
|
|
251
325
|
def print_expression_info(incomplete, prompt, indent)
|
252
326
|
print "<expressionInfo incomplete=\"%s\" prompt=\"%s\" indent=\"%s\"></expressionInfo>",
|
253
|
-
|
327
|
+
incomplete, CGI.escapeHTML(prompt), indent
|
254
328
|
end
|
255
|
-
|
329
|
+
|
256
330
|
def print_eval(exp, value)
|
257
|
-
print "<eval expression=\"%s\" value=\"%s\" />",
|
331
|
+
print "<eval expression=\"%s\" value=\"%s\" />", CGI.escapeHTML(exp), value
|
258
332
|
end
|
259
|
-
|
333
|
+
|
260
334
|
def print_pp(value)
|
261
335
|
print value
|
262
336
|
end
|
263
|
-
|
337
|
+
|
264
338
|
def print_list(b, e, file, line)
|
265
339
|
print "[%d, %d] in %s\n", b, e, file
|
266
340
|
if (lines = Debugger.source_for(file))
|
267
341
|
b.upto(e) do |n|
|
268
|
-
if n > 0 && lines[n-1]
|
342
|
+
if n > 0 && lines[n - 1]
|
269
343
|
if n == line
|
270
|
-
print "=> %d %s\n", n, lines[n-1].chomp
|
344
|
+
print "=> %d %s\n", n, lines[n - 1].chomp
|
271
345
|
else
|
272
|
-
print " %d %s\n", n, lines[n-1].chomp
|
346
|
+
print " %d %s\n", n, lines[n - 1].chomp
|
273
347
|
end
|
274
348
|
end
|
275
349
|
end
|
@@ -277,7 +351,7 @@ module Debugger
|
|
277
351
|
print "No source-file available for %s\n", file
|
278
352
|
end
|
279
353
|
end
|
280
|
-
|
354
|
+
|
281
355
|
def print_methods(methods)
|
282
356
|
print_element "methods" do
|
283
357
|
methods.each do |method|
|
@@ -285,31 +359,31 @@ module Debugger
|
|
285
359
|
end
|
286
360
|
end
|
287
361
|
end
|
288
|
-
|
362
|
+
|
289
363
|
# Events
|
290
|
-
|
364
|
+
|
291
365
|
def print_breakpoint(_, breakpoint)
|
292
366
|
print("<breakpoint file=\"%s\" line=\"%s\" threadId=\"%d\"/>",
|
293
|
-
|
367
|
+
CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum)
|
294
368
|
end
|
295
|
-
|
369
|
+
|
296
370
|
def print_catchpoint(exception)
|
297
371
|
context = Debugger.current_context
|
298
|
-
print("<exception file=\"%s\" line=\"%s\" type=\"%s\" message=\"%s\" threadId=\"%d\"/>",
|
299
|
-
|
372
|
+
print("<exception file=\"%s\" line=\"%s\" type=\"%s\" message=\"%s\" threadId=\"%d\"/>",
|
373
|
+
CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum)
|
300
374
|
end
|
301
|
-
|
375
|
+
|
302
376
|
def print_trace(context, file, line)
|
303
377
|
Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, context.thnum
|
304
378
|
# TBD: do we want to clog fronend with the <trace> elements? There are tons of them.
|
305
379
|
# print "<trace file=\"%s\" line=\"%s\" threadId=\"%d\" />", file, line, context.thnum
|
306
380
|
end
|
307
|
-
|
381
|
+
|
308
382
|
def print_at_line(context, file, line)
|
309
383
|
print "<suspended file=\"%s\" line=\"%s\" threadId=\"%d\" frames=\"%d\"/>",
|
310
384
|
CGI.escapeHTML(File.expand_path(file)), line, context.thnum, context.stack_size
|
311
385
|
end
|
312
|
-
|
386
|
+
|
313
387
|
def print_exception(exception, _)
|
314
388
|
print_element("variables") do
|
315
389
|
proxy = ExceptionProxy.new(exception)
|
@@ -317,21 +391,21 @@ module Debugger
|
|
317
391
|
print_variable('error', proxy, 'exception')
|
318
392
|
end
|
319
393
|
rescue Exception
|
320
|
-
print "<processingException type=\"%s\" message=\"%s\"/>",
|
321
|
-
|
394
|
+
print "<processingException type=\"%s\" message=\"%s\"/>",
|
395
|
+
exception.class, CGI.escapeHTML(exception.to_s)
|
322
396
|
end
|
323
|
-
|
397
|
+
|
324
398
|
def print_inspect(eval_result)
|
325
|
-
print_element("variables") do
|
399
|
+
print_element("variables") do
|
326
400
|
print_variable("eval_result", eval_result, 'local')
|
327
401
|
end
|
328
402
|
end
|
329
|
-
|
330
|
-
def print_load_result(file, exception=nil)
|
403
|
+
|
404
|
+
def print_load_result(file, exception = nil)
|
331
405
|
if exception
|
332
|
-
print("<loadResult file=\"%s\" exceptionType=\"%s\" exceptionMessage=\"%s\"/>", file, exception.class, CGI.escapeHTML(exception.to_s))
|
406
|
+
print("<loadResult file=\"%s\" exceptionType=\"%s\" exceptionMessage=\"%s\"/>", file, exception.class, CGI.escapeHTML(exception.to_s))
|
333
407
|
else
|
334
|
-
print("<loadResult file=\"%s\" status=\"OK\"/>", file)
|
408
|
+
print("<loadResult file=\"%s\" status=\"OK\"/>", file)
|
335
409
|
end
|
336
410
|
end
|
337
411
|
|
@@ -345,7 +419,7 @@ module Debugger
|
|
345
419
|
end
|
346
420
|
|
347
421
|
private
|
348
|
-
|
422
|
+
|
349
423
|
def print(*params)
|
350
424
|
Debugger::print_debug(*params)
|
351
425
|
@interface.print(*params)
|
@@ -381,22 +455,35 @@ module Debugger
|
|
381
455
|
end
|
382
456
|
|
383
457
|
def compact_array_str(value)
|
384
|
-
slice
|
385
|
-
|
386
|
-
|
387
|
-
|
458
|
+
slice = value[0..10]
|
459
|
+
|
460
|
+
compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, OverflowMessageType::NIL_MESSAGE)
|
461
|
+
|
462
|
+
if compact && value.size != slice.size
|
463
|
+
compact[0..compact.size - 2] + ", ...]"
|
388
464
|
end
|
389
465
|
compact
|
390
466
|
end
|
391
467
|
|
392
468
|
def compact_hash_str(value)
|
393
|
-
|
394
|
-
|
469
|
+
keys_strings = Hash.new
|
470
|
+
|
471
|
+
slice = value.sort_by do |k, _|
|
472
|
+
keys_string = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE)
|
473
|
+
keys_strings[k] = keys_string
|
474
|
+
keys_string
|
475
|
+
end[0..5]
|
476
|
+
|
477
|
+
compact = slice.map do |kv|
|
478
|
+
key_string = keys_strings[kv[0]]
|
479
|
+
value_string = exec_with_allocation_control(kv[1], ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE)
|
480
|
+
"#{key_string}: #{handle_binary_data(value_string)}"
|
481
|
+
end.join(", ")
|
395
482
|
"{" + compact + (slice.size != value.size ? ", ..." : "") + "}"
|
396
483
|
end
|
397
484
|
|
398
485
|
def build_compact_value_attr(value, value_str)
|
399
|
-
compact_value_str
|
486
|
+
compact_value_str = build_compact_name(value, value_str)
|
400
487
|
compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\""
|
401
488
|
end
|
402
489
|
|
@@ -422,7 +509,7 @@ module Debugger
|
|
422
509
|
protect m
|
423
510
|
end
|
424
511
|
end
|
425
|
-
|
512
|
+
|
426
513
|
end
|
427
514
|
|
428
515
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-debug-ide
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.1.
|
4
|
+
version: 0.6.1.beta6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Barchfeld, Martin Krauskopf, Mark Moseley, JetBrains RubyMine Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -24,8 +24,10 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.8.1
|
27
|
-
description:
|
28
|
-
|
27
|
+
description: 'An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans
|
28
|
+
and RubyMine.
|
29
|
+
|
30
|
+
'
|
29
31
|
email: rubymine-feedback@jetbrains.com
|
30
32
|
executables:
|
31
33
|
- rdebug-ide
|
@@ -50,7 +52,6 @@ files:
|
|
50
52
|
- lib/ruby-debug-ide/attach/native_debugger.rb
|
51
53
|
- lib/ruby-debug-ide/attach/process_thread.rb
|
52
54
|
- lib/ruby-debug-ide/attach/util.rb
|
53
|
-
- lib/ruby-debug-ide/boo.sh
|
54
55
|
- lib/ruby-debug-ide/command.rb
|
55
56
|
- lib/ruby-debug-ide/commands/breakpoints.rb
|
56
57
|
- lib/ruby-debug-ide/commands/catchpoint.rb
|
@@ -70,7 +71,6 @@ files:
|
|
70
71
|
- lib/ruby-debug-ide/commands/threads.rb
|
71
72
|
- lib/ruby-debug-ide/commands/variables.rb
|
72
73
|
- lib/ruby-debug-ide/event_processor.rb
|
73
|
-
- lib/ruby-debug-ide/foo.sh
|
74
74
|
- lib/ruby-debug-ide/greeter.rb
|
75
75
|
- lib/ruby-debug-ide/helper.rb
|
76
76
|
- lib/ruby-debug-ide/ide_processor.rb
|
@@ -103,9 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
version: 1.3.1
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project: debug-commons
|
106
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.6.11
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: IDE interface for ruby-debug.
|
110
110
|
test_files: []
|
111
|
-
has_rdoc: false
|
data/lib/ruby-debug-ide/boo.sh
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
sh foo.sh
|
data/lib/ruby-debug-ide/foo.sh
DELETED