81 ^ self == Tools::BreakpointService |
81 ^ self == Tools::BreakpointService |
82 |
82 |
83 "Created: / 22-07-2013 / 14:01:17 / cg" |
83 "Created: / 22-07-2013 / 14:01:17 / cg" |
84 ! ! |
84 ! ! |
85 |
85 |
|
86 !BreakpointService methodsFor:'accessing'! |
|
87 |
|
88 breakpointAtLine:line |
|
89 |pos| |
|
90 |
|
91 breakpoints isNil ifTrue:[^ nil]. |
|
92 |
|
93 pos := textView characterPositionOfLine:line col:1. |
|
94 ^ breakpoints |
|
95 detect:[:each | each position = pos ] |
|
96 ifNone:[ |
|
97 breakpoints |
|
98 detect:[:each | each line == line and:[each position isNil ]] |
|
99 ifNone:[ nil ] |
|
100 ] |
|
101 |
|
102 "Modified: / 17-06-2011 / 13:59:17 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
103 "Modified (format): / 05-07-2011 / 21:33:23 / cg" |
|
104 ! |
|
105 |
|
106 breakpoints |
|
107 "/ Fixup breakpoint positions |
|
108 self fixupBreakpointPositions. |
|
109 ^ breakpoints |
|
110 |
|
111 "Modified: / 08-05-2014 / 14:02:25 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
112 ! |
|
113 |
|
114 removeAllBreakpoints |
|
115 breakpoints := OrderedCollection new. |
|
116 ! |
|
117 |
|
118 setOrToggleBreakpointAtLine:line |
|
119 |pos bpnt prepareFullBreakSupport mClass ok| |
|
120 |
|
121 "/ if true, setting a single breakpoint in a method will create |
|
122 "/ a whole set of invisible (and disabled) breakpoints in that method, |
|
123 "/ one for each line. |
|
124 "/ These can later be enabled in the debugger |
|
125 "/ (otherwise, the debugger's behavior is stupid, as it cannot recompile a method |
|
126 "/ to set additional breakpoints). |
|
127 "/ We accept the additional overhead, as we are in debug mode anyway. |
|
128 "/ prepareFullBreakSupport := false. |
|
129 prepareFullBreakSupport := true. |
|
130 |
|
131 codeView method isNil ifTrue:[ |
|
132 ^ self |
|
133 ]. |
|
134 |
|
135 textView reallyModified ifTrue:[ |
|
136 "/ leads to ugly behavior (method no longer found), if we allow |
|
137 "/ this... |
|
138 Dialog warn:'Please accept first (cannot set breakpoint while text is modified)'. |
|
139 ^ self |
|
140 ]. |
|
141 |
|
142 bpnt := self breakpointAtLine:line. |
|
143 bpnt isNil ifTrue:[ |
|
144 "/ no breakpoint there - create a new one as required (i.e. recompile) |
|
145 ok := (self canCreateOrToggleBreakpointAtLine:line). |
|
146 ok ifFalse:[ |
|
147 (currentMethod isMethodWithBreakpoints and:[ prepareFullBreakSupport ]) ifFalse:[ |
|
148 codeView topView class == DebugView ifTrue:[ |
|
149 (Dialog |
|
150 confirm:'Sorry, in an active method, I can only add new breakpoints in an already breakpointed method. |
|
151 (i.e. a method stopped at a method breakpoint or one which already has statement breakpoints) |
|
152 The reason is that the method needs to be recompiled for the breakpoint, which would not affect the method being currently executed. |
|
153 |
|
154 You can proceed to set the breakpoint, but it will only affect the next call into this method, not the current invocation.' |
|
155 yesLabel:'Set Breakpoint for Next Call' noLabel:'Ok') ifTrue:[ |
|
156 self halt. |
|
157 ok := true. |
|
158 ] |
|
159 ] ifFalse:[ |
|
160 Dialog warn:'Sorry, cannot add a new breakpoint here.'. |
|
161 ]. |
|
162 ] |
|
163 ]. |
|
164 ok ifTrue:[ |
|
165 prepareFullBreakSupport ifTrue:[ |
|
166 "/ add a (disabled) breakpoint for every source line. This |
|
167 "/ allows for breakpoints to be enabled/disabled in the debugger... |
|
168 1 to:textView numberOfLines do:[:eachLine | |
|
169 |oldBPnt eachPos otherBpnt| |
|
170 |
|
171 oldBPnt := self breakpointAtLine:eachLine. |
|
172 oldBPnt isNil ifTrue:[ |
|
173 eachPos := textView characterPositionOfLine:eachLine col:1. |
|
174 breakpoints isNil ifTrue:[ breakpoints := OrderedCollection new]. |
|
175 breakpoints add:((otherBpnt := Breakpoint new) position:eachPos line:eachLine). |
|
176 eachLine == line ifTrue:[ |
|
177 bpnt := otherBpnt. |
|
178 ] ifFalse:[ |
|
179 otherBpnt beInvisible. |
|
180 ] |
|
181 ]. |
|
182 ]. |
|
183 ] ifFalse:[ |
|
184 pos := textView characterPositionOfLine:line col:1. |
|
185 breakpoints add:((bpnt := Breakpoint new) position:pos line:line). |
|
186 ]. |
|
187 Screen current shiftDown ifTrue:[ |
|
188 "/ trace |
|
189 bpnt beTracepoint |
|
190 ]. |
|
191 self assert: breakpoints notEmptyOrNil. |
|
192 |
|
193 "/ recompile the method with breakpoints |
|
194 self recompile. |
|
195 ] |
|
196 ] ifFalse:[ |
|
197 "/ breakpoint already there - just enable/disable |
|
198 Screen current shiftDown ifTrue:[ |
|
199 bpnt toggleTracing |
|
200 ] ifFalse:[ |
|
201 bpnt toggle. |
|
202 ]. |
|
203 (mClass := currentMethod mclass) isNil ifTrue:[ |
|
204 "/ hack: ouch - was wrapped in the meantime; |
|
205 "/ hurry up and update. Should be done elsewhere (in codeView) |
|
206 self updateCurrentMethod. |
|
207 currentMethod notNil ifTrue:[ mClass := currentMethod mclass ]. |
|
208 ]. |
|
209 mClass notNil ifTrue:[ |
|
210 Smalltalk changed:#methodTrap with:(MethodTrapChangeNotificationParameter changeClass:mClass changeSelector:currentMethod selector). |
|
211 ]. |
|
212 ]. |
|
213 |
|
214 (bpnt notNil and:[bpnt isReached not]) ifTrue:[ |
|
215 | app | |
|
216 |
|
217 app := codeView application. |
|
218 (app respondsTo: #showInfo:) ifTrue:[ |
|
219 app showInfo: 'Cannot set breakpoint here, try another line...'. |
|
220 ]. |
|
221 codeView flash. |
|
222 ] ifFalse:[ |
|
223 gutterView redrawLine:line. |
|
224 ]. |
|
225 |
|
226 "Created: / 17-06-2011 / 13:45:22 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
227 "Modified: / 28-08-2013 / 14:45:36 / cg" |
|
228 "Modified: / 21-02-2014 / 17:36:11 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
229 ! ! |
|
230 |
86 !BreakpointService methodsFor:'change & update'! |
231 !BreakpointService methodsFor:'change & update'! |
87 |
232 |
88 update: aspect with: param from: sender |
233 update: aspect with: param from: sender |
89 aspect == #visibility ifTrue:[^ self]. |
234 aspect == #visibility ifTrue:[^ self]. |
90 aspect == #sizeOfView ifTrue:[^ self]. |
235 aspect == #sizeOfView ifTrue:[^ self]. |
270 |
415 |
271 "Created: / 17-06-2011 / 13:49:12 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
416 "Created: / 17-06-2011 / 13:49:12 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
272 ! ! |
417 ! ! |
273 |
418 |
274 !BreakpointService methodsFor:'private'! |
419 !BreakpointService methodsFor:'private'! |
275 |
|
276 breakpointAtLine:line |
|
277 |pos| |
|
278 |
|
279 breakpoints isNil ifTrue:[^ nil]. |
|
280 |
|
281 pos := textView characterPositionOfLine:line col:1. |
|
282 ^ breakpoints |
|
283 detect:[:each | each position = pos ] |
|
284 ifNone:[ |
|
285 breakpoints |
|
286 detect:[:each | each line == line and:[each position isNil ]] |
|
287 ifNone:[ nil ] |
|
288 ] |
|
289 |
|
290 "Modified: / 17-06-2011 / 13:59:17 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
291 "Modified (format): / 05-07-2011 / 21:33:23 / cg" |
|
292 ! |
|
293 |
|
294 breakpoints |
|
295 "/ Fixup breakpoint positions |
|
296 self fixupBreakpointPositions. |
|
297 ^ breakpoints |
|
298 |
|
299 "Modified: / 08-05-2014 / 14:02:25 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
300 ! |
|
301 |
420 |
302 fixupBreakpointPositions |
421 fixupBreakpointPositions |
303 breakpoints notEmptyOrNil ifTrue:[ |
422 breakpoints notEmptyOrNil ifTrue:[ |
304 breakpoints do:[:each | |
423 breakpoints do:[:each | |
305 | pos | |
424 | pos | |
428 ] |
547 ] |
429 |
548 |
430 "Created: / 05-07-2011 / 21:33:13 / cg" |
549 "Created: / 05-07-2011 / 21:33:13 / cg" |
431 "Modified: / 22-07-2013 / 16:00:13 / cg" |
550 "Modified: / 22-07-2013 / 16:00:13 / cg" |
432 "Modified: / 08-05-2014 / 14:03:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
551 "Modified: / 08-05-2014 / 14:03:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
433 ! |
|
434 |
|
435 setOrToggleBreakpointAtLine:line |
|
436 |pos bpnt prepareFullBreakSupport mClass ok| |
|
437 |
|
438 "/ if true, setting a single breakpoint in a method will create |
|
439 "/ a whole set of invisible (and disabled) breakpoints in that method, |
|
440 "/ one for each line. |
|
441 "/ These can later be enabled in the debugger |
|
442 "/ (otherwise, the debugger's behavior is stupid, as it cannot recompile a method |
|
443 "/ to set additional breakpoints). |
|
444 "/ We accept the additional overhead, as we are in debug mode anyway. |
|
445 "/ prepareFullBreakSupport := false. |
|
446 prepareFullBreakSupport := true. |
|
447 |
|
448 codeView method isNil ifTrue:[ |
|
449 ^ self |
|
450 ]. |
|
451 |
|
452 textView reallyModified ifTrue:[ |
|
453 "/ leads to ugly behavior (method no longer found), if we allow |
|
454 "/ this... |
|
455 Dialog warn:'Please accept first (cannot set breakpoint while text is modified)'. |
|
456 ^ self |
|
457 ]. |
|
458 |
|
459 bpnt := self breakpointAtLine:line. |
|
460 bpnt isNil ifTrue:[ |
|
461 "/ no breakpoint there - create a new one as required (i.e. recompile) |
|
462 ok := (self canCreateOrToggleBreakpointAtLine:line). |
|
463 ok ifFalse:[ |
|
464 (currentMethod isMethodWithBreakpoints and:[ prepareFullBreakSupport ]) ifFalse:[ |
|
465 codeView topView class == DebugView ifTrue:[ |
|
466 (Dialog |
|
467 confirm:'Sorry, in an active method, I can only add new breakpoints in an already breakpointed method. |
|
468 (i.e. a method stopped at a method breakpoint or one which already has statement breakpoints) |
|
469 The reason is that the method needs to be recompiled for the breakpoint, which would not affect the method being currently executed. |
|
470 |
|
471 You can proceed to set the breakpoint, but it will only affect the next call into this method, not the current invocation.' |
|
472 yesLabel:'Set Breakpoint for Next Call' noLabel:'Ok') ifTrue:[ |
|
473 self halt. |
|
474 ok := true. |
|
475 ] |
|
476 ] ifFalse:[ |
|
477 Dialog warn:'Sorry, cannot add a new breakpoint here.'. |
|
478 ]. |
|
479 ] |
|
480 ]. |
|
481 ok ifTrue:[ |
|
482 prepareFullBreakSupport ifTrue:[ |
|
483 "/ add a (disabled) breakpoint for every source line. This |
|
484 "/ allows for breakpoints to be enabled/disabled in the debugger... |
|
485 1 to:textView numberOfLines do:[:eachLine | |
|
486 |oldBPnt eachPos otherBpnt| |
|
487 |
|
488 oldBPnt := self breakpointAtLine:eachLine. |
|
489 oldBPnt isNil ifTrue:[ |
|
490 eachPos := textView characterPositionOfLine:eachLine col:1. |
|
491 breakpoints isNil ifTrue:[ breakpoints := OrderedCollection new]. |
|
492 breakpoints add:((otherBpnt := Breakpoint new) position:eachPos line:eachLine). |
|
493 eachLine == line ifTrue:[ |
|
494 bpnt := otherBpnt. |
|
495 ] ifFalse:[ |
|
496 otherBpnt beInvisible. |
|
497 ] |
|
498 ]. |
|
499 ]. |
|
500 ] ifFalse:[ |
|
501 pos := textView characterPositionOfLine:line col:1. |
|
502 breakpoints add:((bpnt := Breakpoint new) position:pos line:line). |
|
503 ]. |
|
504 Screen current shiftDown ifTrue:[ |
|
505 "/ trace |
|
506 bpnt beTracepoint |
|
507 ]. |
|
508 self assert: breakpoints notEmptyOrNil. |
|
509 |
|
510 "/ recompile the method with breakpoints |
|
511 self recompile. |
|
512 ] |
|
513 ] ifFalse:[ |
|
514 "/ breakpoint already there - just enable/disable |
|
515 Screen current shiftDown ifTrue:[ |
|
516 bpnt toggleTracing |
|
517 ] ifFalse:[ |
|
518 bpnt toggle. |
|
519 ]. |
|
520 (mClass := currentMethod mclass) isNil ifTrue:[ |
|
521 "/ hack: ouch - was wrapped in the meantime; |
|
522 "/ hurry up and update. Should be done elsewhere (in codeView) |
|
523 self updateCurrentMethod. |
|
524 currentMethod notNil ifTrue:[ mClass := currentMethod mclass ]. |
|
525 ]. |
|
526 mClass notNil ifTrue:[ |
|
527 Smalltalk changed:#methodTrap with:(MethodTrapChangeNotificationParameter changeClass:mClass changeSelector:currentMethod selector). |
|
528 ]. |
|
529 ]. |
|
530 |
|
531 (bpnt notNil and:[bpnt isReached not]) ifTrue:[ |
|
532 | app | |
|
533 |
|
534 app := codeView application. |
|
535 (app respondsTo: #showInfo:) ifTrue:[ |
|
536 app showInfo: 'Cannot set breakpoint here, try another line...'. |
|
537 ]. |
|
538 codeView flash. |
|
539 ] ifFalse:[ |
|
540 gutterView redrawLine:line. |
|
541 ]. |
|
542 |
|
543 "Created: / 17-06-2011 / 13:45:22 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
544 "Modified: / 28-08-2013 / 14:45:36 / cg" |
|
545 "Modified: / 21-02-2014 / 17:36:11 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
546 ! ! |
552 ! ! |
547 |
553 |
548 !BreakpointService methodsFor:'queries'! |
554 !BreakpointService methodsFor:'queries'! |
549 |
555 |
550 canCreateOrToggleBreakpointAtLine:lineOrNilForAnywhere |
556 canCreateOrToggleBreakpointAtLine:lineOrNilForAnywhere |