mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
Rewrote containsAnyOrUnknown so it support recursive detection.
This commit is contained in:
parent
5d083ac45a
commit
771b7e66bb
@ -198,7 +198,6 @@ import {
|
||||
computeMroLinearization,
|
||||
containsAnyOrUnknown,
|
||||
containsLiteralType,
|
||||
containsUnknown,
|
||||
convertParamSpecValueToType,
|
||||
convertToInstance,
|
||||
convertToInstantiable,
|
||||
@ -8218,16 +8217,21 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
|
||||
for (let dedupedIndex = 0; dedupedIndex < dedupedMatchResults.length; dedupedIndex++) {
|
||||
if (assignType(dedupedMatchResults[dedupedIndex], result.returnType)) {
|
||||
if (!containsAnyOrUnknown(dedupedMatchResults[dedupedIndex])) {
|
||||
const anyOrUnknown = containsAnyOrUnknown(
|
||||
dedupedMatchResults[dedupedIndex],
|
||||
/* recurse */ false
|
||||
);
|
||||
if (!anyOrUnknown) {
|
||||
isSubtypeSubsumed = true;
|
||||
} else if (!containsUnknown(dedupedMatchResults[dedupedIndex])) {
|
||||
} else if (isAny(anyOrUnknown)) {
|
||||
dedupedResultsIncludeAny = true;
|
||||
}
|
||||
break;
|
||||
} else if (assignType(result.returnType, dedupedMatchResults[dedupedIndex])) {
|
||||
if (!containsAnyOrUnknown(result.returnType)) {
|
||||
const anyOrUnknown = containsAnyOrUnknown(result.returnType, /* recurse */ false);
|
||||
if (!anyOrUnknown) {
|
||||
dedupedMatchResults[dedupedIndex] = NeverType.createNever();
|
||||
} else if (!containsUnknown(dedupedMatchResults[dedupedIndex])) {
|
||||
} else if (isAny(anyOrUnknown)) {
|
||||
dedupedResultsIncludeAny = true;
|
||||
}
|
||||
break;
|
||||
@ -15433,7 +15437,9 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
const decorator = node.decorators[i];
|
||||
|
||||
const newDecoratedType = applyClassDecorator(decoratedType, classType, decorator);
|
||||
if (containsUnknown(newDecoratedType)) {
|
||||
const unknownOrAny = containsAnyOrUnknown(newDecoratedType, /* recurse */ false);
|
||||
|
||||
if (unknownOrAny && isUnknown(unknownOrAny)) {
|
||||
// Report this error only on the first unknown type.
|
||||
if (!foundUnknown) {
|
||||
addDiagnostic(
|
||||
@ -16547,7 +16553,9 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
const decorator = node.decorators[i];
|
||||
|
||||
const newDecoratedType = applyFunctionDecorator(decoratedType, functionType, decorator, node);
|
||||
if (containsUnknown(newDecoratedType)) {
|
||||
const unknownOrAny = containsAnyOrUnknown(newDecoratedType, /* recurse */ false);
|
||||
|
||||
if (unknownOrAny && isUnknown(unknownOrAny)) {
|
||||
// Report this error only on the first unknown type.
|
||||
if (!foundUnknown) {
|
||||
addDiagnostic(
|
||||
|
@ -2103,32 +2103,42 @@ export function getMembersForModule(moduleType: ModuleType, symbolTable: SymbolT
|
||||
});
|
||||
}
|
||||
|
||||
// Determines if the type is an Any or Unknown or a union that
|
||||
// contains one of these. It does not look at type arguments.
|
||||
export function containsAnyOrUnknown(type: Type) {
|
||||
let foundAnyOrUnknown = false;
|
||||
// Determines if the type contains an Any or Unknown type. If so,
|
||||
// it returns the Any or Unknown type. Unknowns are preferred over
|
||||
// Any if both are present. If recurse is true, it will recurse
|
||||
// through type arguments and parameters.
|
||||
export function containsAnyOrUnknown(type: Type, recurse: boolean): AnyType | UnknownType | undefined {
|
||||
class AnyOrUnknownWalker extends TypeWalker {
|
||||
anyOrUnknownType: AnyType | UnknownType | undefined;
|
||||
|
||||
doForEachSubtype(type, (subtype) => {
|
||||
if (isAnyOrUnknown(subtype)) {
|
||||
foundAnyOrUnknown = true;
|
||||
constructor(private _recurse: boolean) {
|
||||
super();
|
||||
}
|
||||
});
|
||||
|
||||
return foundAnyOrUnknown;
|
||||
}
|
||||
|
||||
// Determines if the type is an Unknown or a union that contains an Unknown.
|
||||
// It does not look at type arguments.
|
||||
export function containsUnknown(type: Type) {
|
||||
let foundUnknown = false;
|
||||
|
||||
doForEachSubtype(type, (subtype) => {
|
||||
if (isUnknown(subtype)) {
|
||||
foundUnknown = true;
|
||||
override visitUnknown(type: UnknownType) {
|
||||
this.anyOrUnknownType = this.anyOrUnknownType ? preserveUnknown(this.anyOrUnknownType, type) : type;
|
||||
}
|
||||
});
|
||||
|
||||
return foundUnknown;
|
||||
override visitAny(type: AnyType) {
|
||||
this.anyOrUnknownType = this.anyOrUnknownType ? preserveUnknown(this.anyOrUnknownType, type) : type;
|
||||
}
|
||||
|
||||
override visitClass(type: ClassType) {
|
||||
if (this._recurse) {
|
||||
super.visitClass(type);
|
||||
}
|
||||
}
|
||||
|
||||
override visitFunction(type: FunctionType) {
|
||||
if (this._recurse) {
|
||||
super.visitFunction(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const walker = new AnyOrUnknownWalker(recurse);
|
||||
walker.walk(type);
|
||||
return walker.anyOrUnknownType;
|
||||
}
|
||||
|
||||
// Determines if any part of the type contains "Unknown", including any type arguments.
|
||||
|
Loading…
Reference in New Issue
Block a user