diff --git a/src/BaselineOfNewTools/BaselineOfNewTools.class.st b/src/BaselineOfNewTools/BaselineOfNewTools.class.st index 844b6cf4..49bcb8cf 100644 --- a/src/BaselineOfNewTools/BaselineOfNewTools.class.st +++ b/src/BaselineOfNewTools/BaselineOfNewTools.class.st @@ -37,6 +37,7 @@ BaselineOfNewTools >> baseline: spec [ package: 'NewTools-Debugger' with: [ spec requires: #( 'NewTools-Inspector' 'NewTools-Debugger-Commands' 'NewTools-Debugger-Extensions' 'NewTools-SpTextPresenterDecorators' ) ]; package: 'NewTools-Debugger-Commands'; package: 'NewTools-Debugger-Extensions'; + package: 'NewTools-Debugger-Morphic'; package: 'NewTools-Debugger-Tests' with: [ spec requires: #( 'NewTools-Debugger' ) ]; "playground" package: 'NewTools-Playground' with: [ spec requires: #( 'NewTools-Inspector' ) ]; @@ -116,8 +117,11 @@ BaselineOfNewTools >> baseline: spec [ 'NewTools-Debugger-Commands' 'NewTools-Debugger-Extensions' 'NewTools-Debugger' - 'NewTools-ObjectCentricBreakpoints' - 'NewTools-Sindarin-Tools' + + 'NewTools-Debugger-Morphic' + 'NewTools-ObjectCentricBreakpoints' + 'NewTools-Sindarin-Tools' + 'NewTools-Sindarin-Commands' 'NewTools-Sindarin-Commands-Tests' 'NewTools-Debugger-Breakpoints-Tools' diff --git a/src/NewTools-Debugger-Morphic/SpMorphicBackend.extension.st b/src/NewTools-Debugger-Morphic/SpMorphicBackend.extension.st new file mode 100644 index 00000000..5b038c57 --- /dev/null +++ b/src/NewTools-Debugger-Morphic/SpMorphicBackend.extension.st @@ -0,0 +1,9 @@ +Extension { #name : 'SpMorphicBackend' } + +{ #category : '*NewTools-Debugger-Morphic' } +SpMorphicBackend >> spawnNewDebugSessionForSpecBackend: aDebugSession [ + + ^ (StMorphicDebugSession newFromSession: aDebugSession) + backend: self; + yourself +] diff --git a/src/NewTools-Debugger-Morphic/StMorphicDebugSession.class.st b/src/NewTools-Debugger-Morphic/StMorphicDebugSession.class.st new file mode 100644 index 00000000..70b82c72 --- /dev/null +++ b/src/NewTools-Debugger-Morphic/StMorphicDebugSession.class.st @@ -0,0 +1,88 @@ +" +I specialize a debug session for Morphic backends used by spec tools +" +Class { + #name : 'StMorphicDebugSession', + #superclass : 'DebugSession', + #instVars : [ + 'errorWasInUIProcess', + 'backend' + ], + #category : 'NewTools-Debugger-Morphic', + #package : 'NewTools-Debugger-Morphic' +} + +{ #category : 'instance creation' } +StMorphicDebugSession class >> newFromSession: aDebugSession [ + + ^ (self + named: aDebugSession name + on: aDebugSession interruptedProcess + startedAt: aDebugSession interruptedContext) + exception: aDebugSession exception; + detectUIProcess; + spawnNewUIProcessIfNecessary; + yourself +] + +{ #category : 'accessing' } +StMorphicDebugSession >> backend: aSpMorphicBackend [ + + backend := aSpMorphicBackend +] + +{ #category : 'debugging actions' } +StMorphicDebugSession >> deferDebuggerOpeningToBackend: aStDebugger [ + + backend defer: [ aStDebugger openWithFullView ] +] + +{ #category : 'process' } +StMorphicDebugSession >> detectUIProcess [ + + errorWasInUIProcess := MorphicUIManager uiProcess + == interruptedProcess +] + +{ #category : 'accessing' } +StMorphicDebugSession >> errorWasInUIProcess [ + + ^ errorWasInUIProcess +] + +{ #category : 'accessing' } +StMorphicDebugSession >> errorWasInUIProcess: aBoolean [ + + errorWasInUIProcess := aBoolean +] + +{ #category : 'private' } +StMorphicDebugSession >> resumeInterruptedProcess [ + + errorWasInUIProcess ifFalse: [ ^ super resumeInterruptedProcess ]. + MorphicUIManager default resumeUIProcess: interruptedProcess +] + +{ #category : 'process' } +StMorphicDebugSession >> spawnNewUIProcess [ + + DefaultExecutionEnvironment beActiveDuring: [ + MorphicUIManager default spawnNewProcess ] +] + +{ #category : 'process' } +StMorphicDebugSession >> spawnNewUIProcessIfNecessary [ + "If we're about to debug the UI process, we must create a new UI process to take its place. Because the debugged process will be suspended at some point, and suspending the UI process means freezing the UI of the image" + + errorWasInUIProcess ifTrue: [ self spawnNewUIProcess ] +] + +{ #category : 'debugging actions' } +StMorphicDebugSession >> terminate [ + + self interruptedProcess ifNotNil: [ ^ super terminate ]. + + "Assume the interrupted process was resumed." + "Kill the active process if the error was in the UI as there should be only one UI process." + self errorWasInUIProcess ifTrue: [ Processor terminateActive ] +] diff --git a/src/NewTools-Debugger-Morphic/StMorphicDebugSessionForTests.class.st b/src/NewTools-Debugger-Morphic/StMorphicDebugSessionForTests.class.st new file mode 100644 index 00000000..e92b9271 --- /dev/null +++ b/src/NewTools-Debugger-Morphic/StMorphicDebugSessionForTests.class.st @@ -0,0 +1,26 @@ +" +This morphic debug session just redefines methods to be used in tests to avoid spawning new ui processes for real +" +Class { + #name : 'StMorphicDebugSessionForTests', + #superclass : 'StMorphicDebugSession', + #instVars : [ + 'newUIProcessSpawned' + ], + #category : 'NewTools-Debugger-Morphic', + #package : 'NewTools-Debugger-Morphic' +} + +{ #category : 'process' } +StMorphicDebugSessionForTests >> newUIProcessSpawned [ + + newUIProcessSpawned ifNil: [ newUIProcessSpawned := false ]. + ^ newUIProcessSpawned +] + +{ #category : 'process' } +StMorphicDebugSessionForTests >> spawnNewUIProcessIfNecessary [ + "we just want to avoid spawning UI processes, while ensuring that we actually called the ui process spawning logic " + + newUIProcessSpawned := errorWasInUIProcess +] diff --git a/src/NewTools-Debugger-Morphic/StMorphicDebugSessionTest.class.st b/src/NewTools-Debugger-Morphic/StMorphicDebugSessionTest.class.st new file mode 100644 index 00000000..a6064e4a --- /dev/null +++ b/src/NewTools-Debugger-Morphic/StMorphicDebugSessionTest.class.st @@ -0,0 +1,53 @@ +Class { + #name : 'StMorphicDebugSessionTest', + #superclass : 'TestCase', + #category : 'NewTools-Debugger-Morphic', + #package : 'NewTools-Debugger-Morphic' +} + +{ #category : 'utilities' } +StMorphicDebugSessionTest >> createDebugSessionForNotUIProcess [ + + | exception nonUIProcess request | + nonUIProcess := [ 1 + 1 ] newProcess. + [ Exception signal ] + on: Exception + do: [ :e | exception := e ]. + request := (OupsDummyDebugRequest newForException: exception) + process: nonUIProcess; + yourself. + ^ StMorphicDebugSessionForTests newFromSession: request debugSession +] + +{ #category : 'utilities' } +StMorphicDebugSessionTest >> createDebugSessionForUIProcess [ + + | exception request | + [ Exception signal ] + on: Exception + do: [ :e | exception := e ]. + request := (OupsDummyDebugRequest newForException: exception) + process: MorphicUIManager uiProcess; + yourself. + ^ StMorphicDebugSessionForTests newFromSession: request debugSession +] + +{ #category : 'utilities' } +StMorphicDebugSessionTest >> testNonUIProcessIsRecognised [ + "Tests that a DebuggerSystem opening a DebugRequest that is NOT on the ui process does NOT spawn a new UI process" + + | morphicDebugSession | + morphicDebugSession := self createDebugSessionForNotUIProcess. + self deny: morphicDebugSession errorWasInUIProcess. + self deny: morphicDebugSession newUIProcessSpawned +] + +{ #category : 'tests' } +StMorphicDebugSessionTest >> testUIProcessIsRecognised [ + "Test that a DebuggerSystem opening a DebugRequest on the ui process will spawn a new UI process" + + | morphicDebugSession | + morphicDebugSession := self createDebugSessionForUIProcess. + self assert: morphicDebugSession errorWasInUIProcess. + self assert: morphicDebugSession newUIProcessSpawned +] diff --git a/src/NewTools-Debugger-Morphic/package.st b/src/NewTools-Debugger-Morphic/package.st new file mode 100644 index 00000000..38e27891 --- /dev/null +++ b/src/NewTools-Debugger-Morphic/package.st @@ -0,0 +1 @@ +Package { #name : 'NewTools-Debugger-Morphic' } diff --git a/src/NewTools-Debugger/DebugSession.extension.st b/src/NewTools-Debugger/DebugSession.extension.st index 12079682..ac2099af 100644 --- a/src/NewTools-Debugger/DebugSession.extension.st +++ b/src/NewTools-Debugger/DebugSession.extension.st @@ -8,15 +8,5 @@ DebugSession >> application [ { #category : '*NewTools-Debugger' } DebugSession >> application: anApplication [ -] - -{ #category : '*NewTools-Debugger' } -DebugSession >> spanNewSession [ - ^ (self class - named: self name - on: self interruptedProcess - startedAt: self interruptedContext) - errorWasInUIProcess: self errorWasInUIProcess; - yourself ] diff --git a/src/NewTools-Debugger/SpApplicationBackend.extension.st b/src/NewTools-Debugger/SpApplicationBackend.extension.st new file mode 100644 index 00000000..a0a6da95 --- /dev/null +++ b/src/NewTools-Debugger/SpApplicationBackend.extension.st @@ -0,0 +1,7 @@ +Extension { #name : 'SpApplicationBackend' } + +{ #category : '*NewTools-Debugger' } +SpApplicationBackend >> spawnNewDebugSessionForSpecBackend: aDebugSession [ + + ^ aDebugSession +] diff --git a/src/NewTools-Debugger/StDebugger.class.st b/src/NewTools-Debugger/StDebugger.class.st index 1431703d..a3fdc6cb 100644 --- a/src/NewTools-Debugger/StDebugger.class.st +++ b/src/NewTools-Debugger/StDebugger.class.st @@ -139,13 +139,18 @@ StDebugger class >> configureLayout: aSymbol [ { #category : 'instance creation' } StDebugger class >> debugSession: aDebugSession [ - | debugger debugActionModel | - debugActionModel := StDebuggerActionModel on: aDebugSession. - debugger := self on: aDebugSession. - aDebugSession application ifNotNil: [ :app | + | applicationDebugSession debugger debugActionModel | + + applicationDebugSession := self currentApplication backend + spawnNewDebugSessionForSpecBackend: aDebugSession. + + debugActionModel := StDebuggerActionModel on: applicationDebugSession. + debugger := self on: applicationDebugSession. + aDebugSession application ifNotNil: [ :app | debugger application: app ]. - debugger openWithFullView. + applicationDebugSession deferDebuggerOpeningToBackend: debugger. + ^ debugger ]