[squeak-dev] The Trunk: Tools-ct.1149.mcz

commits at source.squeak.org commits at source.squeak.org
Thu May 5 16:24:58 UTC 2022


Christoph Thiede uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-ct.1149.mcz

==================== Summary ====================

Name: Tools-ct.1149
Author: ct
Time: 5 May 2022, 6:24:40.020816 pm
UUID: dff67dfa-826f-6a48-948a-febe229528df
Ancestors: Tools-xw.1147, Tools-ct.1109

Merges and revises Tools-ct.1109 (protects the debugger from debugging the active process).

Revision: Instead of stepping the model, disable stepping all buttons upon the first click when the interrupted process is not ready. See #shouldNotStep for an example situation.

Thanks to Marcel for the feedback!

=============== Diff against Tools-xw.1147 ===============

Item was changed:
  ----- Method: Debugger>>customButtonSpecs (in category 'initialize') -----
  customButtonSpecs
  	"Answer an array of elements of the form wording, selector, help-message, that characterize the custom button row of a debugger."
  
  	| list |
  	list := #(('Proceed'	proceed				'Close the debugger and proceed.'	interruptedProcessShouldResume)
  		('Restart'		restart				'Reset this context to its start.')
+ 		('Into'			stepInto				'step Into message sends'	interruptedProcessIsReady)
+ 		('Over'			stepOver				'step Over message sends'	interruptedProcessIsReady)
+ 		('Through'		stepThrough		'step into a block'			interruptedProcessIsReady)
- 		('Into'			stepInto				'step Into message sends'	interruptedProcessIsActive)
- 		('Over'			stepOver				'step Over message sends'	interruptedProcessIsActive)
- 		('Through'		stepThrough		'step into a block'			interruptedProcessIsActive)
  		('Full Stack'		showFullStack			'show full stack')
  		('Where'		showWhere				'select current pc range')
  		('Tally It'			tally				'evaluate current selection and measure the time')).
  	(Preferences restartAlsoProceeds and: [self interruptedProcessShouldResume]) ifTrue:
  		[list := list collect: [:each |
  			each second == #restart
  				ifTrue: [each copy
  						at: 1 put: 'Proceed Here';
  						at: 3 put: 'Proceed from the beginning of this context.';
  						yourself]
  				ifFalse: [each second == #proceed
  					ifTrue: [each copy
  							at: 1 put: 'Proceed Top';
  							at: 3 put: 'Proceed from the current top context.';
  							yourself]
  					ifFalse: [each]]]].
  	^ list!

Item was changed:
  ----- Method: Debugger>>doStep (in category 'context stack menu') -----
  doStep
  	"Send the selected message in the accessed method, and regain control 
  	after the invoked method returns."
  	
  	| currentContext newContext |
  	self okToChange ifFalse: [^ self].
+ 	self interruptedProcessIsReady ifFalse: [^ self shouldNotStep].
  	self checkContextSelection.
  	currentContext := self selectedContext.
  	newContext := self handleLabelUpdatesIn: [interruptedProcess completeStep: currentContext]
  						whenExecuting: currentContext.
+ 	interruptedProcess ifNil: [^ self shouldNotStep].
  	newContext == currentContext ifTrue:
  		[newContext := interruptedProcess stepToSendOrReturn].
+ 	self updateProcess.
  	self contextStackIndex > 1
  		ifTrue: [self resetContext: newContext]
  		ifFalse:
  			[newContext == currentContext
  				ifTrue: [self changed: #contentsSelection.
  						self updateInspectors]
+ 				ifFalse: [self resetContext: newContext]].!
- 				ifFalse: [self resetContext: newContext]].
- !

Item was changed:
  ----- Method: Debugger>>doStepUntil: (in category 'context stack menu') -----
  doStepUntil: condition
  	"Step until the given condition evaluates to other than false, reporting an error it if does not evaluate to true.
  	
  	If shift is pressed when the expression is supplied, don't update the UI. If shift is pressed while stepping, stop stepping. Using a user interrupt to break out would be more natural but Squeak currently doesn't provide a UserInterrupt exception. It should do."
  	
  	| currentContext newContext value lastUpdate updateUI breakOnShift |
  	self okToChange ifFalse: [^ self].
+ 	self interruptedProcessIsReady ifFalse: [^ self shouldNotStep].
  	self checkContextSelection.
  	currentContext := newContext := self selectedContext.
  	lastUpdate := Time millisecondClockValue.
  	updateUI := breakOnShift := Sensor shiftPressed not.
  	
  	Cursor execute showWhile: [[
  		newContext == currentContext
  			and: [currentContext willReturn not
  			and: [(value := condition value) == false]] ] whileTrue: [
  	
  				self
  					handleLabelUpdatesIn: [newContext := interruptedProcess completeStep: currentContext]
  					whenExecuting: currentContext.
+ 				interruptedProcess ifNil: [^ self shouldNotStep].
  				newContext == currentContext ifTrue: [
  					newContext := interruptedProcess stepToSendOrReturn.
  					self resetContext: newContext changeContents: false].
  	
  				Time millisecondClockValue - lastUpdate > 250 "ms" ifTrue: [
  					updateUI ifTrue: [
  						self changed: #contentsSelection.
  						Project current world displayWorldSafely].
  					breakOnShift 
  						ifTrue: [Sensor shiftPressed ifTrue: [
  							self changed: #contentsSelection.
  							self updateInspectors.
  							^self]]
  						ifFalse: [Sensor shiftPressed ifFalse: [breakOnShift := true]].
  					 lastUpdate := Time millisecondClockValue] ]].
  	
+ 	self updateProcess.
  	self contextStackIndex > 1
  		ifTrue: [self resetContext: newContext]
  		ifFalse:
  			[newContext == currentContext
  				ifTrue: [self changed: #contentsSelection; updateInspectors]
  				ifFalse: [self resetContext: newContext]].
  			
+ 	^ value!
- 	^ value
- !

Item was removed:
- ----- Method: Debugger>>interruptedProcessIsActive (in category 'testing') -----
- interruptedProcessIsActive
- 	^interruptedProcess isTerminated not!

Item was added:
+ ----- Method: Debugger>>interruptedProcessIsReady (in category 'testing') -----
+ interruptedProcessIsReady
+ 
+ 	^ interruptedProcess notNil
+ 		and: [interruptedProcess isSuspended "do not debug the active process"]
+ 		and: [interruptedProcess isTerminated not]!

Item was changed:
  ----- Method: Debugger>>interruptedProcessShouldResume (in category 'testing') -----
  interruptedProcessShouldResume
+ 
+ 	^ self interruptedProcessIsReady and: [interruptedProcess shouldResumeFromDebugger]!
- 	^ interruptedProcess shouldResumeFromDebugger!

Item was changed:
  ----- Method: Debugger>>removeMessage (in category 'context stack menu') -----
  removeMessage
  	
  	| oldContext method cleanIndex  |
  	self okToChange ifFalse: [^ false].
  	contextStackIndex isZero ifTrue: [^ false].
  	
  	oldContext := self selectedContext.
  	method := oldContext method.
  	cleanIndex := self findCleanHomeBelow: method.
  	contextStack at: cleanIndex ifAbsent: [
  		self inform: 'Sender of method not found on stack, can''t remove message'.
  		^ false].
+ 	self interruptedProcessIsReady ifFalse: [^ self shouldNotStep].
  	(self confirm: 'I will have to revert to the sender of this message.  Is that OK?')
  		ifFalse: [^ false].
  	
  	super removeMessage ifFalse: [^ false].
  	self
  		contextStackIndex: cleanIndex oldContextWas: oldContext;
  		tryRestartFrom: self selectedContext.
  	
  	^ true!

Item was changed:
  ----- 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 ifNil: [oldContext]) contextStack.
+ 	self changed: #contextStackList.
- 	self changed: #contextStackList; changed: #interruptedProcessIsActive.
  	self contextStackIndex: 1 oldContextWas: oldContext.
+ 	self updateProcess.
+ 	aBoolean ifTrue: [self contentsChanged].!
- 	aBoolean ifTrue: [self contentsChanged].
- !

Item was changed:
  ----- Method: Debugger>>restart (in category 'context stack menu') -----
  restart
  	"Proceed from the initial state of the currently selected context. The 
  	argument is a controller on a view of the receiver. That view is closed."
  	"Closing now depends on a preference #restartAlsoProceeds - hmm 9/7/2001 16:46"
  
  	| unwindError |
  	self okToChange ifFalse: [^ self].
+ 	interruptedProcess isSuspended ifFalse: [^ self shouldNotStep].
  	self checkContextSelection.
  	unwindError := self tryRestartFrom: self selectedContext.
  	((Preferences restartAlsoProceeds
  		and: [unwindError not])
  		and: [self interruptedProcessShouldResume])
  			ifTrue: [self proceed].!

Item was changed:
  ----- Method: Debugger>>send (in category 'context stack menu') -----
  send
  	"Send the selected message in the accessed method, and take control in 
  	the method invoked to allow further step or send."
  
  	self okToChange ifFalse: [^ self].
+ 	self interruptedProcessIsReady ifFalse: [^ self shouldNotStep].
  	self checkContextSelection.
  	interruptedProcess step: self selectedContext.
+ 	interruptedProcess ifNil: [^ self shouldNotStep].
+ 	self resetContext: interruptedProcess stepToSendOrReturn.!
- 	self resetContext: interruptedProcess stepToSendOrReturn.
- !

Item was added:
+ ----- Method: Debugger>>shouldNotStep (in category 'private') -----
+ shouldNotStep
+ 	"An illegal attempt was to step an unready process. Update the enablement of stepping buttons and trigger a visual indication.
+ 	
+ 	For instance, this situation can be triggered by this:
+ 		[self currentHand lastEvent shiftPressed] yourself
+ 			whileFalse: [Project current world doOneCycleNow].
+ 	Debug it, step over #whileFalse: and step over again. Move your cursor while pressing shift to continue."
+ 
+ 	self
+ 		changed: #interruptedProcessIsReady;
+ 		changed: #interruptedProcessShouldResume.
+ 	
+ 	^ self changed: #flash!

Item was changed:
  ----- Method: Debugger>>stepIntoBlock (in category 'context stack menu') -----
  stepIntoBlock
  	"Send messages until you return to the present method context.
  	 Used to step into a block in the method."
  
  	| currentContext newContext |
  	self okToChange ifFalse: [^ self].
+ 	self interruptedProcessIsReady ifFalse: [^ self shouldNotStep].
  	self checkContextSelection.
  	currentContext := self selectedContext.
  	self handleLabelUpdatesIn:
  			[interruptedProcess stepToHome: currentContext]
  		whenExecuting: self selectedContext.
+ 	interruptedProcess ifNil: [^ self shouldNotStep].
  	newContext := interruptedProcess stepToSendOrReturn.
+ 	self updateProcess.
  	self contextStackIndex > 1
  		ifTrue: [self resetContext: newContext]
  		ifFalse:
  			[newContext == currentContext
  				ifTrue: [self changed: #contentsSelection.
  						self updateInspectors]
  				ifFalse: [self resetContext: newContext]].!

Item was added:
+ ----- Method: Debugger>>updateProcess (in category 'private') -----
+ updateProcess
+ 
+ 	self
+ 		changed: #interruptedProcessIsReady;
+ 		changed: #interruptedProcessShouldResume.!



More information about the Squeak-dev mailing list