arcadia 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ name=debug
2
+ label=Debug
3
+ frame=1.0
4
+ active=yes
5
+ require=ext/ae-debug/ae-debug
6
+ class=ArcadiaDebug
7
+
@@ -0,0 +1,582 @@
1
+ #
2
+ # ae-debug.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+
6
+ require "observer"
7
+
8
+ class ArcadiaDebugWrapper
9
+ include Observable
10
+ attr_reader :last_command
11
+
12
+ def initialize
13
+ (RUBY_PLATFORM == 'i386-mswin32')?_cmd="cmd":_cmd='sh'
14
+ @io = IO.popen(_cmd,'w')
15
+ @last_command = _cmd
16
+ @stop = false
17
+ @transfer_file=ArcadiaDebugWrapper.transfer_file
18
+ @threads = Array.new
19
+ end
20
+
21
+ def ArcadiaDebugWrapper.transfer_file
22
+ '~transfer-debug-file.tmp'
23
+ end
24
+
25
+ def start_debug(_file=nil)
26
+ @breakpoint_id=0
27
+ @file=_file
28
+ if File.exist?(@transfer_file)
29
+ File.delete(@transfer_file)
30
+ end
31
+ if _file
32
+ @main_thread = Thread.new{
33
+ command($arcadia['conf']['shell.ruby']+" -r ext/ae-debug/debug1.57 "+_file)
34
+ @last_command = 'debug'
35
+ read
36
+ }
37
+ end
38
+ end
39
+
40
+ def quit_debug
41
+ command("q\ny\n")
42
+ command("exit\n")
43
+ @threads.each{|t|
44
+ if t.alive?
45
+ t.kill
46
+ end
47
+ }
48
+ @main_thread.kill
49
+ end
50
+
51
+ def step_over
52
+ @threads << Thread.new{
53
+ command("n")
54
+ read
55
+ }
56
+ end
57
+
58
+ def step_into
59
+ @threads << Thread.new{
60
+ command("s")
61
+ read
62
+ }
63
+ end
64
+
65
+ def resume
66
+ Thread.new{
67
+ command("c")
68
+ read
69
+ }
70
+ end
71
+
72
+ def finish
73
+ Thread.new{
74
+ command("fin")
75
+ read
76
+ }
77
+ end
78
+
79
+ def v_global
80
+ @threads << Thread.new{
81
+ command("v g")
82
+ read
83
+ }
84
+ end
85
+
86
+ def v_local
87
+ @threads << Thread.new{
88
+ command("v l")
89
+ read
90
+ }
91
+ end
92
+
93
+ def v_instance(_obj)
94
+ @threads << Thread.new{
95
+ command("v i "+_obj)
96
+ read
97
+ }
98
+ end
99
+
100
+ def breakpoint_set(_pos, _context=nil)
101
+ @threads << Thread.new{
102
+ if _context
103
+ command("b "+_context+':'+_pos)
104
+ else
105
+ command("b "+_pos)
106
+ end
107
+ read
108
+ }
109
+ @breakpoint_id = @breakpoint_id + 1 if @breakpoint_id
110
+ end
111
+
112
+ def breckpoint_del(_id)
113
+ @threads << Thread.new{
114
+ if _id
115
+ command("del "+_id)
116
+ else
117
+ command("del")
118
+ end
119
+ read
120
+ }
121
+ end
122
+
123
+ def command(_command)
124
+ begin
125
+ @io.puts(_command)
126
+ @last_command = _command
127
+ rescue Exception => e
128
+ $arcadia.outln("\n"+" error on :"+" command >>> "+_command+' : '+e.to_s ) if $arcadia
129
+ end
130
+ end
131
+
132
+ def stop
133
+ @stop = true
134
+ end
135
+
136
+ def read
137
+ begin
138
+ while !File.exist?(@transfer_file)
139
+ end
140
+ if File.exist?(@transfer_file)
141
+ while !File.stat(@transfer_file).readable?
142
+ end
143
+ File.open(@transfer_file) do |f|
144
+ $ppp = Marshal.load(f)
145
+ end
146
+ while !File.stat(@transfer_file).writable?
147
+ end
148
+ File.delete(@transfer_file) if File.exist?(@transfer_file)
149
+ changed
150
+ notify_observers($ppp)
151
+ end
152
+ rescue Exception => e
153
+ MsgContract.instance.out_debug(self, "\n"+'Error on : '+" read >>> "+@transfer_file+" : "+e.to_s )
154
+ #$arcadia.outln("\n read >>> "+@transfer_file+" � andato in errore :"+e.to_s ) if $arcadia
155
+ end
156
+ end
157
+ end
158
+
159
+ class ArcadiaDebug < ArcadiaExt
160
+
161
+ def before_build
162
+ ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
163
+ @breakpoints = Hash.new
164
+ @static_breakpoints = Array.new
165
+ end
166
+
167
+ def build
168
+ end
169
+
170
+ def debug_state
171
+ end
172
+
173
+ def breakpoint_suf(_file,_line)
174
+ return _line.to_s + "-" + _file.to_s
175
+ end
176
+
177
+ def breakpoint_add(_file,_line)
178
+ if @adw
179
+ @breakpoints[breakpoint_suf(_file,_line)] = @adw.breakpoint_set(_line, _file)
180
+ else
181
+ @static_breakpoints << {:file=>_file,:line=>_line}
182
+ end
183
+ end
184
+
185
+ def breakpoint_del(_file,_line)
186
+ if @adw
187
+ @adw.breakpoint_del(@breakpoints.delete(breakpoint_suf(_file,_line)))
188
+ end
189
+ @static_breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
190
+ end
191
+
192
+ def do_editor_event(_event)
193
+ #@arcadia.outln('in debug _sender ----> '+_sender.to_s)
194
+ #@arcadia.outln('in debug _event.signature ----> '+_event.signature)
195
+ case _event.signature
196
+ when EditorContract::BREAKPOINT_AFTER_CREATE
197
+ self.breakpoint_add(_event.context.file, _event.context.line)
198
+ when EditorContract::BREAKPOINT_AFTER_DELETE
199
+ self.breakpoint_del(_event.context.file, _event.context.line)
200
+ when EditorContract::BUFFER_AFTER_RAISE
201
+ @raised_file=_event.context.file
202
+ end
203
+ end
204
+
205
+ def can_exit_query
206
+ if @adw
207
+ query = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
208
+ 'title' => '(Arcadia) Debug',
209
+ 'message' => "Debug in course, do you want to exit?")=='yes')
210
+ if query
211
+ debug_quit
212
+ return true
213
+ else
214
+ return false
215
+ end
216
+ else
217
+ return true
218
+ end
219
+ end
220
+
221
+ class VariablesViewText < TkTitledFrame
222
+ attr_reader :text
223
+
224
+ def initialize(parent=nil, title='...', maximize_to=nil ,keys=nil)
225
+ super(parent, title, maximize_to, keys)
226
+ @top_label.configure(:background => 'red')
227
+ @text = TkText.new(self.frame,
228
+ 'relief' => 'flat',
229
+ 'wrap' => 'none'
230
+ ){|j|
231
+ parent = TkWinfo.parent(j)
232
+ TkScrollbar.new(parent){|s|
233
+ command proc{|*args| j.yview(*args)}
234
+ j.yscrollcommand proc{|first,last| s.set first,last}
235
+ }.pack('side'=>'right', 'fill'=>'y')
236
+ TkScrollbar.new(parent){|s|
237
+ command proc{|*args| j.xview(*args)}
238
+ orient 'horizontal'
239
+ j.xscrollcommand proc{|first,last| s.set first,last}
240
+ }.pack('side'=>'bottom', 'fill'=>'x')
241
+ }.place(
242
+ 'relwidth' => '1',
243
+ 'relx' => 0,
244
+ 'x' => '0',
245
+ 'y' => '0',
246
+ 'relheight' => '1',
247
+ 'rely' => 0,
248
+ 'height' => '-15',
249
+ 'bordermode' =>
250
+ 'inside',
251
+ 'width' => '-15'
252
+ )
253
+ place('x'=>0, 'y'=>0,'relheight'=>1, 'relwidth'=>1)
254
+ end
255
+ end
256
+
257
+ class VariablesViewProperties < TkTitledScrollFrame
258
+ attr_reader :inspector
259
+
260
+ def initialize(parent=nil, title='...', maximize_to=nil ,keys=nil)
261
+ super(parent, title, maximize_to, keys)
262
+ @inspector=InspectListReadOnly.new(self.frame.cwin)
263
+ place('x'=>0, 'y'=>0,'relheight'=>1, 'relwidth'=>1)
264
+ end
265
+
266
+ end
267
+
268
+
269
+ class ArcadiaDebugInfo
270
+
271
+ def initialize(_parent=nil)
272
+ @nb = Tk::BWidget::NoteBook.new(_parent){
273
+ tabbevelsize 0
274
+ internalborderwidth 2
275
+ activeforeground 'red'
276
+ activebackground 'yellow'
277
+ borderwidth 1
278
+ side $arcadia['conf']['editor.tabs.side']
279
+ font $arcadia['conf']['editor.tabs.font']
280
+ pack('fill'=>'both', :expand => 'yes')
281
+ }
282
+
283
+ @nb_variables = @nb.insert('end','var' ,'text'=>'Variables' )
284
+
285
+ @hsplitter = AGTkOSplittedFrames.new(@nb_variables,220)
286
+
287
+ @hsplitter2 = AGTkOSplittedFrames.new(@hsplitter.top_frame,80)
288
+ @vvl=VariablesViewText.new(@hsplitter2.top_frame,'Local')
289
+ @vvi=VariablesViewText.new(@hsplitter2.bottom_frame,'Instance(self)')
290
+ @vvg=VariablesViewText.new(@hsplitter.bottom_frame,'Global')
291
+ font = $arcadia['conf']['inspectors.debug.tabs.font']
292
+ font_b = $arcadia['conf']['inspectors.debug.tabs.font.bold']
293
+ @vvl.text.tag_configure('key',
294
+ 'foreground' => 'blue',
295
+ 'font'=> font
296
+ )
297
+ @vvl.text.tag_configure('value',
298
+ 'foreground' => 'black',
299
+ 'font'=> font
300
+ )
301
+ @vvl.text.tag_configure('sep',
302
+ 'foreground' => 'gray',
303
+ 'font'=> font
304
+ )
305
+
306
+ @vvi.text.tag_configure('key',
307
+ 'foreground' => 'blue',
308
+ 'font'=> font
309
+ )
310
+
311
+ @vvi.text.tag_configure('value',
312
+ 'foreground' => 'black',
313
+ 'font'=> font
314
+ )
315
+
316
+ @vvi.text.tag_configure('sep',
317
+ 'foreground' => 'gray',
318
+ 'font'=> font
319
+ )
320
+
321
+ @vvg.text.tag_configure('key',
322
+ 'foreground' => '#018869',
323
+ 'font'=> font
324
+ )
325
+
326
+ @vvg.text.tag_configure('value',
327
+ 'foreground' => 'black' ,
328
+ 'font'=> font
329
+ )
330
+
331
+ @vvg.text.tag_configure('sep',
332
+ 'foreground' => 'gray',
333
+ 'font'=> font
334
+ )
335
+
336
+ @nb.raise('var')
337
+ end
338
+
339
+ def hash_to_str(_hash, _ind=0)
340
+ str = ''
341
+ _hash.each{|key,val|
342
+ str = str + "/s"*_ind+ key.to_s+' => '+val.to_s+"\n"
343
+ if val.kind_of?(Hash)
344
+ str = str + hash_to_str(val,_ind+2)
345
+ end
346
+ }
347
+ return str
348
+ end
349
+
350
+ def update_globals(_vars)
351
+ @vvg.text.delete('1.0','end')
352
+ if _vars != nil
353
+ str = ''
354
+ _vars.each{|key,val|
355
+ @vvg.text.insert('end',key.to_s.ljust(18),'key')
356
+ @vvg.text.insert('end','','sep')
357
+ @vvg.text.insert('end',val.to_s+"\n",'value')
358
+ }
359
+ end
360
+ end
361
+ def update_locals(_vars)
362
+ @vvl.text.delete('1.0','end')
363
+ if _vars != nil
364
+ # @vvl.inspector.updatelines(_vars)
365
+ _vars.each{|key,val|
366
+ @vvl.text.insert('end',key.to_s.ljust(18),'key')
367
+ @vvl.text.insert('end','','sep')
368
+ @vvl.text.insert('end',val.to_s+"\n",'value')
369
+ }
370
+ end
371
+ end
372
+
373
+ def update_instances(_vars)
374
+ @vvi.text.delete('1.0','end')
375
+ if _vars != nil
376
+ _vars.each{|key,val|
377
+ @vvi.text.insert('end',key.to_s.ljust(18),'key')
378
+ @vvi.text.insert('end','','sep')
379
+ @vvi.text.insert('end',val.to_s+"\n",'value')
380
+ }
381
+ end
382
+ end
383
+
384
+ end
385
+
386
+
387
+ def debug_begin
388
+ @breakpoints.clear
389
+ DebugContract.instance.debug_begin(DebugContract::TDebugObj.new(self))
390
+ end
391
+
392
+
393
+ def debug_last
394
+ debug($arcadia['pers']['run.file.last'])
395
+ end
396
+
397
+ def debug_current
398
+ debug(@raised_file) if @raised_file!=nil
399
+ end
400
+
401
+ def debug(_filename=nil)
402
+ if _filename
403
+ begin
404
+ self.debug_begin
405
+ @debug_button_box = Tk::BWidget::ButtonBox.new(self.frame){
406
+ homogeneous true
407
+ }.pack('anchor'=>'w')#('fill'=>'x')
408
+ @debug_button_box.add(
409
+ 'name'=>'debug_next',
410
+ 'command'=>proc{self.debug_next},
411
+ 'helptext'=>'step next',
412
+ 'image'=> TkPhotoImage.new('dat' => DEBUG_NEXT_GIF),
413
+ 'relief'=>'flat'
414
+ )
415
+ @debug_button_box.add(
416
+ 'name'=>'debug_into',
417
+ 'command'=>proc{self.debug_into},
418
+ 'helptext'=>'step into',
419
+ 'image'=> TkPhotoImage.new('dat' => DEBUG_INTO_GIF),
420
+ 'relief'=>'flat'
421
+ )
422
+ @debug_button_box.add(
423
+ 'name'=>'debug_fin',
424
+ 'helptext'=>'step over',
425
+ 'command'=>proc{self.debug_fin},
426
+ 'image'=> TkPhotoImage.new('dat' => DEBUG_OUT_GIF),
427
+ 'relief'=>'flat'
428
+ )
429
+ @debug_button_box.add(
430
+ 'name'=>'debug_resume',
431
+ 'helptext'=>'resume',
432
+ 'image'=> TkPhotoImage.new('dat' => DEBUG_RESUME_GIF),
433
+ 'command'=>proc{self.debug_resume},
434
+ 'relief'=>'flat'
435
+ )
436
+
437
+ @debug_button_box.configure(:state=>'disabled')
438
+ @debug_info = ArcadiaDebugInfo.new(self.frame)
439
+ $arcadia['pers']['run.file.last']=_filename
440
+ @adw = ArcadiaDebugWrapper.new
441
+ @adw.add_observer(self)
442
+ @adw.start_debug(_filename)
443
+ #@arcadia['editor'].debug_begin
444
+ MsgContract.instance.out_simple(self,"\n<begin debug>")
445
+
446
+ #@arcadia['shell'].outln("\n<begin debug>")
447
+ rescue Exception => e
448
+ MsgContract.instance.out_debug(self,"---> "+e.to_s)
449
+ #@arcadia['shell'].outln("---> "+e.to_s )
450
+ end
451
+ end
452
+ end
453
+
454
+ def debug_next
455
+ if @adw
456
+ begin
457
+ @debug_button_box.configure(:state=>'disabled')
458
+ @adw.step_over
459
+ rescue Exception => e
460
+ MsgContract.instance.out_debug(self,"---> "+e.to_s)
461
+ #@arcadia['shell'].outln("---> "+e.to_s )
462
+ end
463
+ end
464
+ end
465
+
466
+ def debug_resume
467
+ if @adw
468
+ begin
469
+ @debug_button_box.configure(:state=>'disabled')
470
+ @adw.resume
471
+ rescue Exception => e
472
+ MsgContract.instance.out_debug(self, "debug_resume:---> "+e.to_s)
473
+ #@arcadia['shell'].outln("debug_resume:---> "+e.to_s )
474
+ end
475
+ end
476
+ end
477
+
478
+ def debug_into
479
+ if @adw
480
+ begin
481
+ @debug_button_box.configure(:state=>'disabled')
482
+ @adw.step_into
483
+ rescue Exception => e
484
+ MsgContract.instance.out_debug(self, "---> "+e.to_s)
485
+ # @arcadia['shell'].outln("---> "+e.to_s )
486
+ end
487
+ end
488
+ end
489
+
490
+ def debug_fin
491
+ if @adw
492
+ begin
493
+ @debug_button_box.configure(:state=>'disabled')
494
+ @adw.finish
495
+ rescue Exception => e
496
+ MsgContract.instance.out_debug(self, "---> "+e.to_s)
497
+ #@arcadia['shell'].outln("---> "+e.to_s )
498
+ end
499
+ end
500
+ end
501
+
502
+ def debug_quit
503
+
504
+ if @adw
505
+ begin
506
+ self.frame_free
507
+ #self.debug_end
508
+ @adw.quit_debug
509
+ @adw = nil
510
+ #$arcadia['editor'].debug_end
511
+ MsgContract.instance.out_debug(self, "\n<end debug>")
512
+
513
+ #@arcadia['shell'].outln("\n<end debug>")
514
+ rescue Exception => e
515
+ MsgContract.instance.out_debug(self, "debug_quit:---> "+e.to_s)
516
+ #@arcadia['shell'].outln("debug_quit:---> "+e.to_s )
517
+ end
518
+ end
519
+ end
520
+ def debug_wrapper
521
+ return @adw
522
+ end
523
+
524
+ def update(dbg)
525
+ tobj = DebugContract::TDebugObj.new(self)
526
+ tobj.file = dbg[:file]
527
+ tobj.line = dbg[:line]
528
+ #sobj = @ae_editor_talker.info
529
+ if dbg[:file] != nil
530
+ DebugContract.instance.debug_step(tobj)
531
+ #$arcadia['editor'].open_file_in_debug(dbg[:file], dbg[:line])
532
+ end
533
+ if @adw.last_command == 'debug' && @static_breakpoints.length > 0
534
+ #set breakpoint
535
+ @sindex = 0
536
+ _line = @static_breakpoints[@sindex][:line]
537
+ _file = @static_breakpoints[@sindex][:file]
538
+ self.breakpoint_add(_file, _line)
539
+ @sindex = @sindex + 1
540
+ return
541
+ elsif @adw.last_command[0..1] == 'b ' && @sindex < @static_breakpoints.length
542
+ _line = @static_breakpoints[@sindex][:line]
543
+ _file = @static_breakpoints[@sindex][:file]
544
+ self.breakpoint_add(_file, _line)
545
+ @sindex = @sindex + 1
546
+ return
547
+ end
548
+ if dbg[:error_text] != nil
549
+ str = "\n"+dbg[:file]+':'+dbg[:line].to_s
550
+ str = str + ":\t" +dbg[:error_text].to_s+'('+dbg[:error_class].to_s+')'
551
+ MsgContract.instance.out_debug(self, str)
552
+ #@arcadia['shell'].outln(str,'error')
553
+ end
554
+ if dbg[:callers] != nil
555
+ str = ''
556
+ dbg[:callers].each{|caller|
557
+ str = str+"\n from:"+caller.to_s
558
+ }
559
+
560
+ end
561
+ if str
562
+ MsgContract.instance.out_debug(self, str)
563
+ #@arcadia['shell'].outln(str)
564
+ end
565
+ update_variables(dbg)
566
+ @debug_button_box.configure(:state=>'normal')
567
+ end
568
+
569
+ def update_variables(dbg)
570
+ if @adw.last_command == 'v g'
571
+ @debug_info.update_globals(dbg[:variables])
572
+ @adw.v_local
573
+ elsif @adw.last_command == 'v l'
574
+ @debug_info.update_locals(dbg[:variables])
575
+ @adw.v_instance('self')
576
+ elsif @adw.last_command == 'v i self'
577
+ @debug_info.update_instances(dbg[:variables])
578
+ elsif @adw.last_command[0..1] !='v '
579
+ @adw.v_global
580
+ end
581
+ end
582
+ end