From 8b1892444236b43010c47f0688fd9c5245e94fed Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 14 Nov 2019 21:45:27 -0800 Subject: [PATCH] Fixed a few more bugs. --- server/src/analyzer/typeEvaluator.ts | 28 +++++++++++++++++++++------- server/src/analyzer/types.ts | 7 ++++++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/server/src/analyzer/typeEvaluator.ts b/server/src/analyzer/typeEvaluator.ts index f08c8c254..320a6ade2 100644 --- a/server/src/analyzer/typeEvaluator.ts +++ b/server/src/analyzer/typeEvaluator.ts @@ -4650,6 +4650,9 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { function getTypeFromLambda(node: LambdaNode, expectedType?: Type): TypeResult { const functionType = FunctionType.create(FunctionTypeFlags.None); + // Pre-cache the newly-created function type. + writeTypeCache(node, functionType); + let expectedFunctionType: FunctionType | undefined; if (expectedType) { if (expectedType.category === TypeCategory.Function) { @@ -4669,7 +4672,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { } if (param.name) { - assignTypeToExpression(param.name, paramType); + writeTypeCache(param.name, paramType); } const functionParam: FunctionParameter = { @@ -5552,6 +5555,10 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { functionFlags |= FunctionTypeFlags.Generator; } + if (fileInfo.isStubFile) { + functionFlags |= FunctionTypeFlags.StubDefinition; + } + if (node.isAsync) { functionFlags |= FunctionTypeFlags.Async; } @@ -6347,20 +6354,23 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { let lastContextualExpression = node; let curNode: ParseNode | undefined = node; - function isContextualExpression(node: ExpressionNode) { + function isContextual(node: ParseNode) { return node.nodeType === ParseNodeType.Call || node.nodeType === ParseNodeType.Dictionary || node.nodeType === ParseNodeType.List || node.nodeType === ParseNodeType.Lambda || node.nodeType === ParseNodeType.Set || node.nodeType === ParseNodeType.Tuple || - node.nodeType === ParseNodeType.Unpack; + node.nodeType === ParseNodeType.Unpack || + node.nodeType === ParseNodeType.DictionaryKeyEntry || + node.nodeType === ParseNodeType.DictionaryExpandEntry || + node.nodeType === ParseNodeType.ListComprehension; } // Scan up the parse tree until we find a non-expression, looking for // contextual expressions in the process. - while (curNode && isExpressionNode(curNode)) { - if (isContextualExpression(curNode as ExpressionNode)) { + while (curNode && (isExpressionNode(curNode) || isContextual(curNode))) { + if (isContextual(curNode)) { lastContextualExpression = curNode as ExpressionNode; } @@ -6573,8 +6583,12 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { callIsNoReturn = isNoReturnType(functionType.inferredReturnType); } else if (functionType.details.declaration) { // If the function has yield expressions, it's a generator, and - // we'll assume the yield statements are reachable. - if (!functionType.details.declaration.yieldExpressions) { + // we'll assume the yield statements are reachable. Also, don't + // infer a "no return" type for abstract methods. + if (!functionType.details.declaration.yieldExpressions && + !FunctionType.isAbstractMethod(functionType) && + !FunctionType.isStubDefinition(functionType)) { + callIsNoReturn = !isAfterNodeReachable(functionType.details.declaration.node); } } diff --git a/server/src/analyzer/types.ts b/server/src/analyzer/types.ts index 169ac9fef..820c10d41 100644 --- a/server/src/analyzer/types.ts +++ b/server/src/analyzer/types.ts @@ -516,7 +516,8 @@ export const enum FunctionTypeFlags { SynthesizedMethod = 1 << 7, Overloaded = 1 << 8, Async = 1 << 9, - WrapReturnTypeInAwait = 1 << 10 + WrapReturnTypeInAwait = 1 << 10, + StubDefinition = 1 << 11 } interface FunctionDetails { @@ -652,6 +653,10 @@ export namespace FunctionType { return (type.details.flags & FunctionTypeFlags.WrapReturnTypeInAwait) !== 0; } + export function isStubDefinition(type: FunctionType) { + return (type.details.flags & FunctionTypeFlags.StubDefinition) !== 0; + } + export function getEffectiveParameterType(type: FunctionType, index: number): Type { assert(index < type.details.parameters.length); if (type.specializedTypes) {