Fixed bug where classes declared in a conditional scope were not properly handled.

This commit is contained in:
Eric Traut 2019-08-16 22:09:39 -07:00
parent ec79598701
commit a08f9c6a24
4 changed files with 39 additions and 1 deletions

View File

@ -374,7 +374,8 @@ export class Scope {
if (this._parent) {
// If our recursion is about to take us outside the scope of the current
// module (i.e. into a built-in scope), indicate as such with the second parameter.
// module (i.e. into a built-in scope), indicate as such with the second
// parameter.
return this._parent._lookUpSymbolRecursiveInternal(name,
isOutsideCallerModule || this._scopeType === ScopeType.Module,
isBeyondExecutionScope || this.isIndependentlyExecutable());

View File

@ -3471,6 +3471,15 @@ export class TypeAnalyzer extends ParseTreeWalker {
let prevScope = this._currentScope;
let newScope = AnalyzerNodeInfo.getScope(node);
assert(newScope !== undefined);
let prevParent: Scope | undefined;
if (!newScope!.isIndependentlyExecutable()) {
// Temporary reparent the scope in case it is contained
// within a temporary scope.
prevParent = newScope!.getParent();
newScope!.setParent(this._currentScope);
}
this._currentScope = newScope!;
// Clear the raises/returns flags in case this wasn't our
@ -3486,6 +3495,9 @@ export class TypeAnalyzer extends ParseTreeWalker {
this._currentScope.clearTypeConstraints();
this._currentScope = prevScope;
if (prevParent) {
newScope!.setParent(prevParent);
}
return newScope!;
}

View File

@ -0,0 +1,19 @@
# This sample tests the type checker's ability to determine which
# symbols are potentially unbound.
if True:
class X:
# This should generate an error because 'X' is not yet declared.
def foo(self) -> X:
return X()
a: X
class A:
a: X
b = X
def fn(self) -> X:
return X()

View File

@ -523,3 +523,9 @@ test('UnnecessaryIsInstance1', () => {
analysisResults = TestUtils.typeAnalyzeSampleFiles(['unnecessaryIsInstance1.py'], configOptions);
validateResults(analysisResults, 3);
});
test('Unbound1', () => {
let analysisResults = TestUtils.typeAnalyzeSampleFiles(['unbound1.py']);
validateResults(analysisResults, 1);
});