diff --git a/src/NewTools-Debugger-Commands/StGenerateAndProceedCommand.class.st b/src/NewTools-Debugger-Commands/StGenerateAndProceedCommand.class.st new file mode 100644 index 000000000..f69632173 --- /dev/null +++ b/src/NewTools-Debugger-Commands/StGenerateAndProceedCommand.class.st @@ -0,0 +1,43 @@ +Class { + #name : 'StGenerateAndProceedCommand', + #superclass : 'StDebuggerCommand', + #category : 'NewTools-Debugger-Commands', + #package : 'NewTools-Debugger-Commands' +} + +{ #category : 'default' } +StGenerateAndProceedCommand class >> defaultDescription [ + + ^ 'Save and compile the modified source, relinquish debugger control and proceed execution from the start of the current method.' +] + +{ #category : 'default' } +StGenerateAndProceedCommand class >> defaultIconName [ + + ^ #debuggerProceed +] + +{ #category : 'default' } +StGenerateAndProceedCommand class >> defaultName [ + + + ^ 'Gen.&Proceed' +] + +{ #category : 'default' } +StGenerateAndProceedCommand class >> defaultShortcut [ + + ^ $g meta +] + +{ #category : 'testing' } +StGenerateAndProceedCommand >> appliesTo: aDebugger [ + + ^ aDebugger canGenerateAndProceed +] + +{ #category : 'testing' } +StGenerateAndProceedCommand >> execute [ + + self debugger saveGeneratedCodeAndProceed +] diff --git a/src/NewTools-Debugger-Tests/StDebuggerCommandTest.class.st b/src/NewTools-Debugger-Tests/StDebuggerCommandTest.class.st index a28b95a5d..b03b33f37 100644 --- a/src/NewTools-Debugger-Tests/StDebuggerCommandTest.class.st +++ b/src/NewTools-Debugger-Tests/StDebuggerCommandTest.class.st @@ -52,6 +52,8 @@ StDebuggerCommandTest >> testCommandsInDNUContext [ self deny: (StDefineSubclassResponsabilityCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. "Executable commands, whatever the context" self assert: @@ -88,6 +90,8 @@ StDebuggerCommandTest >> testCommandsInDeadContext [ self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. self deny: (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. "Executable commands, whatever the context" self assert: @@ -126,6 +130,10 @@ StDebuggerCommandTest >> testCommandsInErrorContext [ self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. self deny: (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. "Executable commands, whatever the context" self assert: @@ -142,62 +150,125 @@ StDebuggerCommandTest >> testCommandsInErrorContext [ { #category : 'tests' } StDebuggerCommandTest >> testCommandsInFailingTestContext [ - |debugger| + | debugger | debugger := debuggerProvider debuggerWithFailingTestContext. - self flag:'Cannot work until we can properly detect a failing assertion context'. - - "Executable commands relative to context" - self assert: (StRestartCommand forContext: debugger) canBeExecuted. - self assert: (StReturnValueCommand forContext: debugger) canBeExecuted. - + self flag: + 'Cannot work until we can properly detect a failing assertion context'. + + "Executable commands relative to context" + self assert: (StRestartCommand forContext: debugger) canBeExecuted. + self assert: + (StReturnValueCommand forContext: debugger) canBeExecuted. + "Non-executable commands relative to context" - self deny: (StStepIntoCommand forContext: debugger) canBeExecuted. - self deny: (StStepOverCommand forContext: debugger) canBeExecuted. - self deny: (StStepThroughCommand forContext: debugger) canBeExecuted. - self deny: (StRunToSelectionCommand forContext: debugger) canBeExecuted. + self deny: (StStepIntoCommand forContext: debugger) canBeExecuted. + self deny: (StStepOverCommand forContext: debugger) canBeExecuted. + self deny: (StStepThroughCommand forContext: debugger) canBeExecuted. + self deny: + (StRunToSelectionCommand forContext: debugger) canBeExecuted. self deny: (StProceedCommand forContext: debugger) canBeExecuted. - self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. - self deny: (StDefineSubclassResponsabilityCommand forContext: debugger) canBeExecuted. + self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineSubclassResponsabilityCommand forContext: debugger) + canBeExecuted. self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. - self deny: (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. - + self deny: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. + "Executable commands, whatever the context" - self assert: (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. - self assert: (StFileOutMethodCommand forContext: debugger) canBeExecuted. - self assert: (StPeelToFirstCommand forContext: debugger) canBeExecuted. + self assert: + (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. + self assert: + (StFileOutMethodCommand forContext: debugger) canBeExecuted. + self assert: + (StPeelToFirstCommand forContext: debugger) canBeExecuted. self assert: (StWhereIsCommand forContext: debugger) canBeExecuted. debugger debuggerActionModel clear ] +{ #category : 'tests' } +StDebuggerCommandTest >> testCommandsInGeneratingCodeContext [ + + | debugger | + debugger := debuggerProvider debuggerWithGeneratingCodeContext. + + "Executable commands relative to context" + self assert: (StRestartCommand forContext: debugger) canBeExecuted. + self assert: + (StReturnValueCommand forContext: debugger) canBeExecuted. + self assert: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. + + "Non-executable commands relative to context" + self deny: (StProceedCommand forContext: debugger) canBeExecuted. + self deny: (StStepIntoCommand forContext: debugger) canBeExecuted. + self deny: (StStepOverCommand forContext: debugger) canBeExecuted. + self deny: (StStepThroughCommand forContext: debugger) canBeExecuted. + self deny: + (StRunToSelectionCommand forContext: debugger) canBeExecuted. + self deny: (StProceedCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineSubclassResponsabilityCommand forContext: debugger) + canBeExecuted. + self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. + self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + + "Executable commands, whatever the context" + self assert: + (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. + self assert: + (StFileOutMethodCommand forContext: debugger) canBeExecuted. + self assert: + (StPeelToFirstCommand forContext: debugger) canBeExecuted. + self assert: (StWhereIsCommand forContext: debugger) canBeExecuted +] + { #category : 'tests' } StDebuggerCommandTest >> testCommandsInMissingClassContext [ "When a class is missing, it is possible we are trying to send it a message. - Define new class and define new method must be possible. " + Define new class and define new method must be possible. " + | debugger | - StTestDebuggerProvider compileMissingClassContextBuilder. debugger := debuggerProvider debuggerWithMissingClassContext. - - "Executable commands relative to context" - self assert: (StDefineClassCommand forContext: debugger) canBeExecuted. + + "Executable commands relative to context" + self assert: + (StDefineClassCommand forContext: debugger) canBeExecuted. self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. - self assert: (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. - self assert: (StRestartCommand forContext: debugger) canBeExecuted. - self assert: (StReturnValueCommand forContext: debugger) canBeExecuted. - + self assert: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self assert: (StRestartCommand forContext: debugger) canBeExecuted. + self assert: + (StReturnValueCommand forContext: debugger) canBeExecuted. + "Non-executable commands relative to context" - self assert: (StStepIntoCommand forContext: debugger) canBeExecuted. - self assert: (StStepOverCommand forContext: debugger) canBeExecuted. - self assert: (StStepThroughCommand forContext: debugger) canBeExecuted. - self assert: (StRunToSelectionCommand forContext: debugger) canBeExecuted. - self assert: (StProceedCommand forContext: debugger) canBeExecuted. - self deny: (StDefineSubclassResponsabilityCommand forContext: debugger) canBeExecuted. - - + self assert: (StStepIntoCommand forContext: debugger) canBeExecuted. + self assert: (StStepOverCommand forContext: debugger) canBeExecuted. + self assert: + (StStepThroughCommand forContext: debugger) canBeExecuted. + self assert: + (StRunToSelectionCommand forContext: debugger) canBeExecuted. + self assert: (StProceedCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineSubclassResponsabilityCommand forContext: debugger) + canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. + "Executable commands, whatever the context" - self assert: (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. - self assert: (StFileOutMethodCommand forContext: debugger) canBeExecuted. - self assert: (StPeelToFirstCommand forContext: debugger) canBeExecuted. + self assert: + (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. + self assert: + (StFileOutMethodCommand forContext: debugger) canBeExecuted. + self assert: + (StPeelToFirstCommand forContext: debugger) canBeExecuted. self assert: (StWhereIsCommand forContext: debugger) canBeExecuted. debugger debuggerActionModel clear ] @@ -228,6 +299,8 @@ StDebuggerCommandTest >> testCommandsInMissingSubclassResponsibilityContext [ self deny: (StProceedCommand forContext: debugger) canBeExecuted. self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. "Executable commands, whatever the context" self assert: @@ -270,6 +343,8 @@ StDebuggerCommandTest >> testCommandsInMissingSubclassResponsibilityContextWithS self deny: (StProceedCommand forContext: debugger) canBeExecuted. self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. "Executable commands, whatever the context" self assert: @@ -285,29 +360,40 @@ StDebuggerCommandTest >> testCommandsInMissingSubclassResponsibilityContextWithS { #category : 'tests' } StDebuggerCommandTest >> testCommandsInRunnableContext [ - |debugger| + | debugger | debugger := debuggerProvider debuggerWithRunnableContext. - + "Executable commands relative to context" - self assert: (StStepIntoCommand forContext: debugger) canBeExecuted. - self assert: (StStepOverCommand forContext: debugger) canBeExecuted. - self assert: (StStepThroughCommand forContext: debugger) canBeExecuted. - self assert: (StRunToSelectionCommand forContext: debugger) canBeExecuted. - self assert: (StProceedCommand forContext: debugger) canBeExecuted. - self assert: (StRestartCommand forContext: debugger) canBeExecuted. - self assert: (StReturnValueCommand forContext: debugger) canBeExecuted. - + self assert: (StStepIntoCommand forContext: debugger) canBeExecuted. + self assert: (StStepOverCommand forContext: debugger) canBeExecuted. + self assert: + (StStepThroughCommand forContext: debugger) canBeExecuted. + self assert: + (StRunToSelectionCommand forContext: debugger) canBeExecuted. + self assert: (StProceedCommand forContext: debugger) canBeExecuted. + self assert: (StRestartCommand forContext: debugger) canBeExecuted. + self assert: + (StReturnValueCommand forContext: debugger) canBeExecuted. + "Non-executable commands relative to context" - self deny: (StDefineSubclassResponsabilityCommand forContext: debugger) canBeExecuted. - self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. - self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. - self deny: (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. - + self deny: + (StDefineSubclassResponsabilityCommand forContext: debugger) + canBeExecuted. + self deny: (StDefineMethodCommand forContext: debugger) canBeExecuted. + self deny: (StDefineClassCommand forContext: debugger) canBeExecuted. + self deny: + (StDefineMissingEntityCommand forContext: debugger) canBeExecuted. + self deny: + (StGenerateAndProceedCommand forContext: debugger) canBeExecuted. + "Executable commands, whatever the context" - self assert: (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. - self assert: (StFileOutMethodCommand forContext: debugger) canBeExecuted. - self assert: (StPeelToFirstCommand forContext: debugger) canBeExecuted. - self assert: (StProceedCommand forContext: debugger) canBeExecuted. + self assert: + (StCopyStackToClipboardCommand forContext: debugger) canBeExecuted. + self assert: + (StFileOutMethodCommand forContext: debugger) canBeExecuted. + self assert: + (StPeelToFirstCommand forContext: debugger) canBeExecuted. + self assert: (StProceedCommand forContext: debugger) canBeExecuted. self assert: (StWhereIsCommand forContext: debugger) canBeExecuted. debugger debuggerActionModel clear ] @@ -404,6 +490,17 @@ StDebuggerCommandTest >> testStFileOutMethodCommandExecution [ self assert: debugger tag equals: #fileOutSelectedContext ] +{ #category : 'tests' } +StDebuggerCommandTest >> testStGenerateAndProceedCommandExecution [ + + | debugger command | + debugger := StDummyDebuggerPresenter new. + command := StGenerateAndProceedCommand forContext: debugger. + "StGenerateAndProceedCommand command calls the #saveGeneratedCodeAndProceed action interface of the debugger object" + command execute. + self assert: debugger tag equals: #saveGeneratedCodeAndProceed +] + { #category : 'tests - execution' } StDebuggerCommandTest >> testStPeelToFirstCommandExecution [ diff --git a/src/NewTools-Debugger-Tests/StDebuggerTest.class.st b/src/NewTools-Debugger-Tests/StDebuggerTest.class.st index 3fec80ada..aeae8f420 100644 --- a/src/NewTools-Debugger-Tests/StDebuggerTest.class.st +++ b/src/NewTools-Debugger-Tests/StDebuggerTest.class.st @@ -7,7 +7,8 @@ Class { 'oldFastTDD', 'dbg', 'stackSizeBefore', - 'shouldFilterStack' + 'shouldFilterStack', + 'oldMethodToSourceDictionary' ], #category : 'NewTools-Debugger-Tests-Presenters', #package : 'NewTools-Debugger-Tests', @@ -90,6 +91,7 @@ StDebuggerTest >> setUp [ session := StTestDebuggerProvider new sessionForDebuggerTests. oldFastTDD := self debuggerClass fastTDD. shouldFilterStack := StDebuggerActionModel shouldFilterStack. + oldMethodToSourceDictionary := Dictionary new. self debuggerClass fastTDD: true ] @@ -125,6 +127,10 @@ StDebuggerTest >> tearDown [ StDebuggerActionModel shouldFilterStack: shouldFilterStack. StTestDebuggerProvider removeSelector: #foobar. + oldMethodToSourceDictionary associationsDo: [ :assoc | + assoc key methodClass + compile: assoc value + classified: assoc key protocolName ]. super tearDown ] @@ -537,6 +543,51 @@ StDebuggerTest >> testFastTDD [ self deny: self debuggerClass fastTDD ] +{ #category : 'tests' } +StDebuggerTest >> testGenerateAndProceed [ + + | baseSourceCode expectedSourceCode adapter | + self skip: + 'Does not work, I do not know why it looks like my test is executed several times with the same debugger'. + baseSourceCode := 'methodThatGeneratesCode + + | asserter | + asserter := TestAsserter new. + + asserter see: 42 + 66 + 3'. + + expectedSourceCode := 'methodThatGeneratesCode + + | asserter | + asserter := TestAsserter new. + + asserter see: 42 + 66 + 3 equals: 111'. + + debugger := StTestDebuggerProvider new + debuggerWithGeneratingCodeContext + application: self debuggerClass currentApplication; + initialize; + yourself. + "just things necessary to use debugger's code presenter, which we need in this test" + adapter := SpMorphicCodeAdapter new. + adapter adapt: debugger code. + debugger code adapter: adapter. + debugger code adapter buildWidget. + + self assert: debugger canGenerateAndProceed. + self assert: debugger exception isGeneratingCode. + self + assert: debugger interruptedContext sender sourceCode + equals: baseSourceCode. + + oldMethodToSourceDictionary + at: debugger interruptedContext sender method + put: baseSourceCode. + + debugger saveGeneratedCodeAndProceed + "self assert: debugger interruptedContext isNil" +] + { #category : 'tests - code pane' } StDebuggerTest >> testInitialCodeSelectionAfterStepping [ | adapter segments highlightSegment pcRangeForContext | diff --git a/src/NewTools-Debugger-Tests/StDebuggerToolbarCommandTreeBuilderTest.class.st b/src/NewTools-Debugger-Tests/StDebuggerToolbarCommandTreeBuilderTest.class.st index 062717e1f..4ad31362d 100644 --- a/src/NewTools-Debugger-Tests/StDebuggerToolbarCommandTreeBuilderTest.class.st +++ b/src/NewTools-Debugger-Tests/StDebuggerToolbarCommandTreeBuilderTest.class.st @@ -48,9 +48,12 @@ StDebuggerToolbarCommandTreeBuilderTest >> testCommandGroupStructure [ { #category : 'tests' } StDebuggerToolbarCommandTreeBuilderTest >> testContextControlCommandClasses [ + self assertCollection: builder contextControlCommandClasses - equals: {StDefineMissingEntityCommand} + equals: { + StDefineMissingEntityCommand. + StGenerateAndProceedCommand } ] { #category : 'tests' } diff --git a/src/NewTools-Debugger-Tests/StDummyDebuggerPresenter.class.st b/src/NewTools-Debugger-Tests/StDummyDebuggerPresenter.class.st index 141fb9aa8..ab25ba421 100644 --- a/src/NewTools-Debugger-Tests/StDummyDebuggerPresenter.class.st +++ b/src/NewTools-Debugger-Tests/StDummyDebuggerPresenter.class.st @@ -100,6 +100,13 @@ tag := thisContext method selector. ^true ] +{ #category : 'actions' } +StDummyDebuggerPresenter >> saveGeneratedCodeAndProceed [ + + tag := thisContext method selector. + ^ true +] + { #category : 'mocks' } StDummyDebuggerPresenter >> selectNextExecutedExpression [ tag := thisContext method selector. diff --git a/src/NewTools-Debugger-Tests/StTestDebuggerProvider.class.st b/src/NewTools-Debugger-Tests/StTestDebuggerProvider.class.st index 08490ea2d..368895512 100644 --- a/src/NewTools-Debugger-Tests/StTestDebuggerProvider.class.st +++ b/src/NewTools-Debugger-Tests/StTestDebuggerProvider.class.st @@ -76,6 +76,16 @@ StTestDebuggerProvider >> debuggerWithFailingTestContext [ ^ self newDebugger ] ] +{ #category : 'helpers' } +StTestDebuggerProvider >> debuggerWithGeneratingCodeContext [ + + [ self methodThatGeneratesCode ] + on: StGenerateCode + do: [ :err | + self sessionFor: err signalerContext exception: err. + ^ self newDebugger ] +] + { #category : 'helpers' } StTestDebuggerProvider >> debuggerWithMissingClassContext [ "The called method must contain a undeclared variable (the missing class). @@ -164,6 +174,15 @@ StTestDebuggerProvider >> methodProducingDNU [ ^ self foobar ] +{ #category : 'helpers' } +StTestDebuggerProvider >> methodThatGeneratesCode [ + + | asserter | + asserter := TestAsserter new. + + asserter see: 42 + 66 + 3 +] + { #category : 'helpers' } StTestDebuggerProvider >> newDebugger [ diff --git a/src/NewTools-Debugger/Exception.extension.st b/src/NewTools-Debugger/Exception.extension.st new file mode 100644 index 000000000..e36ddff92 --- /dev/null +++ b/src/NewTools-Debugger/Exception.extension.st @@ -0,0 +1,13 @@ +Extension { #name : 'Exception' } + +{ #category : '*NewTools-Debugger' } +Exception >> isGeneratingCode [ + + ^ false +] + +{ #category : '*NewTools-Debugger' } +Exception >> selectedCodeRangeForContext: aContext forDebugger: aDebugger [ + + ^ aDebugger defaultSelectedCodeRangeForContext: aContext +] diff --git a/src/NewTools-Debugger/StDebugger.class.st b/src/NewTools-Debugger/StDebugger.class.st index 90fac8660..ccdecfd3e 100644 --- a/src/NewTools-Debugger/StDebugger.class.st +++ b/src/NewTools-Debugger/StDebugger.class.st @@ -311,6 +311,12 @@ StDebugger >> canExecuteReturnCommand [ ^ self debuggerActionModel isInterruptedContextDead not ] +{ #category : 'testing' } +StDebugger >> canGenerateAndProceed [ + + ^ self debuggerActionModel isInterruptedContextGeneratingCode +] + { #category : 'actions' } StDebugger >> clear [ @@ -503,6 +509,12 @@ StDebugger >> defaultLayout [ yourself ] +{ #category : 'testing' } +StDebugger >> defaultSelectedCodeRangeForContext: aContext [ + + ^ self debuggerActionModel selectedCodeRangeForContext: aContext +] + { #category : 'code pane' } StDebugger >> discardCodeChangesFor: aContext [ @@ -1077,6 +1089,16 @@ StDebugger >> runToSelection [ inContext: self currentContext ] +{ #category : 'actions' } +StDebugger >> saveGeneratedCodeAndProceed [ + + self + acceptCodeChanges: self code text + forContext: self selectedContext. + + self proceedDebugSession +] + { #category : 'actions' } StDebugger >> selectNextExecutedExpression [ @@ -1086,10 +1108,12 @@ StDebugger >> selectNextExecutedExpression [ (sourceNodeExecuted start to: sourceNodeExecuted stop) ] -{ #category : 'code pane' } +{ #category : 'highlighting' } StDebugger >> selectedCodeRangeForContext: aContext [ - ^ self debuggerActionModel selectedCodeRangeForContext: aContext + ^ self debuggerActionModel exception + selectedCodeRangeForContext: aContext + forDebugger: self ] { #category : 'accessing - model' } @@ -1341,14 +1365,14 @@ StDebugger >> updateCodeFromContext: aContext [ aContext ifNil: [ ^ self clearCode ]. self recordUnsavedCodeChanges. - selectionInterval := self selectedCodeRangeForContext: aContext. - aContext sourceCode = self code text ifFalse: [ + aContext sourceCode = self code text ifFalse: [ self updateSourceCodeFor: aContext ]. + selectionInterval := self selectedCodeRangeForContext: aContext. formerCodeInteractionModel := self code interactionModel. self code beForContext: aContext. "add bindings of the old interaction model in the new one" - formerCodeInteractionModel ifNotNil: [ - formerCodeInteractionModel bindings associations do: [ :assoc | + formerCodeInteractionModel ifNotNil: [ + formerCodeInteractionModel bindings associations do: [ :assoc | self code interactionModel addBinding: assoc ] ]. self code selectionInterval: (selectionInterval last to: selectionInterval last - 1). diff --git a/src/NewTools-Debugger/StDebuggerActionModel.class.st b/src/NewTools-Debugger/StDebuggerActionModel.class.st index b1a4b1f4d..ac2c50f42 100644 --- a/src/NewTools-Debugger/StDebuggerActionModel.class.st +++ b/src/NewTools-Debugger/StDebuggerActionModel.class.st @@ -245,6 +245,12 @@ StDebuggerActionModel >> isInterruptedContextDoesNotUnderstand [ ] +{ #category : 'testing' } +StDebuggerActionModel >> isInterruptedContextGeneratingCode [ + + ^ self contextPredicate isGeneratingCode +] + { #category : 'debug - predicates' } StDebuggerActionModel >> isInterruptedContextMissingClassException [ diff --git a/src/NewTools-Debugger/StDebuggerContextPredicate.class.st b/src/NewTools-Debugger/StDebuggerContextPredicate.class.st index 0dc3b9394..8b47d84a0 100644 --- a/src/NewTools-Debugger/StDebuggerContextPredicate.class.st +++ b/src/NewTools-Debugger/StDebuggerContextPredicate.class.st @@ -75,6 +75,12 @@ StDebuggerContextPredicate >> isContextSubclassResponsibilityException [ ^false ] +{ #category : 'testing' } +StDebuggerContextPredicate >> isGeneratingCode [ + + ^ false +] + { #category : 'predicates' } StDebuggerContextPredicate >> isSteppable [ diff --git a/src/NewTools-Debugger/StDebuggerErrorContextPredicate.class.st b/src/NewTools-Debugger/StDebuggerErrorContextPredicate.class.st index 5d105e9c6..6b96c9621 100644 --- a/src/NewTools-Debugger/StDebuggerErrorContextPredicate.class.st +++ b/src/NewTools-Debugger/StDebuggerErrorContextPredicate.class.st @@ -65,6 +65,12 @@ StDebuggerErrorContextPredicate >> isContextSubclassResponsibilityException [ ^ exception class == SubclassResponsibility ] +{ #category : 'testing' } +StDebuggerErrorContextPredicate >> isGeneratingCode [ + + ^ exception isGeneratingCode +] + { #category : 'predicates' } StDebuggerErrorContextPredicate >> isSteppable [ diff --git a/src/NewTools-Debugger/StDebuggerToolbarCommandTreeBuilder.class.st b/src/NewTools-Debugger/StDebuggerToolbarCommandTreeBuilder.class.st index 6d4c28591..792a70a27 100644 --- a/src/NewTools-Debugger/StDebuggerToolbarCommandTreeBuilder.class.st +++ b/src/NewTools-Debugger/StDebuggerToolbarCommandTreeBuilder.class.st @@ -57,7 +57,10 @@ StDebuggerToolbarCommandTreeBuilder >> buildDebuggerCommandGroup [ { #category : 'accessing - commands classes' } StDebuggerToolbarCommandTreeBuilder >> contextControlCommandClasses [ - ^ {StDefineMissingEntityCommand} + + ^ { + StDefineMissingEntityCommand. + StGenerateAndProceedCommand } ] { #category : 'commands' } diff --git a/src/NewTools-Debugger/StGenerateAssertEqualsCode.class.st b/src/NewTools-Debugger/StGenerateAssertEqualsCode.class.st new file mode 100644 index 000000000..8ce52b18a --- /dev/null +++ b/src/NewTools-Debugger/StGenerateAssertEqualsCode.class.st @@ -0,0 +1,51 @@ +Class { + #name : 'StGenerateAssertEqualsCode', + #superclass : 'StGenerateCode', + #instVars : [ + 'result' + ], + #category : 'NewTools-Debugger-Model', + #package : 'NewTools-Debugger', + #tag : 'Model' +} + +{ #category : 'code generation' } +StGenerateAssertEqualsCode >> generatedCodeFromDebugger: aDebugger [ + + | rewritedInterval rewritedText | + rewritedInterval := self rewritedCodeIntervalInDebugger: aDebugger. + rewritedText := aDebugger code text copyFrom: + rewritedInterval first + 4 to: + rewritedInterval last. + ^ String streamContents: [ :s | + s + nextPutAll: 'assert:'; + nextPutAll: rewritedText; + nextPutAll: ' equals: '; + nextPutAll: self resultString ] +] + +{ #category : 'accessing' } +StGenerateAssertEqualsCode >> result [ + + ^ result +] + +{ #category : 'accessing' } +StGenerateAssertEqualsCode >> result: anObject [ + + result := anObject +] + +{ #category : 'accessing' } +StGenerateAssertEqualsCode >> resultString [ + + ^ self result printString +] + +{ #category : 'rewriting' } +StGenerateAssertEqualsCode >> rewritedCodeIntervalInDebugger: aDebugger [ + + ^ aDebugger defaultSelectedCodeRangeForContext: + aDebugger currentContext +] diff --git a/src/NewTools-Debugger/StGenerateCode.class.st b/src/NewTools-Debugger/StGenerateCode.class.st new file mode 100644 index 000000000..f5581558f --- /dev/null +++ b/src/NewTools-Debugger/StGenerateCode.class.st @@ -0,0 +1,60 @@ +Class { + #name : 'StGenerateCode', + #superclass : 'Error', + #instVars : [ + 'lastSelectionInterval' + ], + #category : 'NewTools-Debugger-Model', + #package : 'NewTools-Debugger', + #tag : 'Model' +} + +{ #category : 'code generation' } +StGenerateCode >> generatedCodeFromDebugger: aDebugger [ + + self subclassResponsibility +] + +{ #category : 'testing' } +StGenerateCode >> isGeneratingCode [ + + ^ true +] + +{ #category : 'rewriting' } +StGenerateCode >> rewriteCodeInDebugger: aDebugger [ + + | text rewritedInterval generatedCode newText highlightedInterval | + text := aDebugger code text. + rewritedInterval := self rewritedCodeIntervalInDebugger: aDebugger. + generatedCode := self generatedCodeFromDebugger: aDebugger. + + newText := String streamContents: [ :s | + s + nextPutAll: (text first: rewritedInterval first - 1); + nextPutAll: generatedCode; + nextPutAll: + (text last: text size - rewritedInterval last) ]. + + highlightedInterval := rewritedInterval first to: + rewritedInterval first + generatedCode size. + aDebugger code text: newText. + + ^ highlightedInterval +] + +{ #category : 'rewriting' } +StGenerateCode >> rewritedCodeIntervalInDebugger: aDebugger [ + + self subclassResponsibility +] + +{ #category : 'rewriting' } +StGenerateCode >> selectedCodeRangeForContext: aContext forDebugger: aDebugger [ + + ^ aDebugger unsavedCodeChanges + at: aContext + ifPresent: [ lastSelectionInterval ] + ifAbsent: [ + lastSelectionInterval := self rewriteCodeInDebugger: aDebugger ] +] diff --git a/src/NewTools-Debugger/TestAsserter.extension.st b/src/NewTools-Debugger/TestAsserter.extension.st new file mode 100644 index 000000000..a8f0bbb03 --- /dev/null +++ b/src/NewTools-Debugger/TestAsserter.extension.st @@ -0,0 +1,9 @@ +Extension { #name : 'TestAsserter' } + +{ #category : '*NewTools-Debugger' } +TestAsserter >> see: anObject [ + + ^ StGenerateAssertEqualsCode new + result: anObject; + signal +]