debugger-ide 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,152 @@
1
+ if RUBY_VERSION < "1.9"
2
+ require 'ruby-debug/interface'
3
+ require 'ruby-debug/command'
4
+ else
5
+ require_relative 'interface'
6
+ require_relative 'command'
7
+ end
8
+
9
+ module Debugger
10
+
11
+ class ControlCommandProcessor # :nodoc:
12
+ def initialize(interface)
13
+ @interface = interface
14
+ @printer = XmlPrinter.new(@interface)
15
+ end
16
+
17
+ def print(*args)
18
+ @interface.print(*args)
19
+ end
20
+
21
+ def process_commands
22
+ @printer.print_debug("Starting command read loop")
23
+ ctrl_cmd_classes = Command.commands.select{|cmd| cmd.control}
24
+ state = ControlState.new(@interface)
25
+ ctrl_cmds = ctrl_cmd_classes.map{|cmd| cmd.new(state, @printer)}
26
+
27
+ while input = @interface.read_command
28
+ # escape % since print_debug might use printf
29
+ @printer.print_debug "Processing: #{input.gsub('%', '%%')}"
30
+ # sleep 0.3
31
+ catch(:debug_error) do
32
+ if cmd = ctrl_cmds.find{|c| c.match(input) }
33
+ cmd.execute
34
+ else
35
+ process_context_commands(input)
36
+ end
37
+ end
38
+ end
39
+ rescue IOError, Errno::EPIPE
40
+ @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil
41
+ @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil
42
+ rescue Exception
43
+ @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil
44
+ @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil
45
+ ensure
46
+ @interface.close
47
+ end
48
+
49
+ def process_context_commands(input)
50
+ unless Debugger.event_processor.at_line?
51
+ @printer.print_error "There is no thread suspended at the time and therefore no context to execute '#{input.gsub('%', '%%')}'"
52
+ return
53
+ end
54
+ context = Debugger.event_processor.context
55
+ file = Debugger.event_processor.file
56
+ line = Debugger.event_processor.line
57
+ event_cmds_classes = Command.commands.select{|cmd| cmd.event}
58
+ state = State.new do |s|
59
+ s.context = context
60
+ s.file = file
61
+ s.line = line
62
+ s.binding = context.frame_binding(0)
63
+ s.interface = @interface
64
+ end
65
+ event_cmds = event_cmds_classes.map{|cmd| cmd.new(state, @printer) }
66
+ catch(:debug_error) do
67
+ splitter[input].each do |input|
68
+ # escape % since print_debug might use printf
69
+ @printer.print_debug "Processing context: #{input.gsub('%', '%%')}"
70
+ if cmd = event_cmds.find{ |c| c.match(input) }
71
+ if context.dead? && cmd.class.need_context
72
+ @printer.print_msg "Command is unavailable\n"
73
+ else
74
+ cmd.execute
75
+ end
76
+ else
77
+ @printer.print_msg "Unknown command: #{input}"
78
+ end
79
+ end
80
+ end
81
+
82
+ context.thread.run if state.proceed?
83
+ end
84
+
85
+ def splitter
86
+ return lambda do |str|
87
+ str.split(/;/).inject([]) do |m, v|
88
+ if m.empty?
89
+ m << v
90
+ else
91
+ if m.last[-1] == ?\\
92
+ m.last[-1,1] = ''
93
+ m.last << ';' << v
94
+ else
95
+ m << v
96
+ end
97
+ end
98
+ m
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class State # :nodoc:
105
+
106
+ attr_accessor :context, :file, :line, :binding
107
+ attr_accessor :frame_pos, :previous_line
108
+ attr_accessor :interface
109
+
110
+ def initialize
111
+ @frame_pos = 0
112
+ @previous_line = nil
113
+ @proceed = false
114
+ yield self
115
+ end
116
+
117
+ def print(*args)
118
+ @interface.print(*args)
119
+ end
120
+
121
+ def proceed?
122
+ @proceed
123
+ end
124
+
125
+ def proceed
126
+ @proceed = true
127
+ end
128
+ end
129
+
130
+ class ControlState # :nodoc:
131
+
132
+ def initialize(interface)
133
+ @interface = interface
134
+ end
135
+
136
+ def proceed
137
+ end
138
+
139
+ def print(*args)
140
+ @interface.print(*args)
141
+ end
142
+
143
+ def context
144
+ nil
145
+ end
146
+
147
+ def file
148
+ print "ERROR: No filename given.\n"
149
+ throw :debug_error
150
+ end
151
+ end
152
+ end
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debugger-ide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-23 00:00:00.000000000 Z
12
+ date: 2012-10-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debugger
@@ -37,7 +37,33 @@ executables:
37
37
  extensions: []
38
38
  extra_rdoc_files: []
39
39
  files:
40
+ - lib/ruby-debug/command.rb
41
+ - lib/ruby-debug/commands/breakpoints.rb
42
+ - lib/ruby-debug/commands/catchpoint.rb
43
+ - lib/ruby-debug/commands/condition.rb
44
+ - lib/ruby-debug/commands/control.rb
45
+ - lib/ruby-debug/commands/enable.rb
46
+ - lib/ruby-debug/commands/eval.rb
47
+ - lib/ruby-debug/commands/frame.rb
48
+ - lib/ruby-debug/commands/inspect.rb
49
+ - lib/ruby-debug/commands/jump.rb
50
+ - lib/ruby-debug/commands/load.rb
51
+ - lib/ruby-debug/commands/pause.rb
52
+ - lib/ruby-debug/commands/set_type.rb
53
+ - lib/ruby-debug/commands/stepping.rb
54
+ - lib/ruby-debug/commands/threads.rb
55
+ - lib/ruby-debug/commands/variables.rb
56
+ - lib/ruby-debug/event_processor.rb
57
+ - lib/ruby-debug/helper.rb
58
+ - lib/ruby-debug/interface.rb
59
+ - lib/ruby-debug/printers.rb
60
+ - lib/ruby-debug/processor.rb
61
+ - lib/ruby-debug/xml_printer.rb
62
+ - lib/ruby-debug-ide.rb
40
63
  - bin/rdebug-ide
64
+ - Gemfile
65
+ - MIT-LICENSE
66
+ - Rakefile
41
67
  homepage: http://github.com/astashov/debugger-ide
42
68
  licenses: []
43
69
  post_install_message: