Skip to content

Commit

Permalink
Merge pull request #2893 from macta/2776-Hitting-an-undefined-class-g…
Browse files Browse the repository at this point in the history
…ives-a-debugger-with-misleading-message-new-was-sent-to-nil-2

2776-Hitting-an-undefined-class-gives-a-debugger-with-misleading-message-new-was-sent-to-nil-2
  • Loading branch information
MarcusDenker committed Mar 19, 2019
2 parents 9a54419 + 423c6d6 commit 724ed61
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 22 deletions.
30 changes: 8 additions & 22 deletions src/DebuggerActions/DoesNotUnderstandDebugAction.class.st
Expand Up @@ -51,22 +51,14 @@ DoesNotUnderstandDebugAction >> closeWindow [
]

{ #category : #private }
DoesNotUnderstandDebugAction >> createMissingClassIn: aContext [
| senderContext variableNode previousContext errorMsgNode |

variableNode := nil.

[ senderContext := aContext sender.
errorMsgNode := senderContext method sourceNodeExecutedForPC: senderContext pc.
variableNode := self findUndeclaredVariableIn: errorMsgNode ]
on: Error
do: [ ^self ].
DoesNotUnderstandDebugAction >> createMissingClassWith: variableNode in: aContext [
| previousContext |

OCUndeclaredVariableWarning new
node: variableNode;
defineClass: variableNode name.

previousContext := aContext stack second.
previousContext := aContext sender.

self closeWindow.

Expand All @@ -91,11 +83,13 @@ DoesNotUnderstandDebugAction >> executeAction [
MessageNotUnderstood exception. Create a stub for the method that was
missing and proceed into it, or create a class if it was missing instead"

| msg msgCategory chosenClass |
| msg msgCategory chosenClass exception |

msg := self interruptedContext tempAt: 1.
(msg lookupClass == UndefinedObject ) ifTrue: [
self createMissingClassIn: self interruptedContext ].
exception := self interruptedContext tempAt: 2.

(exception class == VariableNotDeclared) ifTrue: [
self createMissingClassWith: exception variableNode in: self interruptedContext ].

chosenClass := self
askForSuperclassOf: self interruptedContext receiver class
Expand All @@ -110,14 +104,6 @@ DoesNotUnderstandDebugAction >> executeAction [
self debugger selectTopContext
]

{ #category : #private }
DoesNotUnderstandDebugAction >> findUndeclaredVariableIn: errorMsgNode [
^ errorMsgNode allChildren
detect: [ :n | n isVariable and: [ n isUndeclared ] ]
ifNone: [ errorMsgNode parent allChildren
detect: [ :n | n isVariable and: [ n isUndeclared ] ] ]
]

{ #category : #accessing }
DoesNotUnderstandDebugAction >> help [
^ 'Create the missing class or method in the user prompted class, and restart the debugger at the location where it can be edited.'
Expand Down
35 changes: 35 additions & 0 deletions src/Kernel/UndefinedObject.class.st
Expand Up @@ -77,13 +77,48 @@ UndefinedObject >> deepCopy [
with self."
]

{ #category : #'reflective operations' }
UndefinedObject >> doesNotUnderstand: aMessage [
<debuggerCompleteToSender>
"Handle the fact that there was an attempt to send the given message to an Undeclared variable (nil), hence the receiver does not understand this message (typically #new)."
"Testing: (3 activeProcess)"

| exception resumeValue node |

(node := self findUndeclaredVariableIn: thisContext sender sourceNodeExecuted) ifNil: [
^super doesNotUnderstand: aMessage ].

(exception := VariableNotDeclared new)
message: aMessage;
variableNode: node;
receiver: self.

resumeValue := exception signal.
^ exception reachedDefaultHandler
ifTrue: [ aMessage sentTo: self ]
ifFalse: [ resumeValue ] .


]

{ #category : #'class hierarchy' }
UndefinedObject >> environment [
"Necessary to support disjoint class hierarchies."

^self class environment
]

{ #category : #'reflective operations' }
UndefinedObject >> findUndeclaredVariableIn: ast [
"Walk the ast of the current statment and find the undeclared variable node, or nil (if none).
Assumes there is only one such variable in an executing statement"

ast nodesDo: [:node |
(node isVariable and: [ node isUndeclared]) ifTrue: [ ^node ]].

^nil
]

{ #category : #testing }
UndefinedObject >> haltIfNil [
<debuggerCompleteToSender>
Expand Down
35 changes: 35 additions & 0 deletions src/Kernel/VariableNotDeclared.class.st
@@ -0,0 +1,35 @@
"
This exception is provided to support doesNotUnderstand: on missing classes (Undeclared variables)
"
Class {
#name : #VariableNotDeclared,
#superclass : #MessageNotUnderstood,
#instVars : [
'variableNode'
],
#category : #'Kernel-Exceptions'
}

{ #category : #accessing }
VariableNotDeclared >> classSymbol [
^ self variableNode name
]

{ #category : #accessing }
VariableNotDeclared >> smartDescription [

message ifNil: [^self description].

^self classSymbol printString
, ' is missing, and does not understand ', message selector printString
]

{ #category : #accessing }
VariableNotDeclared >> variableNode [
^ variableNode
]

{ #category : #accessing }
VariableNotDeclared >> variableNode: anObject [
variableNode := anObject
]

0 comments on commit 724ed61

Please sign in to comment.