ruby-debug-ide19 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGES +75 -0
  2. data/ChangeLog +465 -0
  3. data/ChangeLog.archive +1073 -0
  4. data/MIT-LICENSE +24 -0
  5. data/Rakefile +110 -0
  6. data/bin/rdebug-ide +88 -0
  7. data/ext/mkrf_conf.rb +28 -0
  8. data/lib/ruby-debug-ide.rb +172 -0
  9. data/lib/ruby-debug/command.rb +169 -0
  10. data/lib/ruby-debug/commands/breakpoints.rb +129 -0
  11. data/lib/ruby-debug/commands/catchpoint.rb +52 -0
  12. data/lib/ruby-debug/commands/condition.rb +51 -0
  13. data/lib/ruby-debug/commands/control.rb +129 -0
  14. data/lib/ruby-debug/commands/enable.rb +203 -0
  15. data/lib/ruby-debug/commands/eval.rb +64 -0
  16. data/lib/ruby-debug/commands/frame.rb +155 -0
  17. data/lib/ruby-debug/commands/inspect.rb +24 -0
  18. data/lib/ruby-debug/commands/jump.rb +73 -0
  19. data/lib/ruby-debug/commands/load.rb +18 -0
  20. data/lib/ruby-debug/commands/stepping.rb +108 -0
  21. data/lib/ruby-debug/commands/threads.rb +153 -0
  22. data/lib/ruby-debug/commands/variables.rb +136 -0
  23. data/lib/ruby-debug/event_processor.rb +74 -0
  24. data/lib/ruby-debug/helper.rb +33 -0
  25. data/lib/ruby-debug/interface.rb +39 -0
  26. data/lib/ruby-debug/printers.rb +2 -0
  27. data/lib/ruby-debug/processor.rb +152 -0
  28. data/lib/ruby-debug/xml_printer.rb +268 -0
  29. data/test/rd_basic_test.rb +10 -0
  30. data/test/rd_catchpoint_test.rb +20 -0
  31. data/test/rd_condition_test.rb +11 -0
  32. data/test/rd_enable_disable_test.rb +43 -0
  33. data/test/rd_inspect_test.rb +11 -0
  34. data/test/rd_stepping_breakpoints_test.rb +36 -0
  35. data/test/rd_test_base.rb +44 -0
  36. data/test/rd_threads_and_frames_test.rb +11 -0
  37. data/test/rd_variables_test.rb +11 -0
  38. data/test/ruby-debug/xml_printer_test.rb +105 -0
  39. metadata +103 -0
@@ -0,0 +1,268 @@
1
+ require 'cgi'
2
+ require 'yaml'
3
+
4
+ module Debugger
5
+
6
+ class XmlPrinter # :nodoc:
7
+ attr_accessor :interface
8
+
9
+ def initialize(interface)
10
+ @interface = interface
11
+ end
12
+
13
+ def print_msg(*args)
14
+ msg, *args = args
15
+ xml_message = CGI.escapeHTML(msg % args)
16
+ print "<message>#{xml_message}</message>"
17
+ end
18
+
19
+ # Sends debug message to the frontend if XML debug logging flag (--xml-debug) is on.
20
+ def print_debug(*args)
21
+ Debugger.print_debug(*args)
22
+ if Debugger.xml_debug
23
+ msg, *args = args
24
+ xml_message = CGI.escapeHTML(msg % args)
25
+ @interface.print("<message debug='true'>#{xml_message}</message>")
26
+ end
27
+ end
28
+
29
+ def print_error(*args)
30
+ print_element("error") do
31
+ msg, *args = args
32
+ print CGI.escapeHTML(msg % args)
33
+ end
34
+ end
35
+
36
+ def print_frames(context, current_frame_id)
37
+ print_element("frames") do
38
+ (0...context.stack_size).each do |id|
39
+ print_frame(context, id, current_frame_id)
40
+ end
41
+ end
42
+ end
43
+
44
+ def print_current_frame(frame_pos)
45
+ print_debug "Selected frame no #{frame_pos}"
46
+ end
47
+
48
+ def print_frame(context, frame_id, current_frame_id)
49
+ # idx + 1: one-based numbering as classic-debugger
50
+ file = context.frame_file(frame_id)
51
+ print "<frame no=\'%s\' file=\'%s\' line=\'%s\' #{"current='true' " if frame_id == current_frame_id}/>",
52
+ frame_id + 1, File.expand_path(file), context.frame_line(frame_id)
53
+ end
54
+
55
+ def print_contexts(contexts)
56
+ print_element("threads") do
57
+ contexts.each do |c|
58
+ print_context(c) unless c.ignored?
59
+ end
60
+ end
61
+ end
62
+
63
+ def print_context(context)
64
+ current = 'current="yes"' if context.thread == Thread.current
65
+ print "<thread id=\"%s\" status=\"%s\" #{current}/>", context.thnum, context.thread.status
66
+ end
67
+
68
+ def print_variables(vars, kind)
69
+ print_element("variables") do
70
+ # print self at top position
71
+ print_variable('self', yield('self'), kind) if vars.include?('self')
72
+ vars.sort.each do |v|
73
+ print_variable(v, yield(v), kind) unless v == 'self'
74
+ end
75
+ end
76
+ end
77
+
78
+ def print_array(array)
79
+ print_element("variables") do
80
+ index = 0
81
+ array.each { |e|
82
+ print_variable('[' + index.to_s + ']', e, 'instance')
83
+ index += 1
84
+ }
85
+ end
86
+ end
87
+
88
+ def print_hash(hash)
89
+ print_element("variables") do
90
+ hash.keys.each { | k |
91
+ if k.class.name == "String"
92
+ name = '\'' + k + '\''
93
+ else
94
+ name = k.to_s
95
+ end
96
+ print_variable(name, hash[k], 'instance')
97
+ }
98
+ end
99
+ end
100
+
101
+ def print_variable(name, value, kind)
102
+ name = name.to_s
103
+ unless value
104
+ print("<variable name=\"%s\" kind=\"%s\"/>", CGI.escapeHTML(name), kind)
105
+ return
106
+ end
107
+ if value.is_a?(Array) || value.is_a?(Hash)
108
+ has_children = !value.empty?
109
+ unless has_children
110
+ value_str = "Empty #{value.class}"
111
+ else
112
+ value_str = "#{value.class} (#{value.size} element(s))"
113
+ end
114
+ else
115
+ has_children = !value.instance_variables.empty? || !value.class.class_variables.empty?
116
+ value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #$!>"
117
+ unless value_str.is_a?(String)
118
+ value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String."
119
+ end
120
+ if value_str =~ /^\"(.*)"$/
121
+ value_str = $1
122
+ end
123
+ end
124
+ value_str = "[Binary Data]" if value_str.is_binary_data?
125
+ print("<variable name=\"%s\" kind=\"%s\" value=\"%s\" type=\"%s\" hasChildren=\"%s\" objectId=\"%#+x\"/>",
126
+ CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class,
127
+ has_children, value.respond_to?(:object_id) ? value.object_id : value.id)
128
+ end
129
+
130
+ def print_breakpoints(breakpoints)
131
+ print_element 'breakpoints' do
132
+ breakpoints.sort_by{|b| b.id }.each do |b|
133
+ print "<breakpoint n=\"%d\" file=\"%s\" line=\"%s\" />", b.id, b.source, b.pos.to_s
134
+ end
135
+ end
136
+ end
137
+
138
+ def print_breakpoint_added(b)
139
+ print "<breakpointAdded no=\"%s\" location=\"%s:%s\"/>", b.id, b.source, b.pos
140
+ end
141
+
142
+ def print_breakpoint_deleted(b)
143
+ print "<breakpointDeleted no=\"%s\"/>", b.id
144
+ end
145
+
146
+ def print_breakpoint_enabled(b)
147
+ print "<breakpointEnabled bp_id=\"%s\"/>", b.id
148
+ end
149
+
150
+ def print_breakpoint_disabled(b)
151
+ print "<breakpointDisabled bp_id=\"%s\"/>", b.id
152
+ end
153
+
154
+ def print_contdition_set(bp_id)
155
+ print "<conditionSet bp_id=\"%d\"/>", bp_id
156
+ end
157
+
158
+ def print_catchpoint_set(exception_class_name)
159
+ print "<catchpointSet exception=\"%s\"/>", exception_class_name
160
+ end
161
+
162
+ def print_expressions(exps)
163
+ print_element "expressions" do
164
+ exps.each_with_index do |(exp, value), idx|
165
+ print_expression(exp, value, idx+1)
166
+ end
167
+ end unless exps.empty?
168
+ end
169
+
170
+ def print_expression(exp, value, idx)
171
+ print "<dispay name=\"%s\" value=\"%s\" no=\"%d\" />", exp, value, idx
172
+ end
173
+
174
+ def print_eval(exp, value)
175
+ print "<eval expression=\"%s\" value=\"%s\" />", CGI.escapeHTML(exp), value
176
+ end
177
+
178
+ def print_pp(value)
179
+ print value
180
+ end
181
+
182
+ def print_list(b, e, file, line)
183
+ print "[%d, %d] in %s\n", b, e, file
184
+ if lines = Debugger.source_for(file)
185
+ b.upto(e) do |n|
186
+ if n > 0 && lines[n-1]
187
+ if n == line
188
+ print "=> %d %s\n", n, lines[n-1].chomp
189
+ else
190
+ print " %d %s\n", n, lines[n-1].chomp
191
+ end
192
+ end
193
+ end
194
+ else
195
+ print "No sourcefile available for %s\n", file
196
+ end
197
+ end
198
+
199
+ def print_methods(methods)
200
+ print_element "methods" do
201
+ methods.each do |method|
202
+ print "<method name=\"%s\" />", method
203
+ end
204
+ end
205
+ end
206
+
207
+ # Events
208
+
209
+ def print_breakpoint(n, breakpoint)
210
+ print("<breakpoint file=\"%s\" line=\"%s\" threadId=\"%d\"/>",
211
+ breakpoint.source, breakpoint.pos, Debugger.current_context.thnum)
212
+ end
213
+
214
+ def print_catchpoint(exception)
215
+ context = Debugger.current_context
216
+ print("<exception file=\"%s\" line=\"%s\" type=\"%s\" message=\"%s\" threadId=\"%d\"/>",
217
+ context.frame_file(0), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum)
218
+ end
219
+
220
+ def print_trace(context, file, line)
221
+ Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, context.thnum
222
+ # TBD: do we want to clog fronend with the <trace> elements? There are tons of them.
223
+ # print "<trace file=\"%s\" line=\"%s\" threadId=\"%d\" />", file, line, context.thnum
224
+ end
225
+
226
+ def print_at_line(context, file, line)
227
+ print "<suspended file=\'%s\' line=\'%s\' threadId=\'%d\' frames=\'%d\'/>",
228
+ File.expand_path(file), line, context.thnum, context.stack_size
229
+ end
230
+
231
+ def print_exception(exception, binding)
232
+ print "<processingException type=\"%s\" message=\"%s\"/>",
233
+ exception.class, CGI.escapeHTML(exception.to_s)
234
+ end
235
+
236
+ def print_inspect(eval_result)
237
+ print_element("variables") do
238
+ print_variable("eval_result", eval_result, 'local')
239
+ end
240
+ end
241
+
242
+ def print_load_result(file, exception=nil)
243
+ if exception then
244
+ print("<loadResult file=\"%s\" exceptionType=\"%s\" exceptionMessage=\"%s\"/>", file, exception.class, CGI.escapeHTML(exception.to_s))
245
+ else
246
+ print("<loadResult file=\"%s\" status=\"OK\"/>", file)
247
+ end
248
+ end
249
+
250
+ def print_element(name)
251
+ print("<#{name}>")
252
+ begin
253
+ yield
254
+ ensure
255
+ print("</#{name}>")
256
+ end
257
+ end
258
+
259
+ private
260
+
261
+ def print(*params)
262
+ Debugger::print_debug(*params)
263
+ @interface.print(*params)
264
+ end
265
+
266
+ end
267
+
268
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'basic_test'
4
+ require 'rd_test_base'
5
+
6
+ class RDSteppingAndBreakpointsTest < RDTestBase
7
+
8
+ include BasicTest
9
+
10
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rd_test_base'
4
+
5
+ class RDCatchpointTest < RDTestBase
6
+
7
+ def test_catchpoint_basics
8
+ create_socket ['sleep 0.01', '5/0', 'sleep 0.01']
9
+ run_to_line(1)
10
+ send_next
11
+ assert_suspension(@test_path, 2, 1)
12
+ send_ruby('catch ZeroDivisionError')
13
+ assert_catchpoint_set('ZeroDivisionError')
14
+ send_next
15
+ assert_exception(@test_path, 2, 'ZeroDivisionError')
16
+ send_next
17
+ end
18
+
19
+ end
20
+
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rd_test_base'
4
+ require 'condition_test'
5
+
6
+ class RDConditionTest < RDTestBase
7
+
8
+ include ConditionTest
9
+
10
+ end
11
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rd_test_base'
4
+
5
+ class RDEnableDisableTest < RDTestBase
6
+
7
+ def test_enable_disable_basics
8
+ create_socket ['1.upto(10) do', 'sleep 0.01', 'sleep 0.01', 'end']
9
+
10
+ send_test_breakpoint(2)
11
+ assert_breakpoint_added_no(1)
12
+ send_test_breakpoint(3)
13
+ assert_breakpoint_added_no(2)
14
+
15
+ start_debugger
16
+ assert_test_breakpoint(2)
17
+ send_cont
18
+ assert_test_breakpoint(3)
19
+ send_cont
20
+ assert_test_breakpoint(2)
21
+ send_ruby('disable 2')
22
+ assert_breakpoint_disabled(2)
23
+ send_cont
24
+ assert_test_breakpoint(2)
25
+ send_cont
26
+ assert_test_breakpoint(2)
27
+ send_ruby('enable 2')
28
+ assert_breakpoint_enabled(2)
29
+ send_cont
30
+ assert_test_breakpoint(3)
31
+ send_cont
32
+ assert_test_breakpoint(2)
33
+ send_cont
34
+ assert_test_breakpoint(3)
35
+ send_ruby('disable 1')
36
+ assert_breakpoint_disabled(1)
37
+ send_ruby('disable 2')
38
+ assert_breakpoint_disabled(2)
39
+ send_cont
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rd_test_base'
4
+ require 'inspect_test'
5
+
6
+ class RDInspectTest < RDTestBase
7
+
8
+ include InspectTest
9
+
10
+ end
11
+
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rd_test_base'
4
+ require 'stepping_breakpoints_test'
5
+
6
+ class RDSteppingAndBreakpointsTest < RDTestBase
7
+
8
+ include SteppingAndBreakpointsTest
9
+
10
+ def test_hit_breakpoint_while_stepping_over
11
+ create_test2 ["class Test2", "def print", "puts 'XX'", "puts 'XX'", "end", "end"]
12
+ create_socket ["require 'test2.rb'", "Test2.new.print", "puts 'a'"]
13
+ send_ruby("b #{@test2_name}:4")
14
+ assert_breakpoint_added_no(1)
15
+ run_to_line(2)
16
+ send_next
17
+ assert_breakpoint(@test2_name, 4)
18
+ send_cont
19
+ end
20
+
21
+ def test_breakpoint_and_continue_from_other_file
22
+ create_test2 ["class Test2", "def print12", "puts 'one'","puts 'two'", "end", "end"]
23
+ create_socket ["require 'test2.rb'", "Test2.new.print12", "puts 'three'"]
24
+ send_test_breakpoint(2)
25
+ assert_breakpoint_added_no(1)
26
+ send_ruby("b #{@test2_name}:4")
27
+ assert_breakpoint_added_no(2)
28
+ start_debugger
29
+ assert_test_breakpoint(2)
30
+ send_next # test:1 -> test2:4
31
+ assert_breakpoint(@test2_name, 4)
32
+ send_cont # test2:4 -> test:3
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "test-base")
4
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
5
+
6
+ require 'test_base'
7
+
8
+ class RDTestBase < TestBase
9
+
10
+ def setup
11
+ super
12
+ @rdebug_ide = config_load('rdebug_ide', true) || find_rdebug_ide
13
+ unless @rdebug_ide and File.exist?(@rdebug_ide)
14
+ @fast_fail = true
15
+ assert_not_nil(@rdebug_ide, "Cannot find rdebug-ide executable. " +
16
+ "Neither set in the config(.private).yaml nor found on the PATH")
17
+ assert(false, "#{@rdebug_ide} exist")
18
+ end
19
+ end
20
+
21
+ def debug_command(script, port)
22
+ cmd = "#{interpreter}"
23
+ cmd << " --debug" if jruby?
24
+ cmd << " -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" if jruby? and debug_jruby?
25
+ cmd << " -I '#{File.dirname(script)}' #{@rdebug_ide} _0.4.9_" +
26
+ (@verbose_server ? " -d" : "") +
27
+ " -p #{port} -- '#{script}'"
28
+ end
29
+
30
+ def start_debugger
31
+ send_ruby("start")
32
+ end
33
+
34
+ private
35
+
36
+ def find_rdebug_ide
37
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
38
+ rdebug_ide = File.join(dir, 'rdebug-ide')
39
+ return rdebug_ide if File.exists?(rdebug_ide)
40
+ end
41
+ nil
42
+ end
43
+
44
+ end