Bert Freudenberg uploaded a new version of Tools to project The Inbox:
http://source.squeak.org/inbox/Tools-bf.429.mcz ==================== Summary ==================== Name: Tools-bf.429 Author: bf Time: 16 November 2012, 8:47:08.199 pm UUID: cabe1021-05b4-45f3-9141-989bcb580add Ancestors: Tools-eem.428 Fix changes in debugger getting lost when reverting to method from an inner block. As reported by Aran Lunzer: Set up the following method on some class: bugger | a1 | a1 := 0. [ 2 / a1 ] value then send <class> new bugger In the walkback, try changing the last line to [ b1:=2. 2 / a1 ] value (oops - said b1 instead of a1...) Debugger asks if it's ok to revert to the method in which the block was defined. Say ok. Then it asks about adding b1 as a new variable (NB: at this stage, the code edits have already disappeared). Then cancel, intending to fix the variable name. But your edits are lost. =============== Diff against Tools-eem.428 =============== Item was changed: ----- Method: Debugger>>contents:notifying: (in category 'accessing') ----- contents: aText notifying: aController "The retrieved information has changed and its source must now be updated. In this case, the retrieved information is the method of the selected context." | result selector classOfMethod category h ctxt newMethod | contextStackIndex = 0 ifTrue: [^false]. self selectedContext isExecutingBlock ifTrue: [h := self selectedContext activeHome. h ifNil: [self inform: 'Method for block not found on stack, can''t edit and continue'. ^false]. (self confirm: 'I will have to revert to the method from\which this block originated. Is that OK?' withCRs) ifFalse: [^false]. + self resetContext: h changeContents: false. - self resetContext: h. "N.B. Only reset the contents if the compilation succeeds. If contents are reset when compilation fails both compiler error message and modifications are lost." (result := self contents: aText notifying: aController) ifTrue: [self contentsChanged]. ^result]. classOfMethod := self selectedClass. category := self selectedMessageCategoryName. selector := self selectedClass newParser parseSelector: aText. (selector == self selectedMessageName or: [(self selectedMessageName beginsWith: 'DoIt') and: [selector numArgs = self selectedMessageName numArgs]]) ifFalse: [self inform: 'can''t change selector'. ^false]. selector := classOfMethod compile: aText classified: category notifying: aController. selector ifNil: [^false]. "compile cancelled" contents := aText. newMethod := classOfMethod compiledMethodAt: selector. newMethod isQuick ifTrue: [self down. self selectedContext jump: (self selectedContext previousPc - self selectedContext pc)]. ctxt := interruptedProcess popTo: self selectedContext. ctxt == self selectedContext ifFalse: [self inform: 'Method saved, but current context unchanged\because of unwind error. Click OK to see error' withCRs] ifTrue: [newMethod isQuick ifFalse: [interruptedProcess restartTopWith: newMethod; stepToSendOrReturn]. contextVariablesInspector object: nil]. self resetContext: ctxt. Smalltalk isMorphic ifTrue: [World addAlarm: #changed: withArguments: #(contentsSelection) for: self at: (Time millisecondClockValue + 200)]. ^true! Item was added: + ----- Method: Debugger>>resetContext:changeContents: (in category 'private') ----- + resetContext: aContext changeContents: aBoolean + "Used when a new context becomes top-of-stack, for instance when the + method of the selected context is re-compiled, or the simulator steps or + returns to a new method. There is room for much optimization here, first + to save recomputing the whole stack list (and text), and secondly to avoid + recomposing all that text (by editing the paragraph instead of recreating it)." + + | oldContext | + oldContext := self selectedContext. + self newStack: aContext contextStack. + self changed: #contextStackList. + self contextStackIndex: 1 oldContextWas: oldContext. + aBoolean ifTrue: [self contentsChanged]. + ! |
I wasn't sure if this should go into the release at this stage so I submitted to the inbox instead. It seems pretty safe to me, and fixes a major annoyance while debugging, so if others try and find it safe we might apply it now. Otherwise I'll push it early after the 4.4 release.
- Bert - On 2012-11-16, at 19:47, [hidden email] wrote: > Bert Freudenberg uploaded a new version of Tools to project The Inbox: > http://source.squeak.org/inbox/Tools-bf.429.mcz > > ==================== Summary ==================== > > Name: Tools-bf.429 > Author: bf > Time: 16 November 2012, 8:47:08.199 pm > UUID: cabe1021-05b4-45f3-9141-989bcb580add > Ancestors: Tools-eem.428 > > Fix changes in debugger getting lost when reverting to method from an inner block. As reported by Aran Lunzer: > > Set up the following method on some class: > > bugger > | a1 | > a1 := 0. > [ 2 / a1 ] value > > then send <class> new bugger > > In the walkback, try changing the last line to > > [ b1:=2. 2 / a1 ] value > > (oops - said b1 instead of a1...) > > Debugger asks if it's ok to revert to the method in which the block was defined. Say ok. Then it asks about adding b1 as a new variable (NB: at this stage, the code edits have already disappeared). Then cancel, intending to fix the variable name. But your edits are lost. > > =============== Diff against Tools-eem.428 =============== > > Item was changed: > ----- Method: Debugger>>contents:notifying: (in category 'accessing') ----- > contents: aText notifying: aController > "The retrieved information has changed and its source must now be updated. > In this case, the retrieved information is the method of the selected context." > | result selector classOfMethod category h ctxt newMethod | > contextStackIndex = 0 ifTrue: > [^false]. > self selectedContext isExecutingBlock ifTrue: > [h := self selectedContext activeHome. > h ifNil: > [self inform: 'Method for block not found on stack, can''t edit and continue'. > ^false]. > (self confirm: 'I will have to revert to the method from\which this block originated. Is that OK?' withCRs) ifFalse: > [^false]. > + self resetContext: h changeContents: false. > - self resetContext: h. > "N.B. Only reset the contents if the compilation succeeds. If contents are reset > when compilation fails both compiler error message and modifications are lost." > (result := self contents: aText notifying: aController) ifTrue: > [self contentsChanged]. > ^result]. > > classOfMethod := self selectedClass. > category := self selectedMessageCategoryName. > selector := self selectedClass newParser parseSelector: aText. > (selector == self selectedMessageName > or: [(self selectedMessageName beginsWith: 'DoIt') > and: [selector numArgs = self selectedMessageName numArgs]]) ifFalse: > [self inform: 'can''t change selector'. > ^false]. > selector := classOfMethod > compile: aText > classified: category > notifying: aController. > selector ifNil: [^false]. "compile cancelled" > contents := aText. > newMethod := classOfMethod compiledMethodAt: selector. > newMethod isQuick ifTrue: > [self down. > self selectedContext jump: (self selectedContext previousPc - self selectedContext pc)]. > ctxt := interruptedProcess popTo: self selectedContext. > ctxt == self selectedContext > ifFalse: > [self inform: 'Method saved, but current context unchanged\because of unwind error. Click OK to see error' withCRs] > ifTrue: > [newMethod isQuick ifFalse: > [interruptedProcess > restartTopWith: newMethod; > stepToSendOrReturn]. > contextVariablesInspector object: nil]. > self resetContext: ctxt. > Smalltalk isMorphic ifTrue: > [World > addAlarm: #changed: > withArguments: #(contentsSelection) > for: self > at: (Time millisecondClockValue + 200)]. > ^true! > > Item was added: > + ----- Method: Debugger>>resetContext:changeContents: (in category 'private') ----- > + resetContext: aContext changeContents: aBoolean > + "Used when a new context becomes top-of-stack, for instance when the > + method of the selected context is re-compiled, or the simulator steps or > + returns to a new method. There is room for much optimization here, first > + to save recomputing the whole stack list (and text), and secondly to avoid > + recomposing all that text (by editing the paragraph instead of recreating it)." > + > + | oldContext | > + oldContext := self selectedContext. > + self newStack: aContext contextStack. > + self changed: #contextStackList. > + self contextStackIndex: 1 oldContextWas: oldContext. > + aBoolean ifTrue: [self contentsChanged]. > + ! > > |
Free forum by Nabble | Edit this page |