Improved type checking for raise and raise/from statements.

This commit is contained in:
Eric Traut 2019-08-04 19:46:52 -07:00
parent ddba51efc5
commit b4e16e524f
2 changed files with 59 additions and 1 deletions

View File

@ -816,13 +816,67 @@ export class TypeAnalyzer extends ParseTreeWalker {
}
visitRaise(node: RaiseNode): boolean {
const baseExceptionType = ScopeUtils.getBuiltInType(
this._currentScope, 'BaseException') as ClassType;
if (node.typeExpression) {
this._markExpressionAccessed(node.typeExpression);
const exceptionType = this._getTypeOfExpression(node.typeExpression);
// Validate that the argument of "raise" is an exception object or class.
if (baseExceptionType) {
const diagAddendum = new DiagnosticAddendum();
TypeUtils.doForSubtypes(exceptionType, subtype => {
if (!subtype.isAny()) {
if (subtype instanceof ClassType) {
if (!TypeUtils.derivesFromClassRecursive(subtype, baseExceptionType)) {
diagAddendum.addMessage(`'${ subtype.asString() }' does not derive from BaseException`);
}
} else if (subtype instanceof ObjectType) {
if (!TypeUtils.derivesFromClassRecursive(subtype.getClassType(), baseExceptionType)) {
diagAddendum.addMessage(`'${ subtype.asString() }' does not derive from BaseException`);
}
} else {
diagAddendum.addMessage(`'${ subtype.asString() }' does not derive from BaseException`);
}
}
return subtype;
});
if (diagAddendum.getMessageCount() > 0) {
this._addError(`Expected exception class or object` + diagAddendum.getString(), node.typeExpression);
}
}
}
if (node.valueExpression) {
const exceptionType = this._getTypeOfExpression(node.valueExpression);
// TODO - validate that it's an exception type.
// Validate that the argument of "raise" is an exception object or None.
if (baseExceptionType) {
const diagAddendum = new DiagnosticAddendum();
TypeUtils.doForSubtypes(exceptionType, subtype => {
if (!subtype.isAny() && !(subtype instanceof NoneType)) {
if (subtype instanceof ObjectType) {
if (!TypeUtils.derivesFromClassRecursive(subtype.getClassType(), baseExceptionType)) {
diagAddendum.addMessage(`'${ subtype.asString() }' does not derive from BaseException`);
}
} else {
diagAddendum.addMessage(`'${ subtype.asString() }' does not derive from BaseException`);
}
}
return subtype;
});
if (diagAddendum.getMessageCount() > 0) {
this._addError(`Expected exception object or None` + diagAddendum.getString(), node.valueExpression);
}
}
}
if (!this._currentScope.getAlwaysReturns()) {

View File

@ -70,6 +70,10 @@ export class DiagnosticAddendum {
return '';
}
getMessageCount() {
return this._messages.length;
}
private _addAddendum(addendum: DiagnosticAddendum) {
this._childAddenda.push(addendum);
}