diff --git a/src/AST-Core/RBNotice.class.st b/src/AST-Core/RBNotice.class.st index 512961e29a0..32c7f7e8ecf 100644 --- a/src/AST-Core/RBNotice.class.st +++ b/src/AST-Core/RBNotice.class.st @@ -84,3 +84,11 @@ RBNotice >> printOn: aStream [ nextPutAll: self messageText; nextPutAll: ')' ] + +{ #category : #signalling } +RBNotice >> signalError [ + + CodeError new + notice: self; + signal +] diff --git a/src/AST-Core/RBProgramNode.class.st b/src/AST-Core/RBProgramNode.class.st index 6c3194c4fa4..0f0274cd42b 100644 --- a/src/AST-Core/RBProgramNode.class.st +++ b/src/AST-Core/RBProgramNode.class.st @@ -95,9 +95,12 @@ RBProgramNode >> addReplacement: aStringReplacement [ { #category : #notice } RBProgramNode >> addWarning: aMessage [ + | notice | "Add a warning information to the node. Semantic passes that check the validity of AST are the targetted clients of this method." - self addNotice: (RBWarningNotice new messageText: aMessage) + notice := RBWarningNotice new messageText: aMessage. + self addNotice: notice. + ^ notice ] { #category : #accessing } @@ -313,9 +316,7 @@ RBProgramNode >> checkFaulty: aBlock [ aBlock ifNotNil: [ aBlock cull: errorNotice messageText cull: errorNotice position cull: self ]. - CodeError new - notice: errorNotice; - signal. + errorNotice signalError. "If resumed, just return" ] diff --git a/src/CodeImportCommandLineHandlers/STCommandLineHandler.class.st b/src/CodeImportCommandLineHandlers/STCommandLineHandler.class.st index 6e47b4f4693..802d285060f 100644 --- a/src/CodeImportCommandLineHandlers/STCommandLineHandler.class.st +++ b/src/CodeImportCommandLineHandlers/STCommandLineHandler.class.st @@ -124,10 +124,6 @@ STCommandLineHandler >> handleError: error [ STCommandLineHandler >> handleError: error reference: aReference [ "Print a header before failing on an errro / syntax notification from the the script loaded by the given request" - "We ignore warnings for now" - (error isKindOf: OCSemanticWarning) - ifTrue: [ ^ error pass ]. - "Display CodeError nicely" (error isKindOf: CodeError) ifTrue: [ self class printCodeError: error ]. @@ -142,7 +138,7 @@ STCommandLineHandler >> handleError: error reference: aReference [ { #category : #installing } STCommandLineHandler >> handleErrorsDuring: aBlock reference: aReference [ aBlock - on: Error, OCSemanticWarning + on: Error do: [ :e | self handleError: e reference: aReference ] ] diff --git a/src/OpalCompiler-Core/OCASTSemanticAnalyzer.class.st b/src/OpalCompiler-Core/OCASTSemanticAnalyzer.class.st index 9ed7d6b2441..68414a01f4e 100644 --- a/src/OpalCompiler-Core/OCASTSemanticAnalyzer.class.st +++ b/src/OpalCompiler-Core/OCASTSemanticAnalyzer.class.st @@ -150,13 +150,14 @@ OCASTSemanticAnalyzer >> undeclared [ { #category : #'error handling' } OCASTSemanticAnalyzer >> undeclaredVariable: variableNode [ - | varName var | + | varName var notice | varName := variableNode name asSymbol. "If a invalid variable exists, we use it witout warning" self invalidVariables at: varName ifPresent: [ :v | ^ v ]. - variableNode addWarning: 'Undeclared variable'. + notice := OCUndeclaredVariableNotice new messageText: 'Undeclared variable'. + variableNode addNotice: notice. "If a registered undeclared variable exists, use it. Otherwise create an unregistered one." "It will be registered only at backend when a CompiledMethod is produced. Or never if compilation is aborted or if only frontend is requested." @@ -164,14 +165,6 @@ OCASTSemanticAnalyzer >> undeclaredVariable: variableNode [ at: varName ifAbsentPut: [ UndeclaredVariable possiblyRegisteredWithName: varName ]. - compilationContext permitFaulty ifTrue: [ ^ var ]. - - OCUndeclaredVariableWarning new - node: variableNode; - compilationContext: compilationContext; - messageText: 'Undeclared variable'; - signal. - ^ var ] diff --git a/src/OpalCompiler-Core/OCSemanticWarning.class.st b/src/OpalCompiler-Core/OCSemanticWarning.class.st deleted file mode 100644 index 123e25baf31..00000000000 --- a/src/OpalCompiler-Core/OCSemanticWarning.class.st +++ /dev/null @@ -1,64 +0,0 @@ -" -If a variable is not found or some other problem occurs during checking (ASTChecker) than a particular subclass instance of me is signal, usually causing a notification to the user. If not handled, the default handling is done, and compiling continues. -" -Class { - #name : #OCSemanticWarning, - #superclass : #Notification, - #instVars : [ - 'compilationContext', - 'node' - ], - #category : #'OpalCompiler-Core-Exception' -} - -{ #category : #accessing } -OCSemanticWarning >> compilationContext [ - ^ compilationContext -] - -{ #category : #accessing } -OCSemanticWarning >> compilationContext: anObject [ - compilationContext := anObject -] - -{ #category : #'accessing - compatibility' } -OCSemanticWarning >> errorCode [ - self requestor ifNil: [ - ^ self node methodNode asString ]. - ^ self requestor contents -] - -{ #category : #'accessing - compatibility' } -OCSemanticWarning >> errorMessage [ - ^ self messageText -] - -{ #category : #'accessing - compatibility' } -OCSemanticWarning >> location [ - ^ self node sourceInterval first -] - -{ #category : #correcting } -OCSemanticWarning >> methodClass [ - ^node methodNode methodClass -] - -{ #category : #correcting } -OCSemanticWarning >> methodNode [ - ^node methodNode -] - -{ #category : #accessing } -OCSemanticWarning >> node [ - ^node -] - -{ #category : #accessing } -OCSemanticWarning >> node: anObject [ - node := anObject -] - -{ #category : #accessing } -OCSemanticWarning >> requestor [ - ^ compilationContext requestor -] diff --git a/src/OpalCompiler-Core/OCUndeclaredVariableNotice.class.st b/src/OpalCompiler-Core/OCUndeclaredVariableNotice.class.st new file mode 100644 index 00000000000..8a26700677c --- /dev/null +++ b/src/OpalCompiler-Core/OCUndeclaredVariableNotice.class.st @@ -0,0 +1,13 @@ +Class { + #name : #OCUndeclaredVariableNotice, + #superclass : #RBNotice, + #category : #'OpalCompiler-Core-FrontEnd' +} + +{ #category : #signalling } +OCUndeclaredVariableNotice >> signalError [ + + OCUndeclaredVariableWarning new + notice: self; + signal +] diff --git a/src/OpalCompiler-Core/OCUndeclaredVariableWarning.class.st b/src/OpalCompiler-Core/OCUndeclaredVariableWarning.class.st index 0733aea4379..21725638d0b 100644 --- a/src/OpalCompiler-Core/OCUndeclaredVariableWarning.class.st +++ b/src/OpalCompiler-Core/OCUndeclaredVariableWarning.class.st @@ -3,7 +3,10 @@ I get signalled when a temporary variable is used that is not defined. My defau " Class { #name : #OCUndeclaredVariableWarning, - #superclass : #OCSemanticWarning, + #superclass : #Notification, + #instVars : [ + 'notice' + ], #category : #'OpalCompiler-Core-Exception' } @@ -13,15 +16,60 @@ OCUndeclaredVariableWarning >> defaultAction [ className := self methodClass name. selector := self methodNode selector. - NewUndeclaredWarning signal: node name in: (selector + NewUndeclaredWarning signal: self node name in: (selector ifNotNil: [className, '>>', selector] ifNil: ['']). ^ super defaultAction ] +{ #category : #accessing } +OCUndeclaredVariableWarning >> description [ + + ^ self class name , ':' , self notice description +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> methodClass [ + ^ self methodNode methodClass +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> methodNode [ + ^ self node methodNode +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> node [ + ^ self notice node +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> notice [ + + ^ notice +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> notice: anObject [ + + notice := anObject +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> position [ + + ^ self notice position +] + { #category : #correcting } OCUndeclaredVariableWarning >> reparator [ - ^ OCCodeReparator new node: node + ^ OCCodeReparator new node: self node +] + +{ #category : #accessing } +OCUndeclaredVariableWarning >> sourceCode [ + + ^ self methodNode sourceCode ] diff --git a/src/OpalCompiler-Core/OpalCompiler.class.st b/src/OpalCompiler-Core/OpalCompiler.class.st index 08c35350b83..9d8b859741b 100644 --- a/src/OpalCompiler-Core/OpalCompiler.class.st +++ b/src/OpalCompiler-Core/OpalCompiler.class.st @@ -447,13 +447,12 @@ OpalCompiler >> parse [ parser initializeParserWith: source contents. ast := self semanticScope parseASTBy: parser. - self permitFaulty ifFalse: [ ast checkFaulty: nil ]. - ast methodNode compilationContext: self compilationContext. self callParsePlugins. self doSemanticAnalysis. - self permitFaulty ifFalse: [ ast checkFaulty: nil ]. + self permitFaulty ifFalse: [ + ast allNotices do: [ :n | n isWarning ifFalse: [ n signalError ] ] ]. ^ ast ] @@ -480,37 +479,33 @@ OpalCompiler >> parseForRequestor [ "No requestor, easy path" requestor ifNil: [ ^ self parse ]. - ^ [ [ self parse ] - on: OCUndeclaredVariableWarning - do: [ :notification | - | res | - self isInteractive ifFalse: [ notification pass ]. - "The menu is in fact broken on 'noPattern' mode (expression/script/doit) because some reparation assume it's a method body, so just signal as an error (on: block bellow)" - self compilationContext noPattern ifTrue: [ - CodeError new - notice: notification node notices first; "Ugly temporary hack" - signal. - ]. - "I do not like the API that much. - reparator can have 3 outcomes: - * reparation done, reparse. true - * reparation unneded, pass. nil - * operation cancelled, fail. false" - res := notification reparator - requestor: requestor; - openMenu. - res ifNil: [ notification pass ]. - res ifFalse: [ ^ self compilationContext failBlock value ]. - self source: requestor text. - notification retry ] ] - on: CodeError - do: [ :exception | - ast := nil. "Invalidate the AST to avoid compilation if failBlock do return" - requestor - notify: exception messageText , ' ->' - at: exception position - in: exception sourceCode. - self compilationContext failBlock value ] + ^ [ self parse ] + on: OCUndeclaredVariableWarning , CodeError + do: [ :exception | + exception class = OCUndeclaredVariableWarning ifTrue: [ + self isInteractive ifFalse: [ exception pass ]. + "The menu is in fact broken on 'noPattern' mode (expression/script/doit) because some reparation assume it's a method body, so just continue as an error" + self compilationContext noPattern ifFalse: [ + | res | + "I do not like the API that much. + reparator can have 3 outcomes: + * reparation done, reparse. true + * reparation unneded, pass. nil + * operation cancelled, fail. false" + res := exception reparator + requestor: requestor; + openMenu. + res ifNil: [ exception pass ]. + res ifFalse: [ ^ self compilationContext failBlock value ]. + self source: requestor text. + exception retry ] ]. + + ast := nil. "Invalidate the AST to avoid compilation if failBlock do return" + requestor + notify: exception messageText , ' ->' + at: exception position + in: exception sourceCode. + self compilationContext failBlock value ] ] { #category : #'public access' }