debugger-ide 0.0.1 → 0.0.2

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.
@@ -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: