mirror of
https://github.com/microsoft/pyright.git
synced 2024-08-17 11:50:22 +03:00
Merge branch 'main' into add-azure-devops-release
This commit is contained in:
commit
ba50f35bb1
4
.github/workflows/mypy_primer_pr.yaml
vendored
4
.github/workflows/mypy_primer_pr.yaml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
shard-index: [0, 1]
|
||||
shard-index: [0, 1, 2, 3, 4, 5, 6, 7]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
--repo pyright_to_test \
|
||||
--type-checker pyright \
|
||||
--new $GITHUB_SHA --old base_commit \
|
||||
--num-shards 2 --shard-index ${{ matrix.shard-index }} \
|
||||
--num-shards 8 --shard-index ${{ matrix.shard-index }} \
|
||||
--debug \
|
||||
--output concise \
|
||||
| tee diff_${{ matrix.shard-index }}.txt
|
||||
|
@ -3092,106 +3092,123 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
private _reportInvalidOverload(name: string, symbol: Symbol) {
|
||||
const typedDecls = symbol.getTypedDeclarations();
|
||||
if (typedDecls.length >= 1) {
|
||||
const primaryDecl = typedDecls[0];
|
||||
if (typedDecls.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (primaryDecl.type === DeclarationType.Function) {
|
||||
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
|
||||
const overloadedFunctions = isOverloadedFunction(type)
|
||||
? OverloadedFunctionType.getOverloads(type)
|
||||
: isFunction(type) && FunctionType.isOverloaded(type)
|
||||
? [type]
|
||||
: [];
|
||||
const primaryDecl = typedDecls[0];
|
||||
|
||||
if (overloadedFunctions.length === 1) {
|
||||
// There should never be a single overload.
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportInconsistentOverload,
|
||||
LocMessage.singleOverload().format({ name }),
|
||||
primaryDecl.node.name
|
||||
);
|
||||
}
|
||||
if (primaryDecl.type !== DeclarationType.Function) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the file is not a stub and this is the first overload,
|
||||
// verify that there is an implementation.
|
||||
if (!this._fileInfo.isStubFile && overloadedFunctions.length > 0) {
|
||||
let implementationFunction: FunctionType | undefined;
|
||||
let exemptMissingImplementation = false;
|
||||
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
|
||||
const overloadedFunctions = isOverloadedFunction(type)
|
||||
? OverloadedFunctionType.getOverloads(type)
|
||||
: isFunction(type) && FunctionType.isOverloaded(type)
|
||||
? [type]
|
||||
: [];
|
||||
|
||||
if (isOverloadedFunction(type)) {
|
||||
implementationFunction = OverloadedFunctionType.getImplementation(type);
|
||||
// If the implementation has no name, it was synthesized probably by a
|
||||
// decorator that used a callable with a ParamSpec that captured the
|
||||
// overloaded signature. We'll exempt it from this check.
|
||||
if (isOverloadedFunction(type)) {
|
||||
const overloads = OverloadedFunctionType.getOverloads(type);
|
||||
if (overloads.length > 0 && overloads[0].details.name === '') {
|
||||
return;
|
||||
}
|
||||
} else if (isFunction(type)) {
|
||||
if (type.details.name === '') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the implementation has no name, it was synthesized probably by a
|
||||
// decorator that used a callable with a ParamSpec that captured the
|
||||
// overloaded signature. We'll exempt it from this check.
|
||||
const overloads = OverloadedFunctionType.getOverloads(type);
|
||||
if (overloads.length > 0 && overloads[0].details.name === '') {
|
||||
exemptMissingImplementation = true;
|
||||
}
|
||||
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) {
|
||||
implementationFunction = type;
|
||||
if (overloadedFunctions.length === 1) {
|
||||
// There should never be a single overload.
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportInconsistentOverload,
|
||||
LocMessage.singleOverload().format({ name }),
|
||||
primaryDecl.node.name
|
||||
);
|
||||
}
|
||||
|
||||
// If the file is not a stub and this is the first overload,
|
||||
// verify that there is an implementation.
|
||||
if (this._fileInfo.isStubFile || overloadedFunctions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let implementationFunction: FunctionType | undefined;
|
||||
|
||||
if (isOverloadedFunction(type)) {
|
||||
implementationFunction = OverloadedFunctionType.getImplementation(type);
|
||||
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) {
|
||||
implementationFunction = type;
|
||||
}
|
||||
|
||||
if (!implementationFunction) {
|
||||
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node);
|
||||
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) {
|
||||
const classType = this._evaluator.getTypeOfClass(containingClassNode);
|
||||
if (classType) {
|
||||
if (ClassType.isProtocolClass(classType.classType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implementationFunction) {
|
||||
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node);
|
||||
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) {
|
||||
const classType = this._evaluator.getTypeOfClass(containingClassNode);
|
||||
if (classType) {
|
||||
if (ClassType.isProtocolClass(classType.classType)) {
|
||||
exemptMissingImplementation = true;
|
||||
} else if (ClassType.supportsAbstractMethods(classType.classType)) {
|
||||
if (
|
||||
isOverloadedFunction(type) &&
|
||||
OverloadedFunctionType.getOverloads(type).every((overload) =>
|
||||
FunctionType.isAbstractMethod(overload)
|
||||
)
|
||||
) {
|
||||
exemptMissingImplementation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ClassType.supportsAbstractMethods(classType.classType)) {
|
||||
if (
|
||||
isOverloadedFunction(type) &&
|
||||
OverloadedFunctionType.getOverloads(type).every((overload) =>
|
||||
FunctionType.isAbstractMethod(overload)
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a method within a protocol class, don't require that
|
||||
// there is an implementation.
|
||||
if (!exemptMissingImplementation) {
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportNoOverloadImplementation,
|
||||
LocMessage.overloadWithoutImplementation().format({
|
||||
name: primaryDecl.node.name.value,
|
||||
}),
|
||||
primaryDecl.node.name
|
||||
);
|
||||
}
|
||||
} else if (isOverloadedFunction(type)) {
|
||||
// Verify that all overload signatures are assignable to implementation signature.
|
||||
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
|
||||
const diag = new DiagnosticAddendum();
|
||||
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
|
||||
if (implementationFunction!.details.declaration) {
|
||||
const diagnostic = this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportInconsistentOverload,
|
||||
LocMessage.overloadImplementationMismatch().format({
|
||||
name,
|
||||
index: index + 1,
|
||||
}) + diag.getString(),
|
||||
implementationFunction!.details.declaration.node.name
|
||||
);
|
||||
|
||||
if (diagnostic && overload.details.declaration) {
|
||||
diagnostic.addRelatedInfo(
|
||||
LocAddendum.overloadSignature(),
|
||||
overload.details.declaration?.uri ?? primaryDecl.uri,
|
||||
overload.details.declaration?.range ?? primaryDecl.range
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a method within a protocol class, don't require that
|
||||
// there is an implementation.
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportNoOverloadImplementation,
|
||||
LocMessage.overloadWithoutImplementation().format({
|
||||
name: primaryDecl.node.name.value,
|
||||
}),
|
||||
primaryDecl.node.name
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isOverloadedFunction(type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that all overload signatures are assignable to implementation signature.
|
||||
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
|
||||
const diag = new DiagnosticAddendum();
|
||||
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
|
||||
if (implementationFunction!.details.declaration) {
|
||||
const diagnostic = this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportInconsistentOverload,
|
||||
LocMessage.overloadImplementationMismatch().format({
|
||||
name,
|
||||
index: index + 1,
|
||||
}) + diag.getString(),
|
||||
implementationFunction!.details.declaration.node.name
|
||||
);
|
||||
|
||||
if (diagnostic && overload.details.declaration) {
|
||||
diagnostic.addRelatedInfo(
|
||||
LocAddendum.overloadSignature(),
|
||||
overload.details.declaration?.uri ?? primaryDecl.uri,
|
||||
overload.details.declaration?.range ?? primaryDecl.range
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _reportMultipleFinalDeclarations(name: string, symbol: Symbol, scopeType: ScopeType) {
|
||||
|
@ -134,6 +134,11 @@ export interface IncompleteType {
|
||||
isRecursionSentinel?: boolean;
|
||||
}
|
||||
|
||||
interface ReachabilityCacheEntry {
|
||||
isReachable: boolean | undefined;
|
||||
isReachableFrom: Map<number, boolean>;
|
||||
}
|
||||
|
||||
// Define a user type guard function for IncompleteType.
|
||||
export function isIncompleteType(cachedType: CachedType): cachedType is IncompleteType {
|
||||
return !!(cachedType as IncompleteType).isIncompleteType;
|
||||
@ -164,6 +169,7 @@ export function getCodeFlowEngine(
|
||||
speculativeTypeTracker: SpeculativeTypeTracker
|
||||
): CodeFlowEngine {
|
||||
const isReachableRecursionSet = new Set<number>();
|
||||
const reachabilityCache = new Map<number, ReachabilityCacheEntry>();
|
||||
const callIsNoReturnCache = new Map<number, boolean>();
|
||||
const isExceptionContextManagerCache = new Map<number, boolean>();
|
||||
let flowIncompleteGeneration = 1;
|
||||
@ -1182,11 +1188,29 @@ export function getCodeFlowEngine(
|
||||
printControlFlowGraph(flowNode, /* reference */ undefined, 'isFlowNodeReachable');
|
||||
}
|
||||
|
||||
function isFlowNodeReachableRecursive(
|
||||
flowNode: FlowNode,
|
||||
sourceFlowNode: FlowNode | undefined,
|
||||
recursionCount = 0
|
||||
): boolean {
|
||||
function cacheReachabilityResult(isReachable: boolean): boolean {
|
||||
// If there is a finally gate set, we will not cache the results
|
||||
// because this can affect the reachability.
|
||||
if (closedFinallyGateSet.size > 0) {
|
||||
return isReachable;
|
||||
}
|
||||
|
||||
let cacheEntry = reachabilityCache.get(flowNode.id);
|
||||
if (!cacheEntry) {
|
||||
cacheEntry = { isReachable: undefined, isReachableFrom: new Map<number, boolean>() };
|
||||
reachabilityCache.set(flowNode.id, cacheEntry);
|
||||
}
|
||||
|
||||
if (!sourceFlowNode) {
|
||||
cacheEntry.isReachable = isReachable;
|
||||
} else {
|
||||
cacheEntry.isReachableFrom.set(sourceFlowNode.id, isReachable);
|
||||
}
|
||||
|
||||
return isReachable;
|
||||
}
|
||||
|
||||
function isFlowNodeReachableRecursive(flowNode: FlowNode, recursionCount = 0): boolean {
|
||||
// Cut off the recursion at some point to prevent a stack overflow.
|
||||
const maxFlowNodeReachableRecursionCount = 64;
|
||||
if (recursionCount > maxFlowNodeReachableRecursionCount) {
|
||||
@ -1197,21 +1221,36 @@ export function getCodeFlowEngine(
|
||||
let curFlowNode = flowNode;
|
||||
|
||||
while (true) {
|
||||
// See if we've already cached this result.
|
||||
const cacheEntry = reachabilityCache.get(flowNode.id);
|
||||
if (cacheEntry !== undefined && closedFinallyGateSet.size === 0) {
|
||||
if (!sourceFlowNode) {
|
||||
if (cacheEntry.isReachable !== undefined) {
|
||||
return cacheEntry.isReachable;
|
||||
}
|
||||
} else {
|
||||
const isReachableFrom = cacheEntry.isReachableFrom.get(sourceFlowNode.id);
|
||||
if (isReachableFrom !== undefined) {
|
||||
return isReachableFrom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we've already visited this node, we can assume
|
||||
// it wasn't reachable.
|
||||
if (visitedFlowNodeSet.has(curFlowNode.id)) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
|
||||
// Note that we've been here before.
|
||||
visitedFlowNodeSet.add(curFlowNode.id);
|
||||
|
||||
if (curFlowNode.flags & FlowFlags.Unreachable) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
|
||||
if (curFlowNode === sourceFlowNode) {
|
||||
return true;
|
||||
return cacheReachabilityResult(true);
|
||||
}
|
||||
|
||||
if (
|
||||
@ -1271,7 +1310,7 @@ export function getCodeFlowEngine(
|
||||
}
|
||||
|
||||
if (isUnreachable) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1287,7 +1326,7 @@ export function getCodeFlowEngine(
|
||||
// it always raises an exception or otherwise doesn't return,
|
||||
// so we can assume that the code before this is unreachable.
|
||||
if (!ignoreNoReturn && isCallNoReturn(evaluator, callFlowNode)) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
|
||||
curFlowNode = callFlowNode.antecedent;
|
||||
@ -1304,29 +1343,29 @@ export function getCodeFlowEngine(
|
||||
isExceptionContextManager(evaluator, expr, contextMgrNode.isAsync)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
const labelNode = curFlowNode as FlowLabel;
|
||||
for (const antecedent of labelNode.antecedents) {
|
||||
if (isFlowNodeReachableRecursive(antecedent, sourceFlowNode, recursionCount)) {
|
||||
return true;
|
||||
if (isFlowNodeReachableRecursive(antecedent, recursionCount)) {
|
||||
return cacheReachabilityResult(true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
|
||||
if (curFlowNode.flags & FlowFlags.Start) {
|
||||
// If we hit the start but were looking for a particular source flow
|
||||
// node, return false. Otherwise, the start is what we're looking for.
|
||||
return sourceFlowNode ? false : true;
|
||||
return cacheReachabilityResult(sourceFlowNode ? false : true);
|
||||
}
|
||||
|
||||
if (curFlowNode.flags & FlowFlags.PreFinallyGate) {
|
||||
const preFinallyFlowNode = curFlowNode as FlowPreFinallyGate;
|
||||
if (closedFinallyGateSet.has(preFinallyFlowNode.id)) {
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
|
||||
curFlowNode = preFinallyFlowNode.antecedent;
|
||||
@ -1339,10 +1378,8 @@ export function getCodeFlowEngine(
|
||||
|
||||
try {
|
||||
closedFinallyGateSet.add(postFinallyFlowNode.preFinallyGate.id);
|
||||
return isFlowNodeReachableRecursive(
|
||||
postFinallyFlowNode.antecedent,
|
||||
sourceFlowNode,
|
||||
recursionCount
|
||||
return cacheReachabilityResult(
|
||||
isFlowNodeReachableRecursive(postFinallyFlowNode.antecedent, recursionCount)
|
||||
);
|
||||
} finally {
|
||||
if (!wasGateClosed) {
|
||||
@ -1353,7 +1390,7 @@ export function getCodeFlowEngine(
|
||||
|
||||
// We shouldn't get here.
|
||||
fail('Unexpected flow node flags');
|
||||
return false;
|
||||
return cacheReachabilityResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1364,7 +1401,7 @@ export function getCodeFlowEngine(
|
||||
isReachableRecursionSet.add(flowNode.id);
|
||||
|
||||
try {
|
||||
return isFlowNodeReachableRecursive(flowNode, sourceFlowNode);
|
||||
return isFlowNodeReachableRecursive(flowNode);
|
||||
} finally {
|
||||
isReachableRecursionSet.delete(flowNode.id);
|
||||
}
|
||||
|
@ -1020,7 +1020,7 @@ function assignTypeToParamSpec(
|
||||
// performs this reverse mapping of type arguments and populates the type var
|
||||
// map for the target type. If the type is not assignable to the expected type,
|
||||
// it returns false.
|
||||
export function populateTypeVarContextBasedOnExpectedType(
|
||||
export function addConstraintsForExpectedType(
|
||||
evaluator: TypeEvaluator,
|
||||
type: ClassType,
|
||||
expectedType: Type,
|
||||
|
@ -17,7 +17,7 @@ import { DiagnosticAddendum } from '../common/diagnostic';
|
||||
import { DiagnosticRule } from '../common/diagnosticRules';
|
||||
import { LocMessage } from '../localization/localize';
|
||||
import { ArgumentCategory, ExpressionNode, ParameterCategory } from '../parser/parseNodes';
|
||||
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
|
||||
import { addConstraintsForExpectedType } from './constraintSolver';
|
||||
import { applyConstructorTransform, hasConstructorTransform } from './constructorTransform';
|
||||
import { getTypeVarScopesForNode } from './parseTreeUtils';
|
||||
import { CallResult, FunctionArgument, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
|
||||
@ -25,14 +25,17 @@ import {
|
||||
InferenceContext,
|
||||
MemberAccessFlags,
|
||||
UniqueSignatureTracker,
|
||||
addTypeVarsToListIfUnique,
|
||||
applySolvedTypeVars,
|
||||
buildTypeVarContextFromSpecializedClass,
|
||||
convertToInstance,
|
||||
convertTypeToParamSpecValue,
|
||||
doForEachSignature,
|
||||
doForEachSubtype,
|
||||
ensureFunctionSignaturesAreUnique,
|
||||
getTypeVarArgumentsRecursive,
|
||||
getTypeVarScopeId,
|
||||
getTypeVarScopeIds,
|
||||
isTupleClass,
|
||||
lookUpClassMember,
|
||||
mapSubtypes,
|
||||
@ -60,6 +63,7 @@ import {
|
||||
isInstantiableClass,
|
||||
isNever,
|
||||
isOverloadedFunction,
|
||||
isParamSpec,
|
||||
isTypeVar,
|
||||
isUnion,
|
||||
isUnknown,
|
||||
@ -286,7 +290,7 @@ function validateNewAndInitMethods(
|
||||
newMethodReturnType = applySolvedTypeVars(
|
||||
ClassType.cloneAsInstance(type),
|
||||
new TypeVarContext(getTypeVarScopeId(type)),
|
||||
{ unknownIfNotFound: true }
|
||||
{ unknownIfNotFound: true, tupleClassType: evaluator.getTupleClassType() }
|
||||
) as ClassType;
|
||||
}
|
||||
|
||||
@ -539,7 +543,7 @@ function validateInitMethod(
|
||||
typeVarContext.addSolveForScope(getTypeVarScopeId(initMethodType));
|
||||
|
||||
if (
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
!addConstraintsForExpectedType(
|
||||
evaluator,
|
||||
ClassType.cloneAsInstance(type),
|
||||
expectedSubType,
|
||||
@ -548,54 +552,56 @@ function validateInitMethod(
|
||||
errorNode.start
|
||||
)
|
||||
) {
|
||||
const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext);
|
||||
|
||||
let callResult: CallResult | undefined;
|
||||
callResult = evaluator.useSpeculativeMode(errorNode, () => {
|
||||
return evaluator.validateCallArguments(
|
||||
errorNode,
|
||||
argList,
|
||||
{ type: specializedConstructor },
|
||||
typeVarContext.clone(),
|
||||
skipUnknownArgCheck,
|
||||
/* inferenceContext */ undefined,
|
||||
signatureTracker
|
||||
);
|
||||
});
|
||||
|
||||
if (!callResult.argumentErrors) {
|
||||
// Call validateCallArguments again, this time without speculative
|
||||
// mode, so any errors are reported.
|
||||
callResult = evaluator.validateCallArguments(
|
||||
errorNode,
|
||||
argList,
|
||||
{ type: specializedConstructor },
|
||||
typeVarContext,
|
||||
skipUnknownArgCheck,
|
||||
/* inferenceContext */ undefined,
|
||||
signatureTracker
|
||||
);
|
||||
|
||||
if (callResult.isTypeIncomplete) {
|
||||
isTypeIncomplete = true;
|
||||
}
|
||||
|
||||
if (callResult.argumentErrors) {
|
||||
argumentErrors = true;
|
||||
}
|
||||
|
||||
if (callResult.overloadsUsedForCall) {
|
||||
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
|
||||
}
|
||||
|
||||
// Note that we've found an expected type that works.
|
||||
foundWorkingExpectedType = true;
|
||||
|
||||
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext);
|
||||
|
||||
let callResult: CallResult | undefined;
|
||||
callResult = evaluator.useSpeculativeMode(errorNode, () => {
|
||||
return evaluator.validateCallArguments(
|
||||
errorNode,
|
||||
argList,
|
||||
{ type: specializedConstructor },
|
||||
typeVarContext.clone(),
|
||||
skipUnknownArgCheck,
|
||||
/* inferenceContext */ undefined,
|
||||
signatureTracker
|
||||
);
|
||||
});
|
||||
|
||||
if (callResult.argumentErrors) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Call validateCallArguments again, this time without speculative
|
||||
// mode, so any errors are reported.
|
||||
callResult = evaluator.validateCallArguments(
|
||||
errorNode,
|
||||
argList,
|
||||
{ type: specializedConstructor },
|
||||
typeVarContext,
|
||||
skipUnknownArgCheck,
|
||||
/* inferenceContext */ undefined,
|
||||
signatureTracker
|
||||
);
|
||||
|
||||
if (callResult.isTypeIncomplete) {
|
||||
isTypeIncomplete = true;
|
||||
}
|
||||
|
||||
if (callResult.argumentErrors) {
|
||||
argumentErrors = true;
|
||||
}
|
||||
|
||||
if (callResult.overloadsUsedForCall) {
|
||||
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
|
||||
}
|
||||
|
||||
// Note that we've found an expected type that works.
|
||||
foundWorkingExpectedType = true;
|
||||
|
||||
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
|
||||
},
|
||||
/* sortSubtypes */ true
|
||||
);
|
||||
@ -704,7 +710,7 @@ function validateFallbackConstructorCall(
|
||||
}
|
||||
|
||||
if (expectedType) {
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluator,
|
||||
ClassType.cloneAsInstance(type),
|
||||
expectedType,
|
||||
@ -818,6 +824,7 @@ function applyExpectedTypeForConstructor(
|
||||
|
||||
const specializedType = applySolvedTypeVars(type, typeVarContext, {
|
||||
unknownIfNotFound: unsolvedTypeVarsAreUnknown,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
return ClassType.cloneAsInstance(specializedType);
|
||||
}
|
||||
@ -1086,10 +1093,43 @@ function createFunctionFromInitMethod(
|
||||
}
|
||||
|
||||
const convertedInit = FunctionType.clone(boundInit);
|
||||
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? selfType ?? objectType;
|
||||
let returnType = selfType;
|
||||
if (!returnType) {
|
||||
returnType = objectType;
|
||||
|
||||
// If this is a generic type, self-specialize the class (i.e. fill in
|
||||
// its own type parameters as type arguments).
|
||||
if (objectType.details.typeParameters.length > 0 && !objectType.typeArguments) {
|
||||
const typeVarContext = new TypeVarContext(getTypeVarScopeIds(objectType));
|
||||
|
||||
// If a TypeVar is not used in any of the parameter types, it should take
|
||||
// on its default value (typically Unknown) in the resulting specialized type.
|
||||
const typeVarsInParams: TypeVarType[] = [];
|
||||
|
||||
convertedInit.details.parameters.forEach((param, index) => {
|
||||
const paramType = FunctionType.getEffectiveParameterType(convertedInit, index);
|
||||
addTypeVarsToListIfUnique(typeVarsInParams, getTypeVarArgumentsRecursive(paramType));
|
||||
});
|
||||
|
||||
typeVarsInParams.forEach((typeVar) => {
|
||||
if (isParamSpec(typeVar)) {
|
||||
typeVarContext.setTypeVarType(typeVar, convertTypeToParamSpecValue(typeVar));
|
||||
} else {
|
||||
typeVarContext.setTypeVarType(typeVar, typeVar);
|
||||
}
|
||||
});
|
||||
|
||||
returnType = applySolvedTypeVars(objectType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
}
|
||||
}
|
||||
|
||||
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? returnType;
|
||||
|
||||
if (convertedInit.specializedTypes) {
|
||||
convertedInit.specializedTypes.returnType = selfType ?? objectType;
|
||||
convertedInit.specializedTypes.returnType = returnType;
|
||||
}
|
||||
|
||||
if (!convertedInit.details.docString && classType.details.docString) {
|
||||
|
@ -821,7 +821,10 @@ function getConverterInputType(
|
||||
const inputTypeVarContext = new TypeVarContext(typeVar.scopeId);
|
||||
|
||||
if (evaluator.assignType(targetFunction, signature, diagAddendum, inputTypeVarContext)) {
|
||||
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, { unknownIfNotFound: true });
|
||||
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
});
|
||||
acceptedTypes.push(overloadSolution);
|
||||
}
|
||||
});
|
||||
|
@ -109,7 +109,8 @@ export class ImportResolver {
|
||||
private _cachedFilesForPath = new Map<string, Uri[]>();
|
||||
private _cachedDirExistenceForRoot = new Map<string, boolean>();
|
||||
private _stdlibModules: Set<string> | undefined;
|
||||
protected cachedParentImportResults: ParentDirectoryCache;
|
||||
|
||||
protected readonly cachedParentImportResults: ParentDirectoryCache;
|
||||
|
||||
constructor(readonly serviceProvider: ServiceProvider, private _configOptions: ConfigOptions, readonly host: Host) {
|
||||
this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([]));
|
||||
@ -172,7 +173,7 @@ export class ImportResolver {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root);
|
||||
const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
|
||||
const origin = sourceFileUri.getDirectory();
|
||||
|
||||
let current: Uri | undefined = origin;
|
||||
@ -533,7 +534,7 @@ export class ImportResolver {
|
||||
execEnv: ExecutionEnvironment,
|
||||
moduleDescriptor: ImportedModuleDescriptor
|
||||
): ImportResult {
|
||||
const importName = this.formatImportName(moduleDescriptor);
|
||||
const importName = formatImportName(moduleDescriptor);
|
||||
const importFailureInfo: string[] = [];
|
||||
const importResult = this._resolveImportStrict(
|
||||
importName,
|
||||
@ -559,7 +560,7 @@ export class ImportResolver {
|
||||
}
|
||||
|
||||
// Check whether the given file is in the parent directory import resolution cache.
|
||||
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root);
|
||||
const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
|
||||
if (!this.cachedParentImportResults.checkValidPath(this.fileSystem, sourceFileUri, root)) {
|
||||
return importResult;
|
||||
}
|
||||
@ -776,74 +777,12 @@ export class ImportResolver {
|
||||
|
||||
protected getNativeModuleName(uri: Uri): string | undefined {
|
||||
const fileExtension = uri.lastExtension.toLowerCase();
|
||||
if (this._isNativeModuleFileExtension(fileExtension)) {
|
||||
if (_isNativeModuleFileExtension(fileExtension)) {
|
||||
return stripFileExtension(uri.fileName, /* multiDotExtension */ true);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected getModuleNameFromPath(
|
||||
containerPath: Uri,
|
||||
fileUri: Uri,
|
||||
stripTopContainerDir = false
|
||||
): string | undefined {
|
||||
const moduleNameInfo = this.getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
|
||||
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return moduleNameInfo.moduleName;
|
||||
}
|
||||
|
||||
protected getModuleNameInfoFromPath(
|
||||
containerPath: Uri,
|
||||
fileUri: Uri,
|
||||
stripTopContainerDir = false
|
||||
): ModuleNameInfoFromPath | undefined {
|
||||
let fileUriWithoutExtension = fileUri.stripExtension();
|
||||
|
||||
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
|
||||
if (this._isNativeModuleFileExtension(fileUri.lastExtension)) {
|
||||
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
|
||||
}
|
||||
|
||||
if (!fileUriWithoutExtension.startsWith(containerPath)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Strip off the '/__init__' if it's present.
|
||||
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
|
||||
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
|
||||
}
|
||||
|
||||
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
|
||||
if (stripTopContainerDir) {
|
||||
if (parts.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
parts.shift();
|
||||
}
|
||||
|
||||
if (parts.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Handle the case where the symbol was resolved to a stubs package
|
||||
// rather than the real package. We'll strip off the "-stubs" suffix
|
||||
// in this case.
|
||||
if (parts[0].endsWith(stubsSuffix)) {
|
||||
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
|
||||
}
|
||||
|
||||
// Check whether parts contains invalid characters.
|
||||
const containsInvalidCharacters = parts.some((p) => !this._isIdentifier(p));
|
||||
|
||||
return {
|
||||
moduleName: parts.join('.'),
|
||||
containsInvalidCharacters,
|
||||
};
|
||||
}
|
||||
|
||||
// Potentially modifies the ImportResult by removing some or all of the
|
||||
// implicit import entries. Only the imported symbols should be included.
|
||||
protected filterImplicitImports(
|
||||
@ -880,22 +819,6 @@ export class ImportResolver {
|
||||
return newImportResult;
|
||||
}
|
||||
|
||||
protected formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
|
||||
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
|
||||
}
|
||||
|
||||
protected getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
|
||||
if (!this._isDefaultWorkspace(executionRoot)) {
|
||||
return executionRoot!;
|
||||
}
|
||||
|
||||
return sourceFileUri.getDirectory();
|
||||
}
|
||||
|
||||
private _isDefaultWorkspace(uri: Uri | undefined) {
|
||||
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
|
||||
}
|
||||
|
||||
private _resolveImportStrict(
|
||||
importName: string,
|
||||
sourceFileUri: Uri,
|
||||
@ -1119,7 +1042,7 @@ export class ImportResolver {
|
||||
);
|
||||
|
||||
if (stdLibTypeshedPath) {
|
||||
moduleName = this.getModuleNameFromPath(stdLibTypeshedPath, fileUri);
|
||||
moduleName = getModuleNameFromPath(stdLibTypeshedPath, fileUri);
|
||||
if (moduleName) {
|
||||
const moduleDescriptor: ImportedModuleDescriptor = {
|
||||
leadingDots: 0,
|
||||
@ -1149,7 +1072,7 @@ export class ImportResolver {
|
||||
|
||||
// Look for it in the root directory of the execution environment.
|
||||
if (execEnv.root) {
|
||||
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(execEnv.root, fileUri);
|
||||
const candidateModuleNameInfo = _getModuleNameInfoFromPath(execEnv.root, fileUri);
|
||||
|
||||
if (candidateModuleNameInfo) {
|
||||
if (candidateModuleNameInfo.containsInvalidCharacters) {
|
||||
@ -1163,7 +1086,7 @@ export class ImportResolver {
|
||||
}
|
||||
|
||||
for (const extraPath of execEnv.extraPaths) {
|
||||
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(extraPath, fileUri);
|
||||
const candidateModuleNameInfo = _getModuleNameInfoFromPath(extraPath, fileUri);
|
||||
|
||||
if (candidateModuleNameInfo) {
|
||||
if (candidateModuleNameInfo.containsInvalidCharacters) {
|
||||
@ -1182,7 +1105,7 @@ export class ImportResolver {
|
||||
|
||||
// Check for a typings file.
|
||||
if (this._configOptions.stubPath) {
|
||||
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri);
|
||||
const candidateModuleNameInfo = _getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri);
|
||||
|
||||
if (candidateModuleNameInfo) {
|
||||
if (candidateModuleNameInfo.containsInvalidCharacters) {
|
||||
@ -1209,7 +1132,7 @@ export class ImportResolver {
|
||||
);
|
||||
|
||||
if (thirdPartyTypeshedPath) {
|
||||
const candidateModuleName = this.getModuleNameFromPath(
|
||||
const candidateModuleName = getModuleNameFromPath(
|
||||
thirdPartyTypeshedPath,
|
||||
fileUri,
|
||||
/* stripTopContainerDir */ true
|
||||
@ -1226,7 +1149,7 @@ export class ImportResolver {
|
||||
|
||||
const thirdPartyTypeshedPathEx = this.getTypeshedPathEx(execEnv, importFailureInfo);
|
||||
if (thirdPartyTypeshedPathEx) {
|
||||
const candidateModuleName = this.getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri);
|
||||
const candidateModuleName = getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri);
|
||||
|
||||
// Does this candidate look better than the previous best module name?
|
||||
// We'll always try to use the shortest version.
|
||||
@ -1241,7 +1164,7 @@ export class ImportResolver {
|
||||
const pythonSearchPaths = this.getPythonSearchPaths(importFailureInfo);
|
||||
|
||||
for (const searchPath of pythonSearchPaths) {
|
||||
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(searchPath, fileUri);
|
||||
const candidateModuleNameInfo = _getModuleNameInfoFromPath(searchPath, fileUri);
|
||||
|
||||
if (candidateModuleNameInfo) {
|
||||
if (candidateModuleNameInfo.containsInvalidCharacters) {
|
||||
@ -1260,7 +1183,7 @@ export class ImportResolver {
|
||||
}
|
||||
|
||||
if (detectPyTyped && importType === ImportType.ThirdParty) {
|
||||
const root = this.getParentImportResolutionRoot(fileUri, execEnv.root);
|
||||
const root = getParentImportResolutionRoot(fileUri, execEnv.root);
|
||||
|
||||
// Go up directories one by one looking for a py.typed file.
|
||||
let current: Uri | undefined = fileUri.getDirectory();
|
||||
@ -1552,7 +1475,7 @@ export class ImportResolver {
|
||||
moduleDescriptor: ImportedModuleDescriptor,
|
||||
allowPyi: boolean
|
||||
): ImportResult | undefined {
|
||||
const importName = this.formatImportName(moduleDescriptor);
|
||||
const importName = formatImportName(moduleDescriptor);
|
||||
const importFailureInfo: string[] = [];
|
||||
|
||||
// Check for a local stub file using stubPath.
|
||||
@ -1828,16 +1751,6 @@ export class ImportResolver {
|
||||
return bestImportSoFar;
|
||||
}
|
||||
|
||||
private _isIdentifier(value: string) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private _findTypeshedPath(
|
||||
execEnv: ExecutionEnvironment,
|
||||
moduleDescriptor: ImportedModuleDescriptor,
|
||||
@ -2588,7 +2501,7 @@ export class ImportResolver {
|
||||
// Make sure we don't use parent folder resolution when checking whether the given name is resolvable.
|
||||
let importResult: ImportResult | undefined;
|
||||
if (strictOnly) {
|
||||
const importName = this.formatImportName(moduleDescriptor);
|
||||
const importName = formatImportName(moduleDescriptor);
|
||||
const importFailureInfo: string[] = [];
|
||||
|
||||
importResult = this._resolveImportStrict(
|
||||
@ -2653,7 +2566,7 @@ export class ImportResolver {
|
||||
if (fileExt === '.py' || fileExt === '.pyi') {
|
||||
strippedFileName = stripFileExtension(filePath.fileName);
|
||||
} else if (
|
||||
this._isNativeModuleFileExtension(fileExt) &&
|
||||
_isNativeModuleFileExtension(fileExt) &&
|
||||
!this.fileExistsCached(filePath.packageUri) &&
|
||||
!this.fileExistsCached(filePath.packageStubUri)
|
||||
) {
|
||||
@ -2770,15 +2683,10 @@ export class ImportResolver {
|
||||
const fileExtension = fileUri.lastExtension.toLowerCase();
|
||||
const withoutExtension = stripFileExtension(fileUri.fileName, /* multiDotExtension */ true);
|
||||
return (
|
||||
this._isNativeModuleFileExtension(fileExtension) &&
|
||||
equateStringsCaseInsensitive(moduleName, withoutExtension)
|
||||
_isNativeModuleFileExtension(fileExtension) && equateStringsCaseInsensitive(moduleName, withoutExtension)
|
||||
);
|
||||
}
|
||||
|
||||
private _isNativeModuleFileExtension(fileExtension: string): boolean {
|
||||
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
|
||||
}
|
||||
|
||||
private _tryWalkUp(current: Uri | undefined): Uri | undefined {
|
||||
if (!current || current.isEmpty() || current.isRoot()) {
|
||||
return undefined;
|
||||
@ -2796,7 +2704,7 @@ export class ImportResolver {
|
||||
return (
|
||||
current &&
|
||||
!current.isEmpty() &&
|
||||
(current.isChild(root) || (current.equals(root) && this._isDefaultWorkspace(execEnv.root)))
|
||||
(current.isChild(root) || (current.equals(root) && _isDefaultWorkspace(execEnv.root)))
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2806,3 +2714,95 @@ export type ImportResolverFactory = (
|
||||
options: ConfigOptions,
|
||||
host: Host
|
||||
) => ImportResolver;
|
||||
|
||||
export function formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
|
||||
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
|
||||
}
|
||||
|
||||
export function getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
|
||||
if (!_isDefaultWorkspace(executionRoot)) {
|
||||
return executionRoot!;
|
||||
}
|
||||
|
||||
return sourceFileUri.getDirectory();
|
||||
}
|
||||
|
||||
export function getModuleNameFromPath(
|
||||
containerPath: Uri,
|
||||
fileUri: Uri,
|
||||
stripTopContainerDir = false
|
||||
): string | undefined {
|
||||
const moduleNameInfo = _getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
|
||||
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return moduleNameInfo.moduleName;
|
||||
}
|
||||
|
||||
function _getModuleNameInfoFromPath(
|
||||
containerPath: Uri,
|
||||
fileUri: Uri,
|
||||
stripTopContainerDir = false
|
||||
): ModuleNameInfoFromPath | undefined {
|
||||
let fileUriWithoutExtension = fileUri.stripExtension();
|
||||
|
||||
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
|
||||
if (_isNativeModuleFileExtension(fileUri.lastExtension)) {
|
||||
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
|
||||
}
|
||||
|
||||
if (!fileUriWithoutExtension.startsWith(containerPath)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Strip off the '/__init__' if it's present.
|
||||
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
|
||||
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
|
||||
}
|
||||
|
||||
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
|
||||
if (stripTopContainerDir) {
|
||||
if (parts.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
parts.shift();
|
||||
}
|
||||
|
||||
if (parts.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Handle the case where the symbol was resolved to a stubs package
|
||||
// rather than the real package. We'll strip off the "-stubs" suffix
|
||||
// in this case.
|
||||
if (parts[0].endsWith(stubsSuffix)) {
|
||||
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
|
||||
}
|
||||
|
||||
// Check whether parts contains invalid characters.
|
||||
const containsInvalidCharacters = parts.some((p) => !_isIdentifier(p));
|
||||
|
||||
return {
|
||||
moduleName: parts.join('.'),
|
||||
containsInvalidCharacters,
|
||||
};
|
||||
}
|
||||
|
||||
function _isNativeModuleFileExtension(fileExtension: string): boolean {
|
||||
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
|
||||
}
|
||||
|
||||
function _isDefaultWorkspace(uri: Uri | undefined) {
|
||||
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
|
||||
}
|
||||
|
||||
function _isIdentifier(value: string) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -703,7 +703,7 @@ export function getTypeOfBinaryOperation(
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
// Exempt "|" because it might be a union operation involving unknowns.
|
||||
if (node.operator !== OperatorType.BitwiseOr) {
|
||||
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.binaryOperationNotAllowed(), node);
|
||||
@ -950,7 +950,7 @@ export function getTypeOfUnaryOperation(
|
||||
flags: EvaluatorFlags,
|
||||
inferenceContext: InferenceContext | undefined
|
||||
): TypeResult {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.unaryOperationNotAllowed(), node);
|
||||
return { type: UnknownType.create() };
|
||||
}
|
||||
@ -1087,7 +1087,7 @@ export function getTypeOfTernaryOperation(
|
||||
): TypeResult {
|
||||
const fileInfo = getFileInfo(node);
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.ternaryNotAllowed(), node);
|
||||
return { type: UnknownType.create() };
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
PatternValueNode,
|
||||
} from '../parser/parseNodes';
|
||||
import { CodeFlowReferenceExpressionNode } from './codeFlowTypes';
|
||||
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
|
||||
import { addConstraintsForExpectedType } from './constraintSolver';
|
||||
import { getTypeVarScopesForNode, isMatchingExpression } from './parseTreeUtils';
|
||||
import { EvaluatorFlags, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
|
||||
import {
|
||||
@ -685,7 +685,7 @@ function narrowTypeBasedOnClassPattern(
|
||||
// specialize it with Unknown type arguments.
|
||||
if (isClass(exprType) && !exprType.typeAliasInfo) {
|
||||
exprType = ClassType.cloneRemoveTypePromotions(exprType);
|
||||
exprType = specializeWithUnknownTypeArgs(exprType);
|
||||
exprType = specializeWithUnknownTypeArgs(exprType, evaluator.getTupleClassType());
|
||||
}
|
||||
|
||||
// Are there any positional arguments? If so, try to get the mappings for
|
||||
@ -921,7 +921,7 @@ function narrowTypeBasedOnClassPattern(
|
||||
|
||||
const matchTypeInstance = ClassType.cloneAsInstance(unspecializedMatchType);
|
||||
if (
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluator,
|
||||
matchTypeInstance,
|
||||
subjectSubtypeExpanded,
|
||||
@ -932,6 +932,7 @@ function narrowTypeBasedOnClassPattern(
|
||||
) {
|
||||
resultType = applySolvedTypeVars(matchTypeInstance, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
}
|
||||
}
|
||||
@ -1454,7 +1455,7 @@ function getSequencePatternInfo(
|
||||
if (sequenceType && isInstantiableClass(sequenceType)) {
|
||||
const sequenceTypeVarContext = new TypeVarContext(getTypeVarScopeId(sequenceType));
|
||||
if (
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluator,
|
||||
ClassType.cloneAsInstance(sequenceType),
|
||||
subtype,
|
||||
|
@ -102,7 +102,7 @@ export function assignClassToProtocol(
|
||||
// If the caller has provided a destination type var context,
|
||||
// we can't use the cached value unless the dest has no type
|
||||
// parameters to solve.
|
||||
if (!destTypeVarContext || destType.details.typeParameters.length === 0) {
|
||||
if (!destTypeVarContext || !requiresSpecialization(destType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -643,7 +643,7 @@ export class AnalyzerService {
|
||||
|
||||
const configs = this._getExtendedConfigurations(configFilePath ?? pyprojectFilePath);
|
||||
|
||||
if (configs) {
|
||||
if (configs && configs.length > 0) {
|
||||
for (const config of configs) {
|
||||
configOptions.initializeFromJson(
|
||||
config.configFileJsonObj,
|
||||
|
@ -97,7 +97,7 @@ import {
|
||||
isCodeFlowSupportedForReference,
|
||||
wildcardImportReferenceKey,
|
||||
} from './codeFlowTypes';
|
||||
import { assignTypeToTypeVar, populateTypeVarContextBasedOnExpectedType, updateTypeVarType } from './constraintSolver';
|
||||
import { addConstraintsForExpectedType, assignTypeToTypeVar, updateTypeVarType } from './constraintSolver';
|
||||
import {
|
||||
createFunctionFromConstructor,
|
||||
getBoundInitMethod,
|
||||
@ -1266,7 +1266,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
case ParseNodeType.AssignmentExpression: {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.walrusNotAllowed(), node);
|
||||
}
|
||||
|
||||
@ -1294,7 +1294,7 @@ export function createTypeEvaluator(
|
||||
typeResult = getTypeOfExpression(
|
||||
node.typeAnnotation,
|
||||
EvaluatorFlags.ExpectingInstantiableType |
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.DisallowParamSpec |
|
||||
EvaluatorFlags.DisallowTypeVarTuple |
|
||||
@ -1337,7 +1337,7 @@ export function createTypeEvaluator(
|
||||
|
||||
// If this is a PEP 695 type alias, remove the special form so the type
|
||||
// printer prints it as its aliased type rather than TypeAliasType.
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
if (typeResult.type.specialForm && ClassType.isBuiltIn(typeResult.type.specialForm, 'TypeAliasType')) {
|
||||
typeResult.type = TypeBase.cloneAsSpecialForm(typeResult.type, undefined);
|
||||
}
|
||||
@ -1404,7 +1404,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
function getTypeOfAwaitOperator(node: AwaitNode, flags: EvaluatorFlags, inferenceContext?: InferenceContext) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.awaitNotAllowed(), node);
|
||||
return { type: UnknownType.create() };
|
||||
}
|
||||
@ -1484,7 +1484,7 @@ export function createTypeEvaluator(
|
||||
ClassType.isBuiltIn(iterType, 'tuple')
|
||||
) {
|
||||
typeResult = { type: ClassType.cloneForUnpacked(iterType) };
|
||||
} else if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
} else if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.unpackInAnnotation(), node, node.starToken);
|
||||
typeResult = { type: UnknownType.create() };
|
||||
} else {
|
||||
@ -1726,7 +1726,7 @@ export function createTypeEvaluator(
|
||||
|
||||
let evaluatorFlags =
|
||||
EvaluatorFlags.ExpectingInstantiableType |
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.ConvertEllipsisToAny |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType;
|
||||
|
||||
@ -4411,7 +4411,7 @@ export function createTypeEvaluator(
|
||||
node,
|
||||
name,
|
||||
!allowForwardReferences,
|
||||
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0
|
||||
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
|
||||
);
|
||||
|
||||
if (!symbolWithScope) {
|
||||
@ -4424,7 +4424,7 @@ export function createTypeEvaluator(
|
||||
alias,
|
||||
alias.value,
|
||||
!allowForwardReferences,
|
||||
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0
|
||||
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -4517,7 +4517,7 @@ export function createTypeEvaluator(
|
||||
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
|
||||
targetSymbolId: symbol.id,
|
||||
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
|
||||
});
|
||||
|
||||
if (codeFlowTypeResult.type) {
|
||||
@ -4532,7 +4532,7 @@ export function createTypeEvaluator(
|
||||
// Detect, report, and fill in missing type arguments if appropriate.
|
||||
type = reportMissingTypeArguments(node, type, flags);
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
// Verify that the name does not refer to a (non type alias) variable.
|
||||
if (effectiveTypeInfo.includesVariableDecl && !type.typeAliasInfo) {
|
||||
let isAllowedTypeForVariable = isTypeVar(type) || isTypeAliasPlaceholder(type);
|
||||
@ -4593,7 +4593,7 @@ export function createTypeEvaluator(
|
||||
|
||||
type = convertTypeVarToRuntimeInstance(node, type, flags);
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
|
||||
reportUseOfTypeCheckOnly(type, node);
|
||||
}
|
||||
|
||||
@ -4926,7 +4926,10 @@ export function createTypeEvaluator(
|
||||
|
||||
let defaultType: Type;
|
||||
if (param.details.isDefaultExplicit || param.details.isParamSpec) {
|
||||
defaultType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
|
||||
defaultType = applySolvedTypeVars(param, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
} else if (param.details.isVariadic && tupleClass && isInstantiableClass(tupleClass)) {
|
||||
defaultType = makeTupleObject(
|
||||
[{ type: UnknownType.create(), isUnbounded: true }],
|
||||
@ -4951,7 +4954,10 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
type = TypeBase.cloneForTypeAlias(
|
||||
applySolvedTypeVars(type, typeVarContext, { unknownIfNotFound: true }),
|
||||
applySolvedTypeVars(type, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
}),
|
||||
type.typeAliasInfo.name,
|
||||
type.typeAliasInfo.fullName,
|
||||
type.typeAliasInfo.moduleName,
|
||||
@ -5088,7 +5094,7 @@ export function createTypeEvaluator(
|
||||
let leftExprFlags = EvaluatorFlags.MemberAccessBaseDefaults;
|
||||
leftExprFlags |=
|
||||
flags &
|
||||
(EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
(EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.VariableTypeAnnotation |
|
||||
EvaluatorFlags.AllowForwardReferences |
|
||||
EvaluatorFlags.NotParsedByInterpreter |
|
||||
@ -5155,7 +5161,7 @@ export function createTypeEvaluator(
|
||||
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
|
||||
targetSymbolId: indeterminateSymbolId,
|
||||
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
|
||||
});
|
||||
|
||||
if (codeFlowTypeResult.type) {
|
||||
@ -5288,7 +5294,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
// It's illegal to reference a member from a type variable.
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
if (!isIncomplete) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportGeneralTypeIssues,
|
||||
@ -5632,7 +5638,7 @@ export function createTypeEvaluator(
|
||||
type = isFunctionRule ? AnyType.create() : UnknownType.create();
|
||||
}
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
|
||||
reportUseOfTypeCheckOnly(type, node.memberName);
|
||||
}
|
||||
|
||||
@ -6515,7 +6521,7 @@ export function createTypeEvaluator(
|
||||
type: indexTypeResult.type,
|
||||
isIncomplete: !!baseTypeResult.isIncomplete || !!indexTypeResult.isIncomplete,
|
||||
},
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
|
||||
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
|
||||
});
|
||||
|
||||
if (codeFlowTypeResult.type) {
|
||||
@ -6855,7 +6861,10 @@ export function createTypeEvaluator(
|
||||
if (index < typeArgs.length) {
|
||||
typeArgType = convertToInstance(typeArgs[index].type);
|
||||
} else if (param.details.isDefaultExplicit) {
|
||||
typeArgType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
|
||||
typeArgType = applySolvedTypeVars(param, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
} else {
|
||||
typeArgType = UnknownType.create();
|
||||
}
|
||||
@ -7018,7 +7027,7 @@ export function createTypeEvaluator(
|
||||
getIndexAccessMagicMethodName(usage)
|
||||
);
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
// If the class doesn't derive from Generic, a type argument should not be allowed.
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportInvalidTypeArguments,
|
||||
@ -7059,7 +7068,7 @@ export function createTypeEvaluator(
|
||||
// Special-case InitVar, used in dataclasses.
|
||||
const typeArgs = getTypeArgs(node, flags);
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
if ((flags & EvaluatorFlags.VariableTypeAnnotation) === 0) {
|
||||
addError(LocMessage.initVarNotAllowed(), node.baseExpression);
|
||||
}
|
||||
@ -7743,7 +7752,7 @@ export function createTypeEvaluator(
|
||||
signatureTracker: UniqueSignatureTracker | undefined
|
||||
): TypeResult {
|
||||
if (
|
||||
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
|
||||
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
|
||||
node.parent?.nodeType !== ParseNodeType.Argument
|
||||
) {
|
||||
// This is allowed inside of an index trailer, specifically
|
||||
@ -7769,7 +7778,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
flags &= ~(
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.ExpectingInstantiableType
|
||||
);
|
||||
@ -7872,7 +7881,7 @@ export function createTypeEvaluator(
|
||||
} else {
|
||||
const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClass));
|
||||
if (
|
||||
!populateTypeVarContextBasedOnExpectedType(
|
||||
!addConstraintsForExpectedType(
|
||||
evaluatorInterface,
|
||||
ClassType.cloneAsInstance(tupleClass),
|
||||
inferenceContext.expectedType,
|
||||
@ -8001,7 +8010,7 @@ export function createTypeEvaluator(
|
||||
// allowed, and it's a common mistake, so we want to emit a diagnostic
|
||||
// that guides the user to the right solution.
|
||||
if (
|
||||
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
|
||||
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
|
||||
node.leftExpression.nodeType === ParseNodeType.Name &&
|
||||
node.leftExpression.value === 'type'
|
||||
) {
|
||||
@ -8129,7 +8138,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.typeAnnotationCall(), node);
|
||||
|
||||
typeResult = { type: UnknownType.create() };
|
||||
@ -11316,7 +11325,7 @@ export function createTypeEvaluator(
|
||||
if (isClassInstance(effectiveExpectedType) && !isTypeSame(effectiveReturnType, effectiveExpectedType)) {
|
||||
const tempTypeVarContext = new TypeVarContext(getTypeVarScopeId(effectiveReturnType));
|
||||
if (
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluatorInterface,
|
||||
effectiveReturnType,
|
||||
effectiveExpectedType,
|
||||
@ -11333,6 +11342,7 @@ export function createTypeEvaluator(
|
||||
|
||||
effectiveExpectedType = applySolvedTypeVars(genericReturnType, tempTypeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
|
||||
effectiveFlags |= AssignTypeFlags.SkipPopulateUnknownExpectedType;
|
||||
@ -11633,6 +11643,7 @@ export function createTypeEvaluator(
|
||||
|
||||
let specializedReturnType = applySolvedTypeVars(returnType, typeVarContext, {
|
||||
unknownIfNotFound,
|
||||
tupleClassType: getTupleClassType(),
|
||||
unknownExemptTypeVars: getUnknownExemptTypeVarsForReturnType(type, returnType),
|
||||
eliminateUnsolvedInUnions,
|
||||
applyInScopePlaceholders: true,
|
||||
@ -12067,7 +12078,7 @@ export function createTypeEvaluator(
|
||||
EvaluatorFlags.DisallowTypeVarTuple |
|
||||
EvaluatorFlags.DisallowFinal |
|
||||
EvaluatorFlags.DoNotSpecialize
|
||||
: EvaluatorFlags.DoNotSpecialize | EvaluatorFlags.DisallowFinal;
|
||||
: EvaluatorFlags.DisallowFinal | EvaluatorFlags.DoNotSpecialize;
|
||||
const exprTypeResult = getTypeOfExpression(
|
||||
argParam.argument.valueExpression,
|
||||
flags,
|
||||
@ -12516,6 +12527,7 @@ export function createTypeEvaluator(
|
||||
const concreteDefaultType = makeTopLevelTypeVarsConcrete(
|
||||
applySolvedTypeVars(typeVar.details.defaultType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
})
|
||||
);
|
||||
|
||||
@ -13006,14 +13018,12 @@ export function createTypeEvaluator(
|
||||
);
|
||||
}
|
||||
|
||||
let classFlags = baseClass.details.flags & ~(ClassTypeFlags.BuiltInClass | ClassTypeFlags.SpecialBuiltIn);
|
||||
classFlags |= ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass;
|
||||
const classType = ClassType.createInstantiable(
|
||||
className,
|
||||
ParseTreeUtils.getClassFullName(errorNode, fileInfo.moduleName, className),
|
||||
fileInfo.moduleName,
|
||||
fileInfo.fileUri,
|
||||
classFlags,
|
||||
ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass,
|
||||
ParseTreeUtils.getTypeSourceId(errorNode),
|
||||
/* declaredMetaclass */ undefined,
|
||||
baseClass.details.effectiveMetaclass
|
||||
@ -13255,7 +13265,7 @@ export function createTypeEvaluator(
|
||||
inferenceContext: InferenceContext | undefined
|
||||
): TypeResult {
|
||||
if (
|
||||
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
|
||||
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
|
||||
node.parent?.nodeType !== ParseNodeType.Argument
|
||||
) {
|
||||
const diag = new DiagnosticAddendum();
|
||||
@ -13397,7 +13407,7 @@ export function createTypeEvaluator(
|
||||
|
||||
const dictTypeVarContext = new TypeVarContext(getTypeVarScopeId(builtInDict));
|
||||
if (
|
||||
!populateTypeVarContextBasedOnExpectedType(
|
||||
!addConstraintsForExpectedType(
|
||||
evaluatorInterface,
|
||||
builtInDict,
|
||||
inferenceContext.expectedType,
|
||||
@ -13575,7 +13585,7 @@ export function createTypeEvaluator(
|
||||
const keyFlags =
|
||||
flags &
|
||||
~(
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.ExpectingInstantiableType
|
||||
);
|
||||
@ -13837,7 +13847,7 @@ export function createTypeEvaluator(
|
||||
inferenceContext: InferenceContext | undefined
|
||||
): TypeResult {
|
||||
if (
|
||||
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
|
||||
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
|
||||
node.nodeType === ParseNodeType.List &&
|
||||
node.parent?.nodeType !== ParseNodeType.Argument
|
||||
) {
|
||||
@ -13847,7 +13857,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
flags &= ~(
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.ExpectingInstantiableType
|
||||
);
|
||||
@ -14016,7 +14026,7 @@ export function createTypeEvaluator(
|
||||
|
||||
const typeVarContext = new TypeVarContext(getTypeVarScopeId(expectedClassType));
|
||||
if (
|
||||
!populateTypeVarContextBasedOnExpectedType(
|
||||
!addConstraintsForExpectedType(
|
||||
evaluatorInterface,
|
||||
ClassType.cloneAsInstance(expectedClassType),
|
||||
inferenceContext.expectedType,
|
||||
@ -14921,7 +14931,7 @@ export function createTypeEvaluator(
|
||||
// If no type arguments are provided, the resulting type
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.optionalExtraArgs(), errorNode);
|
||||
return UnknownType.create();
|
||||
}
|
||||
@ -15139,7 +15149,7 @@ export function createTypeEvaluator(
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if (!typeArgs) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.typeGuardArgCount(), errorNode);
|
||||
}
|
||||
|
||||
@ -15184,7 +15194,7 @@ export function createTypeEvaluator(
|
||||
|
||||
const enclosingClassTypeResult = enclosingClass ? getTypeOfClass(enclosingClass) : undefined;
|
||||
if (!enclosingClassTypeResult) {
|
||||
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingInstantiableType)) !== 0) {
|
||||
if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.ExpectingInstantiableType)) !== 0) {
|
||||
addDiagnostic(DiagnosticRule.reportGeneralTypeIssues, LocMessage.selfTypeContext(), errorNode);
|
||||
}
|
||||
|
||||
@ -15246,7 +15256,7 @@ export function createTypeEvaluator(
|
||||
// If no type arguments are provided, the resulting type
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
|
||||
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
|
||||
return { type: classType };
|
||||
}
|
||||
|
||||
@ -15330,7 +15340,7 @@ export function createTypeEvaluator(
|
||||
// If no type arguments are provided, the resulting type
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
|
||||
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
|
||||
return classType;
|
||||
}
|
||||
|
||||
@ -15654,7 +15664,7 @@ export function createTypeEvaluator(
|
||||
// If no type arguments are provided, the resulting type
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
|
||||
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
|
||||
addError(LocMessage.unionTypeArgCount(), errorNode);
|
||||
return NeverType.createNever();
|
||||
}
|
||||
@ -15741,7 +15751,7 @@ export function createTypeEvaluator(
|
||||
// If no type arguments are provided, the resulting type
|
||||
// depends on whether we're evaluating a type annotation or
|
||||
// we're in some other context.
|
||||
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.DisallowNakedGeneric)) !== 0) {
|
||||
if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.DisallowNakedGeneric)) !== 0) {
|
||||
addError(LocMessage.genericTypeArgMissing(), errorNode);
|
||||
}
|
||||
|
||||
@ -16113,19 +16123,8 @@ export function createTypeEvaluator(
|
||||
flags |= EvaluatorFlags.DoNotSpecialize;
|
||||
}
|
||||
|
||||
if (isDeclaredTypeAlias(node.leftExpression)) {
|
||||
flags |=
|
||||
EvaluatorFlags.ExpectingInstantiableType |
|
||||
EvaluatorFlags.ExpectingTypeAnnotation |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.DisallowParamSpec |
|
||||
EvaluatorFlags.DisallowTypeVarTuple |
|
||||
EvaluatorFlags.DisallowClassVar;
|
||||
flags &= ~EvaluatorFlags.DoNotSpecialize;
|
||||
}
|
||||
|
||||
// Is this type already cached?
|
||||
let rightHandType = readTypeCache(node.rightExpression, flags);
|
||||
let rightHandType = readTypeCache(node.rightExpression, /* flags */ undefined);
|
||||
let isIncomplete = false;
|
||||
let expectedTypeDiagAddendum: DiagnosticAddendum | undefined;
|
||||
|
||||
@ -16138,76 +16137,118 @@ export function createTypeEvaluator(
|
||||
writeTypeCache(node.rightExpression, { type: rightHandType }, EvaluatorFlags.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rightHandType) {
|
||||
// Determine whether there is a declared type.
|
||||
const declaredType = getDeclaredTypeForExpression(node.leftExpression, {
|
||||
method: 'set',
|
||||
});
|
||||
if (!rightHandType) {
|
||||
// Determine whether there is a declared type.
|
||||
const declaredType = getDeclaredTypeForExpression(node.leftExpression, { method: 'set' });
|
||||
|
||||
let typeAliasNameNode: NameNode | undefined;
|
||||
let isSpeculativeTypeAlias = false;
|
||||
let typeAliasNameNode: NameNode | undefined;
|
||||
let isSpeculativeTypeAlias = false;
|
||||
let typeAliasPlaceholder: TypeVarType | undefined;
|
||||
|
||||
if (isDeclaredTypeAlias(node.leftExpression)) {
|
||||
typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode;
|
||||
if (isDeclaredTypeAlias(node.leftExpression)) {
|
||||
flags =
|
||||
EvaluatorFlags.ExpectingInstantiableType |
|
||||
EvaluatorFlags.ExpectingTypeExpression |
|
||||
EvaluatorFlags.EvaluateStringLiteralAsType |
|
||||
EvaluatorFlags.DisallowParamSpec |
|
||||
EvaluatorFlags.DisallowTypeVarTuple |
|
||||
EvaluatorFlags.DisallowClassVar;
|
||||
|
||||
if (!isLegalTypeAliasExpressionForm(node.rightExpression)) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportInvalidTypeForm,
|
||||
LocMessage.typeAliasIllegalExpressionForm(),
|
||||
node.rightExpression
|
||||
);
|
||||
}
|
||||
} else if (node.leftExpression.nodeType === ParseNodeType.Name) {
|
||||
const symbolWithScope = lookUpSymbolRecursive(
|
||||
node.leftExpression,
|
||||
node.leftExpression.value,
|
||||
/* honorCodeFlow */ false
|
||||
typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode;
|
||||
|
||||
if (!isLegalTypeAliasExpressionForm(node.rightExpression)) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportInvalidTypeForm,
|
||||
LocMessage.typeAliasIllegalExpressionForm(),
|
||||
node.rightExpression
|
||||
);
|
||||
if (symbolWithScope) {
|
||||
const decls = symbolWithScope.symbol.getDeclarations();
|
||||
if (decls.length === 1 && isPossibleTypeAliasOrTypedDict(decls[0])) {
|
||||
}
|
||||
} else if (node.leftExpression.nodeType === ParseNodeType.Name) {
|
||||
const symbolWithScope = lookUpSymbolRecursive(
|
||||
node.leftExpression,
|
||||
node.leftExpression.value,
|
||||
/* honorCodeFlow */ false
|
||||
);
|
||||
|
||||
if (symbolWithScope) {
|
||||
const decls = symbolWithScope.symbol.getDeclarations();
|
||||
|
||||
if (decls.length === 1) {
|
||||
if (isPossibleTypeAliasDeclaration(decls[0])) {
|
||||
typeAliasNameNode = node.leftExpression;
|
||||
isSpeculativeTypeAlias = true;
|
||||
} else if (isPossibleTypeDictFactoryCall(decls[0])) {
|
||||
// Handle calls to TypedDict factory functions like type
|
||||
// aliases to support recursive field type definitions.
|
||||
typeAliasNameNode = node.leftExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Synthesize a type variable that represents the type alias while we're
|
||||
// evaluating it. This allows us to handle recursive definitions.
|
||||
let typeAliasTypeVar: TypeVarType | undefined;
|
||||
if (typeAliasNameNode) {
|
||||
typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${typeAliasNameNode.value}`);
|
||||
typeAliasTypeVar.details.isSynthesized = true;
|
||||
typeAliasTypeVar.details.recursiveTypeAliasName = typeAliasNameNode.value;
|
||||
const scopeId = ParseTreeUtils.getScopeIdForNode(typeAliasNameNode);
|
||||
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
|
||||
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = false;
|
||||
typeAliasTypeVar.scopeId = scopeId;
|
||||
if (typeAliasNameNode) {
|
||||
typeAliasPlaceholder = synthesizeTypeAliasPlaceholder(typeAliasNameNode);
|
||||
|
||||
// Write the type back to the type cache. It will be replaced below.
|
||||
writeTypeCache(node, { type: typeAliasTypeVar }, /* flags */ undefined);
|
||||
writeTypeCache(node.leftExpression, { type: typeAliasTypeVar }, /* flags */ undefined);
|
||||
if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) {
|
||||
writeTypeCache(
|
||||
node.leftExpression.valueExpression,
|
||||
{ type: typeAliasTypeVar },
|
||||
/* flags */ undefined
|
||||
);
|
||||
}
|
||||
writeTypeCache(node, { type: typeAliasPlaceholder }, /* flags */ undefined);
|
||||
writeTypeCache(node.leftExpression, { type: typeAliasPlaceholder }, /* flags */ undefined);
|
||||
|
||||
if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) {
|
||||
writeTypeCache(
|
||||
node.leftExpression.valueExpression,
|
||||
{ type: typeAliasPlaceholder },
|
||||
/* flags */ undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const srcTypeResult = getTypeOfExpression(
|
||||
node.rightExpression,
|
||||
flags,
|
||||
makeInferenceContext(declaredType)
|
||||
const srcTypeResult = getTypeOfExpression(node.rightExpression, flags, makeInferenceContext(declaredType));
|
||||
|
||||
rightHandType = srcTypeResult.type;
|
||||
expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum;
|
||||
if (srcTypeResult.isIncomplete) {
|
||||
isIncomplete = true;
|
||||
}
|
||||
|
||||
// If this was a speculative type alias, it becomes a real type alias
|
||||
// only if the evaluated type is an instantiable type.
|
||||
if (isSpeculativeTypeAlias && !isLegalImplicitTypeAliasType(rightHandType)) {
|
||||
typeAliasNameNode = undefined;
|
||||
}
|
||||
|
||||
if (typeAliasNameNode) {
|
||||
assert(typeAliasPlaceholder !== undefined);
|
||||
|
||||
// If this is a type alias, record its name based on the assignment target.
|
||||
rightHandType = transformTypeForTypeAlias(
|
||||
rightHandType,
|
||||
typeAliasNameNode,
|
||||
typeAliasNameNode,
|
||||
/* isPep695Syntax */ false,
|
||||
/* isPep695TypeVarType */ false
|
||||
);
|
||||
let srcType = srcTypeResult.type;
|
||||
expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum;
|
||||
if (srcTypeResult.isIncomplete) {
|
||||
isIncomplete = true;
|
||||
|
||||
if (isTypeAliasRecursive(typeAliasPlaceholder, rightHandType)) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportGeneralTypeIssues,
|
||||
LocMessage.typeAliasIsRecursiveDirect().format({
|
||||
name: typeAliasNameNode.value,
|
||||
}),
|
||||
node.rightExpression
|
||||
);
|
||||
|
||||
rightHandType = UnknownType.create();
|
||||
}
|
||||
|
||||
// Set the resulting type to the boundType of the original type alias
|
||||
// to support recursive type aliases.
|
||||
typeAliasPlaceholder.details.boundType = rightHandType;
|
||||
|
||||
// Record the type parameters within the recursive type alias so it
|
||||
// can be specialized.
|
||||
typeAliasPlaceholder.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
|
||||
} else {
|
||||
// If the RHS is a constant boolean expression, assign it a literal type.
|
||||
const constExprValue = evaluateStaticBoolExpression(
|
||||
node.rightExpression,
|
||||
@ -16218,46 +16259,7 @@ export function createTypeEvaluator(
|
||||
if (constExprValue !== undefined) {
|
||||
const boolType = getBuiltInObject(node, 'bool');
|
||||
if (isClassInstance(boolType)) {
|
||||
srcType = ClassType.cloneWithLiteral(boolType, constExprValue);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is an enum, transform the type as required.
|
||||
rightHandType = srcType;
|
||||
|
||||
if (typeAliasNameNode) {
|
||||
// If this was a speculative type alias, it becomes a real type alias
|
||||
// only if the evaluated type is an instantiable type.
|
||||
if (!isSpeculativeTypeAlias || isLegalImplicitTypeAliasType(rightHandType)) {
|
||||
// If this is a type alias, record its name based on the assignment target.
|
||||
rightHandType = transformTypeForTypeAlias(
|
||||
rightHandType,
|
||||
typeAliasNameNode,
|
||||
typeAliasNameNode,
|
||||
/* isPep695Syntax */ false,
|
||||
/* isPep695TypeVarType */ false
|
||||
);
|
||||
|
||||
assert(typeAliasTypeVar !== undefined);
|
||||
if (isTypeAliasRecursive(typeAliasTypeVar, rightHandType)) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportGeneralTypeIssues,
|
||||
LocMessage.typeAliasIsRecursiveDirect().format({
|
||||
name: typeAliasNameNode.value,
|
||||
}),
|
||||
node.rightExpression
|
||||
);
|
||||
|
||||
rightHandType = UnknownType.create();
|
||||
}
|
||||
|
||||
// Set the resulting type to the boundType of the original type alias
|
||||
// to support recursive type aliases.
|
||||
typeAliasTypeVar.details.boundType = rightHandType;
|
||||
|
||||
// Record the type parameters within the recursive type alias so it
|
||||
// can be specialized.
|
||||
typeAliasTypeVar.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
|
||||
rightHandType = ClassType.cloneWithLiteral(boolType, constExprValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16275,39 +16277,18 @@ export function createTypeEvaluator(
|
||||
writeTypeCache(node, { type: rightHandType, isIncomplete }, EvaluatorFlags.None);
|
||||
}
|
||||
|
||||
function isPossibleTypeAliasOrTypedDict(decl: Declaration) {
|
||||
if (isPossibleTypeAliasDeclaration(decl)) {
|
||||
return true;
|
||||
}
|
||||
// Synthesize a TypeVar that acts as a placeholder for a type alias. This allows
|
||||
// the type alias definition to refer to itself.
|
||||
function synthesizeTypeAliasPlaceholder(nameNode: NameNode): TypeVarType {
|
||||
const placeholder = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`);
|
||||
placeholder.details.isSynthesized = true;
|
||||
placeholder.details.recursiveTypeAliasName = nameNode.value;
|
||||
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
|
||||
placeholder.details.recursiveTypeAliasScopeId = scopeId;
|
||||
placeholder.details.recursiveTypeAliasIsPep695Syntax = false;
|
||||
placeholder.scopeId = scopeId;
|
||||
|
||||
if (
|
||||
decl.type === DeclarationType.Variable &&
|
||||
decl.node.parent &&
|
||||
decl.node.parent.nodeType === ParseNodeType.Assignment &&
|
||||
decl.node.parent.rightExpression?.nodeType === ParseNodeType.Call
|
||||
) {
|
||||
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
|
||||
|
||||
// Use a simple heuristic to determine whether this is potentially
|
||||
// a call to the TypedDict call. This avoids the expensive (and potentially
|
||||
// recursive) call to getTypeOfExpression in cases where it's not needed.
|
||||
if (
|
||||
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
|
||||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
|
||||
callLeftNode.memberName.value === 'TypedDict' &&
|
||||
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
|
||||
) {
|
||||
// See if this is a call to TypedDict. We want to support
|
||||
// recursive type references in a TypedDict call.
|
||||
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
|
||||
|
||||
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
// Evaluates the type of a type alias (i.e. "type") statement. This code
|
||||
@ -16346,15 +16327,9 @@ export function createTypeEvaluator(
|
||||
|
||||
// Synthesize a type variable that represents the type alias while we're
|
||||
// evaluating it. This allows us to handle recursive definitions.
|
||||
const typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`);
|
||||
typeAliasTypeVar.details.isSynthesized = true;
|
||||
typeAliasTypeVar.details.recursiveTypeAliasName = nameNode.value;
|
||||
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
|
||||
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
|
||||
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = isPep695Syntax;
|
||||
typeAliasTypeVar.scopeId = scopeId;
|
||||
const typeAliasTypeVar = synthesizeTypeAliasPlaceholder(nameNode);
|
||||
|
||||
// Write the type to the type cache. It will be replaced below.
|
||||
// Write the type to the type cache to support recursive type alias definitions.
|
||||
writeTypeCache(nameNode, { type: typeAliasTypeVar }, /* flags */ undefined);
|
||||
|
||||
// Set a partial type to handle recursive (self-referential) type aliases.
|
||||
@ -18340,6 +18315,7 @@ export function createTypeEvaluator(
|
||||
// Replace any unsolved TypeVars with Unknown (including all function-scoped TypeVars).
|
||||
inferredParamType = applySolvedTypeVars(inferredParamType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -18764,6 +18740,11 @@ export function createTypeEvaluator(
|
||||
return false;
|
||||
}
|
||||
|
||||
const statements = functionDecl.node.suite.statements;
|
||||
if (statements.some((statement) => statement.nodeType !== ParseNodeType.StatementList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const raiseStatement of functionDecl.raiseStatements) {
|
||||
if (!raiseStatement.typeExpression || raiseStatement.valueExpression) {
|
||||
return false;
|
||||
@ -19494,6 +19475,16 @@ export function createTypeEvaluator(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Forward-declared type annotation expressions need to be be evaluated
|
||||
// in context so they have the appropriate flags set. Most of these cases
|
||||
// will have been detected above when calling getParentAnnotationNode,
|
||||
// but TypeAlias expressions are not handled there.
|
||||
const stringEnclosure = ParseTreeUtils.getParentNodeOfType(parent, ParseNodeType.StringList);
|
||||
if (stringEnclosure) {
|
||||
nodeToEvaluate = stringEnclosure as StringListNode;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The left expression of a call or member access expression is not generally contextual.
|
||||
if (parent.nodeType === ParseNodeType.Call || parent.nodeType === ParseNodeType.MemberAccess) {
|
||||
if (nodeToEvaluate === parent.leftExpression) {
|
||||
@ -19520,15 +19511,7 @@ export function createTypeEvaluator(
|
||||
// The base expression of an index expression is not contextual.
|
||||
if (nodeToEvaluate === parent.baseExpression) {
|
||||
flags = EvaluatorFlags.IndexBaseDefaults;
|
||||
break;
|
||||
}
|
||||
} else if (parent.nodeType === ParseNodeType.StringList && nodeToEvaluate === parent.typeAnnotation) {
|
||||
// Forward-declared type annotation expressions need to be be evaluated
|
||||
// in context so they have the appropriate flags set. Most of these cases
|
||||
// will have been detected above when calling getParentAnnotationNode,
|
||||
// but TypeAlias expressions are not handled there.
|
||||
nodeToEvaluate = parent;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isExpressionNode(parent)) {
|
||||
@ -19873,7 +19856,19 @@ export function createTypeEvaluator(
|
||||
// don't bother doing additional work.
|
||||
let cacheEntry = readTypeCacheEntry(subnode);
|
||||
if (cacheEntry && !cacheEntry.typeResult.isIncomplete) {
|
||||
return cacheEntry.typeResult;
|
||||
const typeResult = cacheEntry.typeResult;
|
||||
|
||||
// Handle the special case where a function or class is partially evaluated.
|
||||
// Indicate that these are not complete types.
|
||||
if (isFunction(typeResult.type) && FunctionType.isPartiallyEvaluated(typeResult.type)) {
|
||||
return { ...typeResult, isIncomplete: true };
|
||||
}
|
||||
|
||||
if (isClass(typeResult.type) && ClassType.isPartiallyEvaluated(typeResult.type)) {
|
||||
return { ...typeResult, isIncomplete: true };
|
||||
}
|
||||
|
||||
return typeResult;
|
||||
}
|
||||
|
||||
callback();
|
||||
@ -20024,7 +20019,7 @@ export function createTypeEvaluator(
|
||||
case 'Protocol': {
|
||||
if (
|
||||
(flags &
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
|
||||
0
|
||||
) {
|
||||
addError(LocMessage.protocolNotAllowed(), errorNode);
|
||||
@ -20049,7 +20044,7 @@ export function createTypeEvaluator(
|
||||
case 'TypedDict': {
|
||||
if (
|
||||
(flags &
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
|
||||
0
|
||||
) {
|
||||
addError(LocMessage.typedDictNotAllowed(), errorNode);
|
||||
@ -20060,7 +20055,7 @@ export function createTypeEvaluator(
|
||||
case 'Literal': {
|
||||
if (
|
||||
(flags &
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
|
||||
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
|
||||
0
|
||||
) {
|
||||
addError(LocMessage.literalNotAllowed(), errorNode);
|
||||
@ -20375,7 +20370,10 @@ export function createTypeEvaluator(
|
||||
return;
|
||||
}
|
||||
|
||||
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, { unknownIfNotFound: true });
|
||||
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
typeArgTypes.push(solvedDefaultType);
|
||||
if (isParamSpec(typeParam)) {
|
||||
typeVarContext.setTypeVarType(typeParam, convertTypeToParamSpecValue(solvedDefaultType));
|
||||
@ -20510,7 +20508,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
if (options?.allowRequired) {
|
||||
flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeAnnotation;
|
||||
flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeExpression;
|
||||
}
|
||||
|
||||
if (options?.allowUnpackedTuple) {
|
||||
@ -20524,7 +20522,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
if (options?.enforceTypeAnnotationRules) {
|
||||
flags |= EvaluatorFlags.ExpectingTypeAnnotation;
|
||||
flags |= EvaluatorFlags.ExpectingTypeExpression;
|
||||
}
|
||||
|
||||
if (options?.disallowProtocolAndTypedDict) {
|
||||
@ -22347,7 +22345,7 @@ export function createTypeEvaluator(
|
||||
getEffectiveTypeOfSymbol(member.symbol),
|
||||
member.classType,
|
||||
/* selfClass */ undefined,
|
||||
typeClass ?? UnknownType.create()
|
||||
typeClass && isInstantiableClass(typeClass) ? typeClass : undefined
|
||||
);
|
||||
}
|
||||
return UnknownType.create();
|
||||
@ -25944,7 +25942,7 @@ export function createTypeEvaluator(
|
||||
!assignedType.tupleTypeArguments
|
||||
) {
|
||||
const typeVarContext = new TypeVarContext(getTypeVarScopeId(assignedType));
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluatorInterface,
|
||||
ClassType.cloneForSpecialization(
|
||||
assignedType,
|
||||
@ -27118,6 +27116,43 @@ export function createTypeEvaluator(
|
||||
return isLegal;
|
||||
}
|
||||
|
||||
function isPossibleTypeAliasOrTypedDict(decl: Declaration) {
|
||||
return isPossibleTypeAliasDeclaration(decl) || isPossibleTypeDictFactoryCall(decl);
|
||||
}
|
||||
|
||||
function isPossibleTypeDictFactoryCall(decl: Declaration) {
|
||||
if (
|
||||
decl.type !== DeclarationType.Variable ||
|
||||
!decl.node.parent ||
|
||||
decl.node.parent.nodeType !== ParseNodeType.Assignment ||
|
||||
decl.node.parent.rightExpression?.nodeType !== ParseNodeType.Call
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
|
||||
|
||||
// Use a simple heuristic to determine whether this is potentially
|
||||
// a call to the TypedDict call. This avoids the expensive (and potentially
|
||||
// recursive) call to getTypeOfExpression in cases where it's not needed.
|
||||
if (
|
||||
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
|
||||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
|
||||
callLeftNode.memberName.value === 'TypedDict' &&
|
||||
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
|
||||
) {
|
||||
// See if this is a call to TypedDict. We want to support
|
||||
// recursive type references in a TypedDict call.
|
||||
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
|
||||
|
||||
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function printObjectTypeForClass(type: ClassType): string {
|
||||
return TypePrinter.printObjectTypeForClass(
|
||||
type,
|
||||
|
@ -86,10 +86,9 @@ export const enum EvaluatorFlags {
|
||||
// than an instance (object)
|
||||
ExpectingInstantiableType = 1 << 7,
|
||||
|
||||
// A type annotation restricts the types of expressions that are
|
||||
// allowed. If this flag is set, illegal type expressions are
|
||||
// flagged as errors.
|
||||
ExpectingTypeAnnotation = 1 << 8,
|
||||
// A type expression imposes grammatical and semantic limits on an
|
||||
// expression. If this flag is set, illegal type expressions are
|
||||
ExpectingTypeExpression = 1 << 8,
|
||||
|
||||
// Suppress the reportMissingTypeArgument diagnostic in this context.
|
||||
AllowMissingTypeArgs = 1 << 9,
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from '../parser/parseNodes';
|
||||
import { KeywordType, OperatorType } from '../parser/tokenizerTypes';
|
||||
import { getFileInfo } from './analyzerNodeInfo';
|
||||
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
|
||||
import { addConstraintsForExpectedType } from './constraintSolver';
|
||||
import { Declaration, DeclarationType } from './declaration';
|
||||
import { transformTypeForEnumMember } from './enums';
|
||||
import * as ParseTreeUtils from './parseTreeUtils';
|
||||
@ -638,7 +638,7 @@ export function getTypeNarrowingCallback(
|
||||
);
|
||||
const arg1Type = arg1TypeResult.type;
|
||||
|
||||
const classTypeList = getIsInstanceClassTypes(arg1Type);
|
||||
const classTypeList = getIsInstanceClassTypes(evaluator, arg1Type);
|
||||
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
|
||||
|
||||
if (classTypeList) {
|
||||
@ -1146,7 +1146,10 @@ function narrowTypeForIsEllipsis(evaluator: TypeEvaluator, type: Type, isPositiv
|
||||
// that accepts a single class, and a more complex form that accepts a tuple
|
||||
// of classes (including arbitrarily-nested tuples). This method determines
|
||||
// which form and returns a list of classes or undefined.
|
||||
function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | FunctionType)[] | undefined {
|
||||
function getIsInstanceClassTypes(
|
||||
evaluator: TypeEvaluator,
|
||||
argType: Type
|
||||
): (ClassType | TypeVarType | FunctionType)[] | undefined {
|
||||
let foundNonClassType = false;
|
||||
const classTypeList: (ClassType | TypeVarType | FunctionType)[] = [];
|
||||
|
||||
@ -1155,7 +1158,7 @@ function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | Func
|
||||
const addClassTypesToList = (types: Type[]) => {
|
||||
types.forEach((subtype) => {
|
||||
if (isClass(subtype)) {
|
||||
subtype = specializeWithUnknownTypeArgs(subtype);
|
||||
subtype = specializeWithUnknownTypeArgs(subtype, evaluator.getTupleClassType());
|
||||
|
||||
if (isInstantiableClass(subtype) && ClassType.isBuiltIn(subtype, 'Callable')) {
|
||||
subtype = convertToInstantiable(getUnknownTypeForCallable());
|
||||
@ -1359,7 +1362,8 @@ function narrowTypeForIsInstanceInternal(
|
||||
concreteFilterType,
|
||||
/* typeArguments */ undefined,
|
||||
/* isTypeArgumentExplicit */ false
|
||||
)
|
||||
),
|
||||
evaluator.getTupleClassType()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1451,7 +1455,7 @@ function narrowTypeForIsInstanceInternal(
|
||||
);
|
||||
|
||||
if (
|
||||
populateTypeVarContextBasedOnExpectedType(
|
||||
addConstraintsForExpectedType(
|
||||
evaluator,
|
||||
unspecializedFilterType,
|
||||
concreteVarType,
|
||||
@ -1463,7 +1467,11 @@ function narrowTypeForIsInstanceInternal(
|
||||
specializedFilterType = applySolvedTypeVars(
|
||||
unspecializedFilterType,
|
||||
typeVarContext,
|
||||
{ unknownIfNotFound: true, useUnknownOverDefault: true }
|
||||
{
|
||||
unknownIfNotFound: true,
|
||||
useUnknownOverDefault: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}
|
||||
) as ClassType;
|
||||
}
|
||||
}
|
||||
@ -1764,7 +1772,11 @@ function narrowTypeForIsInstanceInternal(
|
||||
|
||||
const filteredType = evaluator.mapSubtypesExpandTypeVars(
|
||||
expandedTypes,
|
||||
/* options */ undefined,
|
||||
{
|
||||
expandCallback: (type) => {
|
||||
return evaluator.expandPromotionTypes(errorNode, type);
|
||||
},
|
||||
},
|
||||
(subtype, unexpandedSubtype) => {
|
||||
// If we fail to filter anything in the negative case, we need to decide
|
||||
// whether to retain the original TypeVar or replace it with its specialized
|
||||
@ -2459,33 +2471,69 @@ function narrowTypeForClassComparison(
|
||||
isPositiveTest: boolean
|
||||
): Type {
|
||||
return mapSubtypes(referenceType, (subtype) => {
|
||||
const concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
|
||||
let concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
|
||||
|
||||
if (isPositiveTest) {
|
||||
if (isNoneInstance(concreteSubtype)) {
|
||||
return undefined;
|
||||
return isNoneTypeClass(classType) ? classType : undefined;
|
||||
}
|
||||
|
||||
if (isClassInstance(concreteSubtype) && TypeBase.isInstance(subtype)) {
|
||||
if (ClassType.isBuiltIn(concreteSubtype, 'type')) {
|
||||
return classType;
|
||||
if (
|
||||
isClassInstance(concreteSubtype) &&
|
||||
TypeBase.isInstance(subtype) &&
|
||||
ClassType.isBuiltIn(concreteSubtype, 'type')
|
||||
) {
|
||||
concreteSubtype =
|
||||
concreteSubtype.typeArguments && concreteSubtype.typeArguments.length > 0
|
||||
? convertToInstantiable(concreteSubtype.typeArguments[0])
|
||||
: UnknownType.create();
|
||||
}
|
||||
|
||||
if (isAnyOrUnknown(concreteSubtype)) {
|
||||
return classType;
|
||||
}
|
||||
|
||||
if (isClass(concreteSubtype)) {
|
||||
if (TypeBase.isInstance(concreteSubtype)) {
|
||||
return ClassType.isBuiltIn(concreteSubtype, 'object') ? classType : undefined;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
const isSuperType = isIsinstanceFilterSuperclass(
|
||||
evaluator,
|
||||
subtype,
|
||||
concreteSubtype,
|
||||
classType,
|
||||
classType,
|
||||
/* isInstanceCheck */ false
|
||||
);
|
||||
|
||||
if (isInstantiableClass(concreteSubtype) && ClassType.isFinal(concreteSubtype)) {
|
||||
if (
|
||||
!ClassType.isSameGenericClass(concreteSubtype, classType) &&
|
||||
!isIsinstanceFilterSuperclass(
|
||||
if (!classType.includeSubclasses) {
|
||||
// Handle the case where the LHS and RHS operands are specific
|
||||
// classes, as opposed to types that represent classes and their
|
||||
// subclasses.
|
||||
if (!concreteSubtype.includeSubclasses) {
|
||||
return ClassType.isSameGenericClass(concreteSubtype, classType) ? classType : undefined;
|
||||
}
|
||||
|
||||
const isSubType = isIsinstanceFilterSubclass(
|
||||
evaluator,
|
||||
subtype,
|
||||
concreteSubtype,
|
||||
classType,
|
||||
classType,
|
||||
/* isInstanceCheck */ false
|
||||
)
|
||||
) {
|
||||
);
|
||||
|
||||
if (isSuperType) {
|
||||
return classType;
|
||||
}
|
||||
|
||||
if (isSubType) {
|
||||
return addConditionToType(classType, getTypeCondition(concreteSubtype));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (ClassType.isFinal(concreteSubtype) && !isSuperType) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -245,12 +245,13 @@ export const enum AssignTypeFlags {
|
||||
}
|
||||
|
||||
export interface ApplyTypeVarOptions {
|
||||
typeClassType?: ClassType;
|
||||
tupleClassType?: ClassType;
|
||||
unknownIfNotFound?: boolean;
|
||||
useUnknownOverDefault?: boolean;
|
||||
unknownExemptTypeVars?: TypeVarType[];
|
||||
useNarrowBoundOnly?: boolean;
|
||||
eliminateUnsolvedInUnions?: boolean;
|
||||
typeClassType?: Type;
|
||||
applyInScopePlaceholders?: boolean;
|
||||
}
|
||||
|
||||
@ -1073,7 +1074,7 @@ export function specializeWithDefaultTypeArgs(type: ClassType): ClassType {
|
||||
|
||||
// Specializes the class with "Unknown" type args (or the equivalent for ParamSpecs
|
||||
// or TypeVarTuples).
|
||||
export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
|
||||
export function specializeWithUnknownTypeArgs(type: ClassType, tupleClassType?: ClassType): ClassType {
|
||||
if (type.details.typeParameters.length === 0) {
|
||||
return type;
|
||||
}
|
||||
@ -1091,18 +1092,22 @@ export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
|
||||
|
||||
return ClassType.cloneForSpecialization(
|
||||
type,
|
||||
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param)),
|
||||
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param, tupleClassType)),
|
||||
/* isTypeArgumentExplicit */ false,
|
||||
/* includeSubclasses */ type.includeSubclasses
|
||||
);
|
||||
}
|
||||
|
||||
// Returns "Unknown" for simple TypeVars or the equivalent for a ParamSpec.
|
||||
export function getUnknownTypeForTypeVar(typeVar: TypeVarType): Type {
|
||||
export function getUnknownTypeForTypeVar(typeVar: TypeVarType, tupleClassType?: ClassType): Type {
|
||||
if (typeVar.details.isParamSpec) {
|
||||
return getUnknownTypeForParamSpec();
|
||||
}
|
||||
|
||||
if (typeVar.details.isVariadic && tupleClassType) {
|
||||
return getUnknownTypeForVariadicTypeVar(tupleClassType);
|
||||
}
|
||||
|
||||
return UnknownType.create();
|
||||
}
|
||||
|
||||
@ -1118,6 +1123,19 @@ export function getUnknownTypeForParamSpec(): FunctionType {
|
||||
return newFunction;
|
||||
}
|
||||
|
||||
export function getUnknownTypeForVariadicTypeVar(tupleClassType: ClassType): Type {
|
||||
assert(isInstantiableClass(tupleClassType) && ClassType.isBuiltIn(tupleClassType, 'tuple'));
|
||||
|
||||
return ClassType.cloneAsInstance(
|
||||
specializeTupleClass(
|
||||
tupleClassType,
|
||||
[{ type: UnknownType.create(), isUnbounded: true }],
|
||||
/* isTypeArgumentExplicit */ true,
|
||||
/* isUnpackedTuple */ true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Returns the equivalent of "Callable[..., Unknown]".
|
||||
export function getUnknownTypeForCallable(): FunctionType {
|
||||
const newFunction = FunctionType.createSynthesizedInstance('', FunctionTypeFlags.GradualCallableForm);
|
||||
@ -1374,7 +1392,7 @@ export function partiallySpecializeType(
|
||||
type: Type,
|
||||
contextClassType: ClassType,
|
||||
selfClass?: ClassType | TypeVarType,
|
||||
typeClassType?: Type
|
||||
typeClassType?: ClassType
|
||||
): Type {
|
||||
// If the context class is not specialized (or doesn't need specialization),
|
||||
// then there's no need to do any more work.
|
||||
@ -3115,7 +3133,7 @@ export function computeMroLinearization(classType: ClassType): boolean {
|
||||
// The first class in the MRO is the class itself.
|
||||
const typeVarContext = buildTypeVarContextFromSpecializedClass(classType);
|
||||
let specializedClassType = applySolvedTypeVars(classType, typeVarContext);
|
||||
if (!isClass(specializedClassType) && !isAny(specializedClassType) && !isUnknown(specializedClassType)) {
|
||||
if (!isClass(specializedClassType) && !isAnyOrUnknown(specializedClassType)) {
|
||||
specializedClassType = UnknownType.create();
|
||||
}
|
||||
|
||||
@ -3159,11 +3177,16 @@ export function computeMroLinearization(classType: ClassType): boolean {
|
||||
|
||||
if (!isInstantiableClass(classList[0])) {
|
||||
foundValidHead = true;
|
||||
assert(isClass(classList[0]) || isAnyOrUnknown(classList[0]));
|
||||
classType.details.mro.push(classList[0]);
|
||||
let head = classList[0];
|
||||
if (!isClass(head) && !isAnyOrUnknown(head)) {
|
||||
head = UnknownType.create();
|
||||
}
|
||||
classType.details.mro.push(head);
|
||||
classList.shift();
|
||||
break;
|
||||
} else if (!isInTail(classList[0], classListsToMerge)) {
|
||||
}
|
||||
|
||||
if (!isInTail(classList[0], classListsToMerge)) {
|
||||
foundValidHead = true;
|
||||
classType.details.mro.push(classList[0]);
|
||||
filterClass(classList[0], classListsToMerge);
|
||||
@ -3186,8 +3209,11 @@ export function computeMroLinearization(classType: ClassType): boolean {
|
||||
// Handle the situation by pull the head off the first empty list.
|
||||
// This allows us to make forward progress.
|
||||
if (!isInstantiableClass(nonEmptyList[0])) {
|
||||
assert(isClass(nonEmptyList[0]) || isAnyOrUnknown(nonEmptyList[0]));
|
||||
classType.details.mro.push(nonEmptyList[0]);
|
||||
let head = nonEmptyList[0];
|
||||
if (!isClass(head) && !isAnyOrUnknown(head)) {
|
||||
head = UnknownType.create();
|
||||
}
|
||||
classType.details.mro.push(head);
|
||||
nonEmptyList.shift();
|
||||
} else {
|
||||
classType.details.mro.push(nonEmptyList[0]);
|
||||
@ -3290,6 +3316,8 @@ export function convertTypeToParamSpecValue(type: Type): FunctionType {
|
||||
newFunction.details.typeVarScopeId = newFunction.details.higherOrderTypeVarScopeIds.pop();
|
||||
}
|
||||
|
||||
newFunction.details.constructorTypeVarScopeId = type.details.constructorTypeVarScopeId;
|
||||
|
||||
return newFunction;
|
||||
}
|
||||
|
||||
@ -3328,6 +3356,7 @@ export function convertParamSpecValueToType(type: FunctionType): Type {
|
||||
|
||||
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.typeVarScopeId);
|
||||
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.higherOrderTypeVarScopeIds);
|
||||
functionType.details.constructorTypeVarScopeId = withoutParamSpec.details.constructorTypeVarScopeId;
|
||||
|
||||
withoutParamSpec.details.parameters.forEach((entry, index) => {
|
||||
FunctionType.addParameter(functionType, {
|
||||
@ -4122,7 +4151,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
|
||||
|
||||
if (this._options.unknownIfNotFound) {
|
||||
return this._options.useUnknownOverDefault
|
||||
? specializeWithUnknownTypeArgs(subtype)
|
||||
? specializeWithUnknownTypeArgs(subtype, this._options.tupleClassType)
|
||||
: specializeWithDefaultTypeArgs(subtype);
|
||||
}
|
||||
}
|
||||
@ -4160,7 +4189,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
|
||||
return this._solveDefaultType(typeVar.details.defaultType, recursionCount);
|
||||
}
|
||||
|
||||
return UnknownType.create();
|
||||
return getUnknownTypeForTypeVar(typeVar, this._options.tupleClassType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,9 +825,7 @@ export namespace ClassType {
|
||||
newClassType.includeSubclasses = true;
|
||||
}
|
||||
|
||||
newClassType.tupleTypeArguments = tupleTypeArguments?.map((t) =>
|
||||
isNever(t.type) ? { type: UnknownType.create(), isUnbounded: t.isUnbounded, isOptional: t.isOptional } : t
|
||||
);
|
||||
newClassType.tupleTypeArguments = tupleTypeArguments ? [...tupleTypeArguments] : undefined;
|
||||
|
||||
if (isEmptyContainer !== undefined) {
|
||||
newClassType.isEmptyContainer = isEmptyContainer;
|
||||
@ -1766,6 +1764,7 @@ export namespace FunctionType {
|
||||
|
||||
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.typeVarScopeId);
|
||||
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.higherOrderTypeVarScopeIds);
|
||||
newFunction.details.constructorTypeVarScopeId = paramSpecValue.details.constructorTypeVarScopeId;
|
||||
|
||||
if (!newFunction.details.methodClass && paramSpecValue.details.methodClass) {
|
||||
newFunction.details.methodClass = paramSpecValue.details.methodClass;
|
||||
|
@ -24,11 +24,13 @@ export class BackgroundAnalysis extends BackgroundAnalysisBase {
|
||||
constructor(serviceProvider: ServiceProvider) {
|
||||
super(serviceProvider.console());
|
||||
|
||||
const index = ++BackgroundAnalysis._workerIndex;
|
||||
const initialData: InitializationData = {
|
||||
rootUri: getRootUri(serviceProvider)?.toString() ?? '',
|
||||
serviceId: index.toString(),
|
||||
cancellationFolderName: getCancellationFolderName(),
|
||||
runner: undefined,
|
||||
workerIndex: ++BackgroundAnalysis._workerIndex,
|
||||
workerIndex: index,
|
||||
};
|
||||
|
||||
// this will load this same file in BG thread and start listener
|
||||
|
@ -310,7 +310,14 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
|
||||
const console = this.getConsole();
|
||||
this.logTracker = new LogTracker(console, `BG(${threadId})`);
|
||||
|
||||
this._program = new Program(this.importResolver, this._configOptions, serviceProvider, this.logTracker);
|
||||
this._program = new Program(
|
||||
this.importResolver,
|
||||
this._configOptions,
|
||||
serviceProvider,
|
||||
this.logTracker,
|
||||
undefined,
|
||||
data.serviceId
|
||||
);
|
||||
}
|
||||
|
||||
get program(): Program {
|
||||
|
@ -251,10 +251,10 @@ export function getBackgroundWaiter<T>(port: MessagePort, deserializer: (v: any)
|
||||
|
||||
export interface InitializationData {
|
||||
rootUri: string;
|
||||
serviceId: string;
|
||||
workerIndex: number;
|
||||
cancellationFolderName: string | undefined;
|
||||
runner: string | undefined;
|
||||
title?: string;
|
||||
workerIndex: number;
|
||||
}
|
||||
|
||||
export interface RequestResponse {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Helper functions relating to collections and arrays.
|
||||
*/
|
||||
|
||||
import { compareValues, Comparison, equateValues, isArray } from './core';
|
||||
import { compareValues, Comparison, equateValues, isArray, MapLike } from './core';
|
||||
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
export type EqualityComparer<T> = (a: T, b: T) => boolean;
|
||||
@ -318,7 +318,7 @@ export function getNestedProperty(object: any, property: string) {
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getOrAdd<K, V>(map: Map<K, V>, key: K, newValueFactory: () => V): V {
|
||||
export function getOrAdd<K, V>(map: MapLike<K, V>, key: K, newValueFactory: () => V): V {
|
||||
const value = map.get(key);
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
|
@ -102,8 +102,11 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
* since `Object.prototype` may be modified by outside code.
|
||||
*/
|
||||
export interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
export interface MapLike<K, V> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value: V): this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +115,7 @@ export interface MapLike<T> {
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function hasProperty(map: MapLike<any>, key: string): boolean {
|
||||
export function hasProperty(map: { [index: string]: any }, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,7 @@ export function expandPathVariables(path: string, rootPath: Uri, workspaces: Wor
|
||||
const ws_regexp = RegExp(`\\$\\{workspaceFolder:${escapedWorkspaceName}\\}`, 'g');
|
||||
path = path.replace(ws_regexp, workspace.rootUri.getPath());
|
||||
}
|
||||
|
||||
if (process.env.HOME !== undefined) {
|
||||
replace(/\$\{env:HOME\}/g, process.env.HOME || '');
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import { printLiteralValue } from '../analyzer/typePrinter';
|
||||
import {
|
||||
ClassType,
|
||||
combineTypes,
|
||||
EnumLiteral,
|
||||
FunctionType,
|
||||
isClass,
|
||||
isClassInstance,
|
||||
@ -127,6 +128,7 @@ import {
|
||||
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
||||
import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils';
|
||||
import '../common/serviceProviderExtensions';
|
||||
import { transformTypeForEnumMember } from '../analyzer/enums';
|
||||
|
||||
namespace Keywords {
|
||||
const base: string[] = [
|
||||
@ -705,13 +707,7 @@ export class CompletionProvider {
|
||||
// Handle enum members specially. Enum members normally look like
|
||||
// variables, but the are declared using assignment expressions
|
||||
// within an enum class.
|
||||
if (
|
||||
primaryDecl.type === DeclarationType.Variable &&
|
||||
detail.boundObjectOrClass &&
|
||||
isInstantiableClass(detail.boundObjectOrClass) &&
|
||||
ClassType.isEnumClass(detail.boundObjectOrClass) &&
|
||||
primaryDecl.node.parent?.nodeType === ParseNodeType.Assignment
|
||||
) {
|
||||
if (this._isEnumMember(detail.boundObjectOrClass, name)) {
|
||||
itemKind = CompletionItemKind.EnumMember;
|
||||
}
|
||||
|
||||
@ -757,19 +753,16 @@ export class CompletionProvider {
|
||||
|
||||
if (isClass(subtype)) {
|
||||
const instance = TypeBase.isInstance(subtype);
|
||||
if (ClassType.isEnumClass(subtype) && instance) {
|
||||
// We don't add members for instances of enum members, but do add members of `enum.Enum` itself.
|
||||
// ex) 'MyEnum.member.' <= here
|
||||
const enumType = subtype.details.baseClasses.find(
|
||||
(t) => isClass(t) && ClassType.isBuiltIn(t, 'Enum')
|
||||
) as ClassType | undefined;
|
||||
if (!enumType) {
|
||||
return;
|
||||
}
|
||||
getMembersForClass(subtype, symbolTable, instance);
|
||||
|
||||
getMembersForClass(enumType, symbolTable, /* instance */ true);
|
||||
} else {
|
||||
getMembersForClass(subtype, symbolTable, instance);
|
||||
if (ClassType.isEnumClass(subtype) && instance) {
|
||||
// Don't show enum member out of another enum member
|
||||
// ex) Enum.Member. <= shouldn't show `Member` again.
|
||||
for (const name of symbolTable.keys()) {
|
||||
if (this._isEnumMember(subtype, name)) {
|
||||
symbolTable.delete(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isModule(subtype)) {
|
||||
getMembersForModule(subtype, symbolTable);
|
||||
@ -3143,6 +3136,21 @@ export class CompletionProvider {
|
||||
// before doing more expensive type evaluation.
|
||||
return decl.isMethod && decl.node.decorators.length > 0;
|
||||
}
|
||||
|
||||
private _isEnumMember(containingType: ClassType | undefined, name: string) {
|
||||
if (!containingType || !ClassType.isEnumClass(containingType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const symbolType = transformTypeForEnumMember(this.evaluator, containingType, name);
|
||||
|
||||
return (
|
||||
symbolType &&
|
||||
isClassInstance(symbolType) &&
|
||||
ClassType.isSameGenericClass(symbolType, containingType) &&
|
||||
symbolType.literalValue instanceof EnumLiteral
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class CompletionMap {
|
||||
|
@ -118,7 +118,7 @@ export function setLocaleOverride(locale: string) {
|
||||
localeOverride = locale.toLowerCase();
|
||||
}
|
||||
|
||||
export function getLocaleFromEnv() {
|
||||
export function getLocaleFromEnv(): string {
|
||||
if (localeOverride) {
|
||||
return localeOverride;
|
||||
}
|
||||
@ -130,7 +130,7 @@ export function getLocaleFromEnv() {
|
||||
const vscodeConfigString = env?.VSCODE_NLS_CONFIG;
|
||||
if (vscodeConfigString) {
|
||||
try {
|
||||
return JSON.parse(vscodeConfigString).locale;
|
||||
return JSON.parse(vscodeConfigString).locale || defaultLocale;
|
||||
} catch {
|
||||
// Fall through
|
||||
}
|
||||
@ -142,7 +142,7 @@ export function getLocaleFromEnv() {
|
||||
// This string may contain a local followed by an encoding (e.g. "en-us.UTF-8").
|
||||
const localeStringSplit = localeString.split('.');
|
||||
if (localeStringSplit.length > 0 && localeStringSplit[0]) {
|
||||
return localeStringSplit[0];
|
||||
return localeStringSplit[0] || defaultLocale;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
@ -158,8 +158,8 @@
|
||||
"enumMemberDelete": "Člen výčtu {name} se nedá odstranit.",
|
||||
"enumMemberSet": "Člen výčtu {name} se nedá přiřadit.",
|
||||
"enumMemberTypeAnnotation": "Poznámky typu nejsou pro členy výčtu povolené",
|
||||
"exceptionGroupIncompatible": "Syntaxe skupiny výjimek (except*) vyžaduje Python 3.11 nebo novější",
|
||||
"exceptionGroupTypeIncorrect": "Typ výjimky v kromě* se nedá odvodit z BaseGroupException.",
|
||||
"exceptionGroupIncompatible": "Syntaxe skupiny výjimek (\"except*\") vyžaduje Python 3.11 nebo novější",
|
||||
"exceptionGroupTypeIncorrect": "Typ výjimky v except* se nedá odvodit z BaseGroupException.",
|
||||
"exceptionTypeIncorrect": "„{type}“ se neodvozuje od BaseException",
|
||||
"exceptionTypeNotClass": "{type} není platná třída výjimky",
|
||||
"exceptionTypeNotInstantiable": "Konstruktor pro výjimku typu {type} vyžaduje jeden nebo více argumentů",
|
||||
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Argumenty typu nejsou u třídy Protocol povoleny při použití syntaxe parametru typu",
|
||||
"protocolIllegal": "Použití protokolu vyžaduje Python 3.7 nebo novější",
|
||||
"protocolNotAllowed": "„Protocol“ nejde v tomto kontextu použít.",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "Argument typu pro „protokol“ musí být parametr typu",
|
||||
"protocolUnsafeOverlap": "Třída se nebezpečně překrývá s názvem „{name}“ a může vytvořit shodu při spuštění.",
|
||||
"protocolVarianceContravariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kontravariantní",
|
||||
"protocolVarianceCovariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kovariantní",
|
||||
|
@ -159,7 +159,7 @@
|
||||
"enumMemberSet": "Das Enumerationselement \"{name}\" kann nicht zugewiesen werden.",
|
||||
"enumMemberTypeAnnotation": "Typanmerkungen sind für Enumerationsmember nicht zulässig",
|
||||
"exceptionGroupIncompatible": "Die Ausnahmegruppensyntax (\"except*\") erfordert Python 3.11 oder höher.",
|
||||
"exceptionGroupTypeIncorrect": "Der Ausnahmetyp in „except*“ kann nicht von BaseGroupException abgeleitet werden.",
|
||||
"exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.",
|
||||
"exceptionTypeIncorrect": "\"{type}\" ist nicht von BaseException abgeleitet.",
|
||||
"exceptionTypeNotClass": "\"{type}\" ist keine gültige Ausnahmeklasse.",
|
||||
"exceptionTypeNotInstantiable": "Der Konstruktor für den Ausnahmetyp \"{type}\" erfordert mindestens ein Argument.",
|
||||
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Typargumente sind mit der Protokollklasse nicht zulässig, wenn die Typparametersyntax verwendet wird.",
|
||||
"protocolIllegal": "Die Verwendung von \"Protocol\" erfordert Python 3.7 oder höher.",
|
||||
"protocolNotAllowed": "\"Protocol\" kann in diesem Kontext nicht verwendet werden.",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "Das Typargument für „Protocol“ muss ein Typparameter sein.",
|
||||
"protocolUnsafeOverlap": "Die Klasse überlappt unsicher mit „{name}“ und könnte zur Laufzeit eine Übereinstimmung erzeugen.",
|
||||
"protocolVarianceContravariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"contravariant\" sein.",
|
||||
"protocolVarianceCovariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"covariant\" sein.",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "No se permiten argumentos de tipo con la clase Protocol cuando se usa la sintaxis de parámetro de tipo",
|
||||
"protocolIllegal": "El uso de \"Protocolo\" requiere Python 3.7 o posterior.",
|
||||
"protocolNotAllowed": "\"Protocolo\" no puede utilizarse en este contexto",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "El argumento de tipo para \"Protocol\" debe ser un parámetro de tipo",
|
||||
"protocolUnsafeOverlap": "La clase se superpone \"{name}\" de forma no segura y podría producir una coincidencia en tiempo de ejecución",
|
||||
"protocolVarianceContravariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser contravariante.",
|
||||
"protocolVarianceCovariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser covariante",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Les arguments de type ne sont pas autorisés avec la classe Protocol lors de l'utilisation de la syntaxe des paramètres de type",
|
||||
"protocolIllegal": "L’utilisation de « Protocole » nécessite Python 3.7 ou une version plus récente",
|
||||
"protocolNotAllowed": "\"Protocole\" ne peut pas être utilisé dans ce contexte",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "L’argument de type pour « Protocol » doit être un paramètre de type",
|
||||
"protocolUnsafeOverlap": "La classe chevauche « {name} » de manière non sécurisée et peut produire une correspondance au moment de l’exécution",
|
||||
"protocolVarianceContravariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être contravariante",
|
||||
"protocolVarianceCovariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être covariante",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Gli argomenti tipo non sono consentiti con la classe Protocollo quando si usa la sintassi dei parametri tipo",
|
||||
"protocolIllegal": "L'uso del \"protocollo\" richiede Python 3.7 o versione successiva",
|
||||
"protocolNotAllowed": "\"Protocol\" non può essere usato in questo contesto",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "L'argomento di tipo per \"Protocol\" deve essere un parametro di tipo",
|
||||
"protocolUnsafeOverlap": "La classe si sovrappone a \"{name}\" in modo non sicuro e può produrre una corrispondenza in fase di esecuzione",
|
||||
"protocolVarianceContravariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere controvariante",
|
||||
"protocolVarianceCovariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere covariante",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "型パラメーター構文を使用する場合、Protocol クラスでは型引数を使用できません",
|
||||
"protocolIllegal": "\"Protocol\" を使用するには Python 3.7 以降が必要です",
|
||||
"protocolNotAllowed": "\"Protocol\" はこのコンテキストでは使用できません",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "\"Protocol\" の型引数は型パラメーターである必要があります",
|
||||
"protocolUnsafeOverlap": "クラスが安全でない方法で \"{name}\" と重複しており、実行時に一致する可能性があります",
|
||||
"protocolVarianceContravariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は反変である必要があります",
|
||||
"protocolVarianceCovariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は共変である必要があります",
|
||||
|
@ -159,7 +159,7 @@
|
||||
"enumMemberSet": "열거형 멤버 \"{name}\"을(를) 할당할 수 없음",
|
||||
"enumMemberTypeAnnotation": "열거형 멤버에는 형식 주석을 사용할 수 없습니다.",
|
||||
"exceptionGroupIncompatible": "예외 그룹 구문(\"except*\")에는 Python 3.11 이상이 필요합니다.",
|
||||
"exceptionGroupTypeIncorrect": "exception*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.",
|
||||
"exceptionGroupTypeIncorrect": "except*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.",
|
||||
"exceptionTypeIncorrect": "‘{type}’은 BaseException에서 파생되지 않습니다.",
|
||||
"exceptionTypeNotClass": "\"{type}\"은(는) 올바른 예외 클래스가 아닙니다.",
|
||||
"exceptionTypeNotInstantiable": "예외 형식 \"{type}\"에 대한 생성자에는 하나 이상의 인수가 필요합니다.",
|
||||
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "형식 매개 변수 구문을 사용할 때는 Protocol 클래스에 형식 인수가 허용되지 않습니다.",
|
||||
"protocolIllegal": "\"프로토콜\"을 사용하려면 Python 3.7 이상이 필요합니다.",
|
||||
"protocolNotAllowed": "이 컨텍스트에서는 \"Protocol\"을 사용할 수 없습니다.",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "\"Protocol\"의 형식 인수는 형식 매개 변수여야 합니다.",
|
||||
"protocolUnsafeOverlap": "클래스가 \"{name}\"과(와) 안전하지 않게 겹치며 런타임에 일치 항목을 생성할 수 있습니다.",
|
||||
"protocolVarianceContravariant": "‘{class}‘ 제네릭 프로토콜에서 사용되는 ’{variable}‘ 형식 변수는 반공변이어야 합니다.",
|
||||
"protocolVarianceCovariant": "‘{class}‘ 제네릭 프로토콜에서 사용되는 ’{variable}‘ 형식 변수는 공변이어야 합니다",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Argumenty typu są niedozwolone w przypadku klasy protokołu, gdy jest używana składnia parametru typu",
|
||||
"protocolIllegal": "Użycie elementu „Protocol” wymaga języka Python w wersji 3.7 lub nowszej",
|
||||
"protocolNotAllowed": "„Protokół” nie może być używany w tym kontekście",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "Argument typu dla elementy „Protocol” musi być parametrem typu",
|
||||
"protocolUnsafeOverlap": "Klasa nakłada się niebezpiecznie na element „{name}” i może utworzyć dopasowanie w czasie wykonywania",
|
||||
"protocolVarianceContravariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kontrawariantna",
|
||||
"protocolVarianceCovariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kowariantna",
|
||||
|
@ -158,8 +158,8 @@
|
||||
"enumMemberDelete": "O membro enumerado \"{name}\" não pode ser excluído",
|
||||
"enumMemberSet": "O membro enumerado \"{name}\" não pode ser atribuído",
|
||||
"enumMemberTypeAnnotation": "Anotações de tipo não são permitidas para membros de enumeração",
|
||||
"exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"exceto*\") requer o Python 3.11 ou mais recente",
|
||||
"exceptionGroupTypeIncorrect": "O tipo de exceção em exceto* não pode derivar de BaseGroupException",
|
||||
"exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"except*\") requer o Python 3.11 ou mais recente",
|
||||
"exceptionGroupTypeIncorrect": "O tipo de exceção em except* não pode derivar de BaseGroupException",
|
||||
"exceptionTypeIncorrect": "\"{type}\" não deriva de BaseException",
|
||||
"exceptionTypeNotClass": "\"{type}\" não é uma classe de exceção válida",
|
||||
"exceptionTypeNotInstantiable": "O construtor para o tipo de exceção \"{type}\" requer um ou mais argumentos",
|
||||
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Argumentos de tipo não são permitidos com a classe Protocol ao usar a sintaxe de parâmetro de tipo",
|
||||
"protocolIllegal": "O uso de \"Protocol\" requer o Python 3.7 ou mais recente",
|
||||
"protocolNotAllowed": "\"Protocol\" não pode ser usado nesse contexto",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "O argumento de tipo para o \"Protocolo\" deve ser um parâmetro de tipo",
|
||||
"protocolUnsafeOverlap": "A classe se sobrepõe a \"{name}\" de forma não segura e pode produzir uma correspondência em runtime",
|
||||
"protocolVarianceContravariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser contravariante",
|
||||
"protocolVarianceCovariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser covariante",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Аргументы типа не допускаются с классом протокола при использовании синтаксиса параметра типа",
|
||||
"protocolIllegal": "Ключевое слово \"Protocol\" можно использовать в Python версии не ниже 3.7",
|
||||
"protocolNotAllowed": "Невозможно использовать \"Protocol\" в этом контексте",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "Аргумент типа для параметра \"Protocol\" должен быть параметром типа",
|
||||
"protocolUnsafeOverlap": "Класс небезопасно перекрывает \"{name}\" и может вызвать совпадение во время выполнения",
|
||||
"protocolVarianceContravariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть контравариантной.",
|
||||
"protocolVarianceCovariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть ковариантной",
|
||||
|
@ -159,7 +159,7 @@
|
||||
"enumMemberSet": "Sabit liste üyesi \"{name}\" atanamıyor",
|
||||
"enumMemberTypeAnnotation": "Sabit listesi üyeleri için tür ek açıklamalarına izin verilmiyor",
|
||||
"exceptionGroupIncompatible": "Özel durum grubu söz dizimi (\"except*\") için Python 3.11 veya daha yeni bir sürümü gerekiyor",
|
||||
"exceptionGroupTypeIncorrect": "Except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor",
|
||||
"exceptionGroupTypeIncorrect": "except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor",
|
||||
"exceptionTypeIncorrect": "\"{type}\", BaseException türevi değil",
|
||||
"exceptionTypeNotClass": "\"{type}\" geçerli bir özel durum sınıfı değil",
|
||||
"exceptionTypeNotInstantiable": "\"{type}\" özel durum türü oluşturucusu bir veya daha fazla bağımsız değişken gerektiriyor",
|
||||
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "Tür parametresi söz dizimi kullanılırken, tür bağımsız değişkenlerinin Protokol sınıfıyla kullanılmasına izin verilmez",
|
||||
"protocolIllegal": "\"Protocol\" kullanımı için Python 3.7 veya daha yeni bir sürümü gerekiyor",
|
||||
"protocolNotAllowed": "\"Protokol\" bu bağlamda kullanılamaz",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "“Protokol” için tür bağımsız değişkeni bir tür parametresi olmalıdır",
|
||||
"protocolUnsafeOverlap": "Sınıf, \"{name}\" ile güvenli olmayan bir şekilde çakışıyor ve çalışma zamanında bir eşleşme üretebilir",
|
||||
"protocolVarianceContravariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni, değişken karşıtı olmalıdır",
|
||||
"protocolVarianceCovariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni birlikte değişen olmalıdır",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "使用类型参数语法时,协议类不允许使用类型参数",
|
||||
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更高版本",
|
||||
"protocolNotAllowed": "\"Protocol\" 不能用于此上下文",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "“协议”的类型参数必须是类型参数",
|
||||
"protocolUnsafeOverlap": "类与“{name}”不安全地重叠,并且可能在运行时生成匹配项",
|
||||
"protocolVarianceContravariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为逆变",
|
||||
"protocolVarianceCovariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为协变",
|
||||
|
@ -403,7 +403,7 @@
|
||||
"protocolBaseClassWithTypeArgs": "使用型別參數語法時,通訊協定類別不允許使用型別引數",
|
||||
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更新版本",
|
||||
"protocolNotAllowed": "\"Protocol\" 不能用在此內容中",
|
||||
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
|
||||
"protocolTypeArgMustBeTypeParam": "“Protocol” 的型別引數必須是型別參數",
|
||||
"protocolUnsafeOverlap": "類別以不安全方式重疊 \"{name}\",且可能會在運行時間產生相符專案",
|
||||
"protocolVarianceContravariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為逆變數",
|
||||
"protocolVarianceCovariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為共變數",
|
||||
|
@ -1302,3 +1302,90 @@ test('import from completion for namespace package', async () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('members off enum member', async () => {
|
||||
const code = `
|
||||
// @filename: test.py
|
||||
//// from enum import Enum
|
||||
//// class Planet(Enum):
|
||||
//// MERCURY = (3.303e+23, 2.4397e6)
|
||||
//// EARTH = (5.976e+24, 6.37814e6)
|
||||
////
|
||||
//// def __init__(self, mass, radius):
|
||||
//// self.mass = mass # in kilograms
|
||||
//// self.radius = radius # in meters
|
||||
////
|
||||
//// @property
|
||||
//// def surface_gravity(self):
|
||||
//// # universal gravitational constant (m3 kg-1 s-2)
|
||||
//// G = 6.67300E-11
|
||||
//// return G * self.mass / (self.radius * self.radius)
|
||||
////
|
||||
//// Planet.EARTH.[|/*marker*/|]
|
||||
`;
|
||||
|
||||
const state = parseAndGetTestState(code).state;
|
||||
|
||||
await state.verifyCompletion('excluded', 'markdown', {
|
||||
['marker']: {
|
||||
completions: [
|
||||
{
|
||||
label: 'MERCURY',
|
||||
kind: CompletionItemKind.EnumMember,
|
||||
},
|
||||
{
|
||||
label: 'EARTH',
|
||||
kind: CompletionItemKind.EnumMember,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await state.verifyCompletion('included', 'markdown', {
|
||||
['marker']: {
|
||||
completions: [
|
||||
{
|
||||
label: 'mass',
|
||||
kind: CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'radius',
|
||||
kind: CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'surface_gravity',
|
||||
kind: CompletionItemKind.Property,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('enum with regular base type', async () => {
|
||||
const code = `
|
||||
// @filename: test.py
|
||||
//// from enum import Enum
|
||||
//// from datetime import timedelta
|
||||
//// class Period(timedelta, Enum):
|
||||
//// Today = -1
|
||||
////
|
||||
//// Period.Today.[|/*marker*/|]
|
||||
`;
|
||||
|
||||
const state = parseAndGetTestState(code).state;
|
||||
|
||||
await state.verifyCompletion('included', 'markdown', {
|
||||
['marker']: {
|
||||
completions: [
|
||||
{
|
||||
label: 'days',
|
||||
kind: CompletionItemKind.Property,
|
||||
},
|
||||
{
|
||||
label: 'seconds',
|
||||
kind: CompletionItemKind.Property,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -192,4 +192,47 @@ describe(`Basic language server tests`, () => {
|
||||
assert.equal(diagnostic.diagnostics[3].code, 'reportUnusedImport');
|
||||
assert.equal(diagnostic.diagnostics[5].code, 'reportUnusedImport');
|
||||
});
|
||||
|
||||
test('Diagnostic severity overrides test', async () => {
|
||||
const code = `
|
||||
// @filename: test.py
|
||||
//// def test([|/*marker*/x|]): ...
|
||||
////
|
||||
// @filename: pyproject.toml
|
||||
////
|
||||
`;
|
||||
const settings = [
|
||||
{
|
||||
item: {
|
||||
scopeUri: `file://${normalizeSlashes(DEFAULT_WORKSPACE_ROOT, '/')}`,
|
||||
section: 'python.analysis',
|
||||
},
|
||||
value: {
|
||||
diagnosticSeverityOverrides: {
|
||||
reportUnknownParameterType: 'warning',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const info = await runLanguageServer(
|
||||
DEFAULT_WORKSPACE_ROOT,
|
||||
code,
|
||||
/* callInitialize */ true,
|
||||
settings,
|
||||
undefined,
|
||||
/* supportsBackgroundThread */ true
|
||||
);
|
||||
|
||||
// get the file containing the marker that also contains our task list comments
|
||||
await openFile(info, 'marker');
|
||||
|
||||
// Wait for the diagnostics to publish
|
||||
const diagnostics = await waitForDiagnostics(info);
|
||||
const diagnostic = diagnostics.find((d) => d.uri.includes('test.py'));
|
||||
assert(diagnostic);
|
||||
|
||||
// Make sure the error has a special rule
|
||||
assert.equal(diagnostic.diagnostics[0].code, 'reportUnknownParameterType');
|
||||
});
|
||||
});
|
||||
|
@ -7,8 +7,7 @@ from abc import ABC, abstractmethod
|
||||
class A(ABC):
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def method1() -> None:
|
||||
...
|
||||
def method1() -> None: ...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
@ -66,8 +65,7 @@ def func1(a: type[A]):
|
||||
a.method3()
|
||||
|
||||
|
||||
class C(A):
|
||||
...
|
||||
class C(A): ...
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
|
@ -18,8 +18,7 @@ class Foo(ABC):
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
def func1(self, a: str) -> str:
|
||||
...
|
||||
def func1(self, a: str) -> str: ...
|
||||
|
||||
# This should generate an error because this overload is
|
||||
# missing an abstractmethod overload.
|
||||
@ -27,8 +26,7 @@ class Foo(ABC):
|
||||
raise NotImplementedError()
|
||||
|
||||
@overload
|
||||
def func2(self, a: str) -> str:
|
||||
...
|
||||
def func2(self, a: str) -> str: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
|
@ -23,5 +23,4 @@ class Bar(Foo):
|
||||
@final
|
||||
# This should generate an error because Foo.foo, Bar.bar, and Bar.bar1
|
||||
# are abstract.
|
||||
class Baz(Bar):
|
||||
...
|
||||
class Baz(Bar): ...
|
||||
|
@ -9,8 +9,7 @@ from typing import NamedTuple
|
||||
class ClassA(ABC):
|
||||
@property
|
||||
@abstractmethod
|
||||
def myproperty(self) -> str:
|
||||
...
|
||||
def myproperty(self) -> str: ...
|
||||
|
||||
|
||||
MixinB = NamedTuple("MixinB", [("myproperty", str)])
|
||||
|
@ -10,9 +10,7 @@ v1: Annotated[str, ClassA, func1(), v2[0]] = ""
|
||||
v2 = [1, 2, 3]
|
||||
|
||||
|
||||
class ClassA:
|
||||
...
|
||||
class ClassA: ...
|
||||
|
||||
|
||||
def func1():
|
||||
...
|
||||
def func1(): ...
|
||||
|
@ -64,8 +64,7 @@ class ClassD:
|
||||
|
||||
str: "str"
|
||||
|
||||
def int(self):
|
||||
...
|
||||
def int(self): ...
|
||||
|
||||
foo: "int"
|
||||
|
||||
@ -147,4 +146,3 @@ x12: b"int"
|
||||
|
||||
# This should generate an error because format strings aren't allowed.
|
||||
x13: f"int"
|
||||
|
||||
|
@ -27,8 +27,7 @@ class ClassB(ClassA):
|
||||
def func5(self, x: ClassA):
|
||||
x.func0()
|
||||
|
||||
class ClassA:
|
||||
...
|
||||
class ClassA: ...
|
||||
|
||||
def func6(self, x: ClassC):
|
||||
x.my_int
|
||||
|
@ -53,8 +53,7 @@ e = [3]
|
||||
e: list[int]
|
||||
|
||||
|
||||
def register(fn: Callable[[], None]) -> None:
|
||||
...
|
||||
def register(fn: Callable[[], None]) -> None: ...
|
||||
|
||||
|
||||
# These should be be fine because they use the "_" name.
|
||||
|
@ -11,12 +11,10 @@ v1 = cast(Any, 0)
|
||||
v2 = cast(typing.Any, 0)
|
||||
|
||||
|
||||
class A(Any):
|
||||
...
|
||||
class A(Any): ...
|
||||
|
||||
|
||||
class B(typing.Any):
|
||||
...
|
||||
class B(typing.Any): ...
|
||||
|
||||
|
||||
# This should generate an error because Any is not callable.
|
||||
|
@ -20,8 +20,7 @@ class A:
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class B(Generic[T]):
|
||||
...
|
||||
class B(Generic[T]): ...
|
||||
|
||||
|
||||
def func1(v1: list[Any | None], v2: list[int | str]):
|
||||
|
@ -38,8 +38,7 @@ d4: dict[str, tuple[int, Callable[[int], int]]] = {
|
||||
|
||||
|
||||
class Adder(Protocol):
|
||||
def __call__(self, x: int, y: dict[str, int]) -> int:
|
||||
...
|
||||
def __call__(self, x: int, y: dict[str, int]) -> int: ...
|
||||
|
||||
|
||||
v1: Adder = lambda x, y: x + y["hi"]
|
||||
|
@ -7,12 +7,10 @@ from typing import Any, TypeVar, overload
|
||||
|
||||
class Foo:
|
||||
@overload
|
||||
def bar(self, obj: None) -> object:
|
||||
...
|
||||
def bar(self, obj: None) -> object: ...
|
||||
|
||||
@overload
|
||||
def bar(self, obj: object) -> Any:
|
||||
...
|
||||
def bar(self, obj: object) -> Any: ...
|
||||
|
||||
def bar(self, obj: object | None) -> Any:
|
||||
pass
|
||||
|
@ -17,8 +17,7 @@ def func1() -> Tuple[str, int]:
|
||||
return (a, y)
|
||||
|
||||
|
||||
def get_value(x: int) -> int:
|
||||
...
|
||||
def get_value(x: int) -> int: ...
|
||||
|
||||
|
||||
x = sum(max(value for x in range(10) if (value := get_value(x))) for _ in range(10))
|
||||
|
@ -7,8 +7,7 @@ from typing import Any, Callable, TypeVar, overload
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]:
|
||||
...
|
||||
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]: ...
|
||||
|
||||
|
||||
@decorator(
|
||||
@ -19,7 +18,7 @@ def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]:
|
||||
],
|
||||
)
|
||||
def decorated(
|
||||
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])]
|
||||
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])],
|
||||
):
|
||||
pass
|
||||
|
||||
@ -29,13 +28,11 @@ reveal_type(walrus_target_2, expected_text="list[str]")
|
||||
|
||||
|
||||
@overload
|
||||
def func1(value: None = None) -> None:
|
||||
...
|
||||
def func1(value: None = None) -> None: ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(value: str) -> str:
|
||||
...
|
||||
def func1(value: str) -> str: ...
|
||||
|
||||
|
||||
def func1(value: str | None = None) -> str | None:
|
||||
|
@ -19,15 +19,12 @@ class MyPartial[**P, R]:
|
||||
self.first = first
|
||||
self.func = func
|
||||
|
||||
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
|
||||
...
|
||||
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
|
||||
|
||||
|
||||
class CallbackKeyed[*Ts](Protocol):
|
||||
def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]:
|
||||
...
|
||||
def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]: ...
|
||||
|
||||
|
||||
def invoke_keyed[*Ts](fn: CallbackKeyed[*Ts], *args: *Ts) -> tuple[*Ts]:
|
||||
return fn(*args, keyed=True)
|
||||
|
||||
|
@ -7,12 +7,15 @@ T = TypeVar("T")
|
||||
T_co = TypeVar("T_co", covariant=True)
|
||||
T_contra = TypeVar("T_contra", contravariant=True)
|
||||
|
||||
|
||||
class Parent_Invariant(Generic[T]):
|
||||
pass
|
||||
|
||||
|
||||
class ShouldBeInvariant[T](Parent_Invariant[T]):
|
||||
pass
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
a1: ShouldBeInvariant[int] = ShouldBeInvariant[float]()
|
||||
|
||||
@ -23,9 +26,11 @@ a2: ShouldBeInvariant[float] = ShouldBeInvariant[int]()
|
||||
class Parent_Covariant(Generic[T_co]):
|
||||
pass
|
||||
|
||||
|
||||
class ShouldBeCovariant[T](Parent_Covariant[T]):
|
||||
pass
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
b1: ShouldBeCovariant[int] = ShouldBeCovariant[float]()
|
||||
|
||||
@ -35,11 +40,12 @@ b2: ShouldBeCovariant[float] = ShouldBeCovariant[int]()
|
||||
class Parent_Contravariant(Generic[T_contra]):
|
||||
pass
|
||||
|
||||
|
||||
class ShouldBeContravariant[T](Parent_Contravariant[T]):
|
||||
pass
|
||||
|
||||
|
||||
c1: ShouldBeContravariant[int] = ShouldBeContravariant[float]()
|
||||
|
||||
# This should generate an error.
|
||||
c2: ShouldBeContravariant[float] = ShouldBeContravariant[int]()
|
||||
|
||||
|
@ -4,12 +4,10 @@
|
||||
from typing import Any, Hashable, Mapping, Protocol
|
||||
|
||||
|
||||
def requires_hashable_tuple(p1: tuple[Hashable, ...]):
|
||||
...
|
||||
def requires_hashable_tuple(p1: tuple[Hashable, ...]): ...
|
||||
|
||||
|
||||
def requires_hashable_dict(p1: dict[str, Hashable]):
|
||||
...
|
||||
def requires_hashable_dict(p1: dict[str, Hashable]): ...
|
||||
|
||||
|
||||
def test_args(*args: Hashable):
|
||||
@ -24,8 +22,7 @@ def test_kwargs(**kwargs: Hashable):
|
||||
requires_hashable_dict(kwargs)
|
||||
|
||||
|
||||
class StrSubclass(str):
|
||||
...
|
||||
class StrSubclass(str): ...
|
||||
|
||||
|
||||
def test_kwargs2(
|
||||
@ -51,30 +48,26 @@ def test_kwargs2(
|
||||
|
||||
|
||||
class Callback1(Protocol):
|
||||
def __call__(self) -> None:
|
||||
...
|
||||
def __call__(self) -> None: ...
|
||||
|
||||
|
||||
def func1(
|
||||
value: str = ...,
|
||||
*args: object,
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
|
||||
def func2(
|
||||
value: str = ...,
|
||||
**kwargs: object,
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
|
||||
def func3(
|
||||
value: str = ...,
|
||||
*args: object,
|
||||
**kwargs: object,
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
|
||||
v1: Callback1 = func1
|
||||
|
@ -71,8 +71,7 @@ for a, b in zip(*q6):
|
||||
reveal_type(b, expected_text="int")
|
||||
|
||||
|
||||
def func1(a: list[str], c: list[int]):
|
||||
...
|
||||
def func1(a: list[str], c: list[int]): ...
|
||||
|
||||
|
||||
func1(*q6)
|
||||
|
@ -5,31 +5,25 @@
|
||||
from typing import Any, Generic, TypeVar, Mapping, KeysView
|
||||
|
||||
|
||||
class MyMapping(Mapping[str, Any]):
|
||||
...
|
||||
class MyMapping(Mapping[str, Any]): ...
|
||||
|
||||
|
||||
class StrRecord:
|
||||
def __getitem__(self, __key: str) -> str:
|
||||
...
|
||||
def __getitem__(self, __key: str) -> str: ...
|
||||
|
||||
def keys(self) -> KeysView[str]:
|
||||
...
|
||||
def keys(self) -> KeysView[str]: ...
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class GenericRecord(Generic[T]):
|
||||
def __getitem__(self, __key: str) -> T:
|
||||
...
|
||||
def __getitem__(self, __key: str) -> T: ...
|
||||
|
||||
def keys(self) -> KeysView[T]:
|
||||
...
|
||||
def keys(self) -> KeysView[T]: ...
|
||||
|
||||
|
||||
def func1(**kwargs: Any) -> None:
|
||||
...
|
||||
def func1(**kwargs: Any) -> None: ...
|
||||
|
||||
|
||||
m = MyMapping()
|
||||
|
@ -9,16 +9,14 @@ from typing import Any, Awaitable, Callable, Iterable, Sequence, TypeVar
|
||||
_T1 = TypeVar("_T1")
|
||||
|
||||
|
||||
def func1(__iterable: Iterable[_T1]) -> _T1:
|
||||
...
|
||||
def func1(__iterable: Iterable[_T1]) -> _T1: ...
|
||||
|
||||
|
||||
a: Callable[[Sequence[float]], float] = func1
|
||||
b: Callable[[Sequence[Any]], Any] = func1
|
||||
|
||||
|
||||
def func2(__iterable: Sequence[_T1]) -> _T1:
|
||||
...
|
||||
def func2(__iterable: Sequence[_T1]) -> _T1: ...
|
||||
|
||||
|
||||
# This should generate an error because an Iterable parameter
|
||||
@ -29,8 +27,7 @@ c: Callable[[Iterable[float]], float] = func2
|
||||
_T2 = TypeVar("_T2", bound=float)
|
||||
|
||||
|
||||
def func3(__iterable: Iterable[_T2]) -> _T2:
|
||||
...
|
||||
def func3(__iterable: Iterable[_T2]) -> _T2: ...
|
||||
|
||||
|
||||
d: Callable[[Sequence[int]], int] = func3
|
||||
|
@ -8,8 +8,7 @@ T = TypeVar("T")
|
||||
R = TypeVar("R")
|
||||
|
||||
|
||||
class ClassA(Generic[R]):
|
||||
...
|
||||
class ClassA(Generic[R]): ...
|
||||
|
||||
|
||||
class ClassB(Generic[T]):
|
||||
|
@ -8,17 +8,14 @@ T = TypeVar("T")
|
||||
|
||||
|
||||
@overload
|
||||
def func1(real: float):
|
||||
...
|
||||
def func1(real: float): ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(real: str):
|
||||
...
|
||||
def func1(real: str): ...
|
||||
|
||||
|
||||
def func1(real: float | str) -> None:
|
||||
...
|
||||
def func1(real: float | str) -> None: ...
|
||||
|
||||
|
||||
def func2(f: Callable[[T], Any], p: T):
|
||||
|
@ -1,5 +1,6 @@
|
||||
# This sample tests the handling of the `__call__` attribute.
|
||||
|
||||
|
||||
class A:
|
||||
def __init__(self):
|
||||
self.__call__ = self.method1
|
||||
|
@ -140,7 +140,7 @@ class TestClass7:
|
||||
pass
|
||||
|
||||
|
||||
def test_func7(*args: * tuple[int, *tuple[int, ...]]) -> int:
|
||||
def test_func7(*args: *tuple[int, *tuple[int, ...]]) -> int:
|
||||
return 123
|
||||
|
||||
|
||||
|
@ -9,8 +9,7 @@ OutputT = TypeVar("OutputT", covariant=True)
|
||||
|
||||
|
||||
class MyCallable(Protocol[InputT, OutputT]):
|
||||
def __call__(self, inputs: InputT) -> OutputT:
|
||||
...
|
||||
def __call__(self, inputs: InputT) -> OutputT: ...
|
||||
|
||||
|
||||
class Class1:
|
||||
|
@ -7,17 +7,14 @@ TE = TypeVar("TE", bound=Exception)
|
||||
|
||||
|
||||
class CallbackProtocol1(Protocol[TE]):
|
||||
def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE:
|
||||
...
|
||||
def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
|
||||
|
||||
|
||||
def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE:
|
||||
...
|
||||
def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
|
||||
|
||||
|
||||
def func2(
|
||||
s_exc_class: Exception,
|
||||
t_exc_class: Type[TE],
|
||||
mapper: CallbackProtocol1[TE] = func1,
|
||||
):
|
||||
...
|
||||
): ...
|
||||
|
@ -6,15 +6,12 @@ from typing import Any, Protocol, overload
|
||||
|
||||
class P1(Protocol):
|
||||
@overload
|
||||
def __call__(self, x: int) -> int:
|
||||
...
|
||||
def __call__(self, x: int) -> int: ...
|
||||
|
||||
@overload
|
||||
def __call__(self, x: str) -> str:
|
||||
...
|
||||
def __call__(self, x: str) -> str: ...
|
||||
|
||||
def __call__(self, x: Any) -> Any:
|
||||
...
|
||||
def __call__(self, x: Any) -> Any: ...
|
||||
|
||||
|
||||
def func0(x: Any) -> Any:
|
||||
@ -32,13 +29,11 @@ a1: P1 = func1
|
||||
|
||||
|
||||
@overload
|
||||
def of1(x: int) -> int:
|
||||
...
|
||||
def of1(x: int) -> int: ...
|
||||
|
||||
|
||||
@overload
|
||||
def of1(x: str) -> str:
|
||||
...
|
||||
def of1(x: str) -> str: ...
|
||||
|
||||
|
||||
def of1(x: Any) -> Any:
|
||||
@ -46,13 +41,11 @@ def of1(x: Any) -> Any:
|
||||
|
||||
|
||||
@overload
|
||||
def of2(x: int) -> complex:
|
||||
...
|
||||
def of2(x: int) -> complex: ...
|
||||
|
||||
|
||||
@overload
|
||||
def of2(x: str) -> str:
|
||||
...
|
||||
def of2(x: str) -> str: ...
|
||||
|
||||
|
||||
def of2(x: Any) -> Any:
|
||||
@ -66,8 +59,7 @@ b1: P1 = of2
|
||||
|
||||
|
||||
class P2(Protocol):
|
||||
def __call__(self, *args: int) -> Any:
|
||||
...
|
||||
def __call__(self, *args: int) -> Any: ...
|
||||
|
||||
|
||||
a: P2 = lambda *args: map(lambda arg: arg + 0, args)
|
||||
|
@ -6,22 +6,18 @@ from typing import Protocol
|
||||
|
||||
# Callback with positional parameter with default arg value.
|
||||
class Callback1(Protocol):
|
||||
def __call__(self, path: str = ...) -> str:
|
||||
...
|
||||
def __call__(self, path: str = ...) -> str: ...
|
||||
|
||||
|
||||
# Callback with positional parameter without default arg value.
|
||||
class Callback2(Protocol):
|
||||
def __call__(self, path: str) -> str:
|
||||
...
|
||||
def __call__(self, path: str) -> str: ...
|
||||
|
||||
|
||||
def func1_1(path: str = "") -> str:
|
||||
...
|
||||
def func1_1(path: str = "") -> str: ...
|
||||
|
||||
|
||||
def func1_2(path: str) -> str:
|
||||
...
|
||||
def func1_2(path: str) -> str: ...
|
||||
|
||||
|
||||
val1_1: Callback1 = func1_1
|
||||
@ -36,22 +32,18 @@ val2_2: Callback2 = func1_2
|
||||
|
||||
# Callback with keyword parameter with default arg value.
|
||||
class Callback3(Protocol):
|
||||
def __call__(self, *, path: str = ...) -> str:
|
||||
...
|
||||
def __call__(self, *, path: str = ...) -> str: ...
|
||||
|
||||
|
||||
# Callback with keyword parameter without default arg value.
|
||||
class Callback4(Protocol):
|
||||
def __call__(self, *, path: str) -> str:
|
||||
...
|
||||
def __call__(self, *, path: str) -> str: ...
|
||||
|
||||
|
||||
def func3_1(*, path: str = "") -> str:
|
||||
...
|
||||
def func3_1(*, path: str = "") -> str: ...
|
||||
|
||||
|
||||
def func3_2(*, path: str) -> str:
|
||||
...
|
||||
def func3_2(*, path: str) -> str: ...
|
||||
|
||||
|
||||
val3_1: Callback3 = func3_1
|
||||
|
@ -5,11 +5,10 @@ from typing import Any, Protocol
|
||||
|
||||
|
||||
class X(Protocol):
|
||||
def __call__(self, x: int, /, y: str) -> Any:
|
||||
...
|
||||
def __call__(self, x: int, /, y: str) -> Any: ...
|
||||
|
||||
def f1(x: int, /, y: str, z: None = None) -> Any:
|
||||
...
|
||||
|
||||
def f1(x: int, /, y: str, z: None = None) -> Any: ...
|
||||
|
||||
|
||||
x: X = f1
|
||||
|
@ -5,12 +5,10 @@ from typing import Any, Protocol
|
||||
|
||||
|
||||
class P(Protocol):
|
||||
def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None:
|
||||
...
|
||||
def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
|
||||
|
||||
|
||||
def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None:
|
||||
...
|
||||
def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
|
||||
|
||||
|
||||
p: P = f
|
||||
|
@ -15,8 +15,7 @@ class A:
|
||||
_T = TypeVar("_T", bound=A)
|
||||
|
||||
|
||||
class B(Generic[_T]):
|
||||
...
|
||||
class B(Generic[_T]): ...
|
||||
|
||||
|
||||
class C(A):
|
||||
|
@ -9,8 +9,7 @@ class ClassA:
|
||||
# This should generate a warning because __class_getitem__
|
||||
# is implicitly a classmethod and should use cls rather than
|
||||
# self.
|
||||
def __class_getitem__(self, args: tuple[int, ...]) -> None:
|
||||
...
|
||||
def __class_getitem__(self, args: tuple[int, ...]) -> None: ...
|
||||
|
||||
|
||||
reveal_type(ClassA[10, 63], expected_text="type[ClassA]")
|
||||
@ -23,8 +22,7 @@ _S = TypeVar("_S")
|
||||
class ClassB(Generic[_T, _S]):
|
||||
# Even though this class has a __class_getitem__ method,
|
||||
# it will be assumed to follow normal generic class semantics.
|
||||
def __class_getitem__(cls, args: tuple[int, ...]) -> None:
|
||||
...
|
||||
def __class_getitem__(cls, args: tuple[int, ...]) -> None: ...
|
||||
|
||||
|
||||
reveal_type(ClassB[int, str], expected_text="type[ClassB[int, str]]")
|
||||
|
@ -19,7 +19,6 @@ def dynamic_subclass1(cls: type[T_A]):
|
||||
|
||||
|
||||
def dynamic_subclass2(base: type[A] | None):
|
||||
class SubClass(base or A):
|
||||
...
|
||||
class SubClass(base or A): ...
|
||||
|
||||
return SubClass
|
||||
|
@ -6,34 +6,27 @@ from typing import Collection, Iterator, Mapping, Sequence, TypeVar
|
||||
|
||||
# This should generate an error.
|
||||
class A(Mapping[str, int], Collection[int]):
|
||||
def __len__(self) -> int:
|
||||
...
|
||||
def __len__(self) -> int: ...
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
...
|
||||
def __iter__(self) -> Iterator[str]: ...
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
class B(Mapping[str, int], Sequence[int]):
|
||||
...
|
||||
class B(Mapping[str, int], Sequence[int]): ...
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
class C(Sequence[int], Mapping[str, int]):
|
||||
...
|
||||
class C(Sequence[int], Mapping[str, int]): ...
|
||||
|
||||
|
||||
class D(Sequence[float], Mapping[float, int]):
|
||||
...
|
||||
class D(Sequence[float], Mapping[float, int]): ...
|
||||
|
||||
|
||||
class E(Sequence[float], Mapping[int, int]):
|
||||
...
|
||||
class E(Sequence[float], Mapping[int, int]): ...
|
||||
|
||||
|
||||
# This should generate an error.
|
||||
class F(Mapping[int, int], Sequence[float]):
|
||||
...
|
||||
class F(Mapping[int, int], Sequence[float]): ...
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
@ -41,16 +34,13 @@ S = TypeVar("S")
|
||||
|
||||
|
||||
class G(Mapping[T, S], Collection[T]):
|
||||
def __len__(self) -> int:
|
||||
...
|
||||
def __len__(self) -> int: ...
|
||||
|
||||
def __iter__(self) -> Iterator[T]: ...
|
||||
|
||||
def __iter__(self) -> Iterator[T]:
|
||||
...
|
||||
|
||||
# This should generate an error.
|
||||
class H(Mapping[T, S], Collection[S]):
|
||||
def __len__(self) -> int:
|
||||
...
|
||||
def __len__(self) -> int: ...
|
||||
|
||||
def __iter__(self) -> Iterator[T]:
|
||||
...
|
||||
def __iter__(self) -> Iterator[T]: ...
|
||||
|
@ -215,8 +215,7 @@ class SubclassTuple2(ParentClass2):
|
||||
cv_decl_1, cv_decl_2, cv_decl_3 = (3, 4.5, None)
|
||||
|
||||
|
||||
class ConfigBase:
|
||||
...
|
||||
class ConfigBase: ...
|
||||
|
||||
|
||||
class ParentClass3(Protocol):
|
||||
@ -225,13 +224,11 @@ class ParentClass3(Protocol):
|
||||
|
||||
|
||||
class ChildClass3(ParentClass3):
|
||||
class Config1(ConfigBase):
|
||||
...
|
||||
class Config1(ConfigBase): ...
|
||||
|
||||
# This should generate an error if reportIncompatibleVariableOverride
|
||||
# is enabled.
|
||||
class Config2:
|
||||
...
|
||||
class Config2: ...
|
||||
|
||||
|
||||
class PeerClass1:
|
||||
|
@ -66,5 +66,4 @@ class TD_A2(TypedDict):
|
||||
|
||||
|
||||
# This should generate an error for x but not y.
|
||||
class TD_A(TD_A1, TD_A2):
|
||||
...
|
||||
class TD_A(TD_A1, TD_A2): ...
|
||||
|
@ -5,31 +5,25 @@
|
||||
from typing import Any, Callable, overload
|
||||
|
||||
|
||||
class C:
|
||||
...
|
||||
class C: ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(v: Callable[[], int]) -> int:
|
||||
...
|
||||
def func1(v: Callable[[], int]) -> int: ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(v: Callable[[], list[C]]) -> list[C]:
|
||||
...
|
||||
def func1(v: Callable[[], list[C]]) -> list[C]: ...
|
||||
|
||||
|
||||
def func1(v: Any) -> Any:
|
||||
...
|
||||
def func1(v: Any) -> Any: ...
|
||||
|
||||
|
||||
def func2(v: list[C]):
|
||||
...
|
||||
def func2(v: list[C]): ...
|
||||
|
||||
|
||||
t = func1(lambda: func3())
|
||||
t.append(C())
|
||||
|
||||
|
||||
def func3() -> list[C]:
|
||||
...
|
||||
def func3() -> list[C]: ...
|
||||
|
@ -5,31 +5,25 @@
|
||||
from typing import Any, Callable, overload
|
||||
|
||||
|
||||
class C:
|
||||
...
|
||||
class C: ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(v: Callable[[], int]) -> int:
|
||||
...
|
||||
def func1(v: Callable[[], int]) -> int: ...
|
||||
|
||||
|
||||
@overload
|
||||
def func1(v: Callable[[], list[C]]) -> list[C]:
|
||||
...
|
||||
def func1(v: Callable[[], list[C]]) -> list[C]: ...
|
||||
|
||||
|
||||
def func1(v: Any) -> Any:
|
||||
...
|
||||
def func1(v: Any) -> Any: ...
|
||||
|
||||
|
||||
def func2(v: list[C]):
|
||||
...
|
||||
def func2(v: list[C]): ...
|
||||
|
||||
|
||||
t = func1(lambda: func3())
|
||||
t.append(C())
|
||||
|
||||
|
||||
def func3() -> list[C]:
|
||||
...
|
||||
def func3() -> list[C]: ...
|
||||
|
@ -30,12 +30,10 @@ def func1(os: OS, val: Literal[1, "linux"]):
|
||||
return True
|
||||
|
||||
|
||||
class ClassA:
|
||||
...
|
||||
class ClassA: ...
|
||||
|
||||
|
||||
class ClassB:
|
||||
...
|
||||
class ClassB: ...
|
||||
|
||||
|
||||
_T1 = TypeVar("_T1")
|
||||
|
@ -8,8 +8,7 @@ b = a + 4
|
||||
c = 1.2 * a
|
||||
|
||||
|
||||
def requires_complex(val: complex):
|
||||
...
|
||||
def requires_complex(val: complex): ...
|
||||
|
||||
|
||||
requires_complex(a)
|
||||
|
@ -18,8 +18,7 @@ def add1(value: _T1) -> _T1:
|
||||
|
||||
|
||||
class IntSubclass2(int):
|
||||
def __add__(self, value: object) -> "IntSubclass2":
|
||||
...
|
||||
def __add__(self, value: object) -> "IntSubclass2": ...
|
||||
|
||||
|
||||
_T2 = TypeVar("_T2", int, IntSubclass2)
|
||||
|
@ -6,8 +6,7 @@ from os import PathLike
|
||||
from typing import AnyStr
|
||||
|
||||
|
||||
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr:
|
||||
...
|
||||
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr: ...
|
||||
|
||||
|
||||
def func2(value: AnyStr) -> AnyStr:
|
||||
|
@ -5,16 +5,13 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
|
||||
class A:
|
||||
...
|
||||
class A: ...
|
||||
|
||||
|
||||
class B:
|
||||
...
|
||||
class B: ...
|
||||
|
||||
|
||||
class A2(A):
|
||||
...
|
||||
class A2(A): ...
|
||||
|
||||
|
||||
T = TypeVar("T", A, B)
|
||||
|
@ -5,8 +5,7 @@ from typing import AnyStr, Iterable, TypeVar, Generic
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
class ClassA:
|
||||
...
|
||||
class ClassA: ...
|
||||
|
||||
|
||||
_T = TypeVar("_T", int | float, ClassA)
|
||||
|
@ -13,12 +13,10 @@ _T1 = TypeVar("_T1")
|
||||
AnyStr = TypeVar("AnyStr", str, bytes)
|
||||
|
||||
|
||||
def exists2(path: AnyStr) -> bool:
|
||||
...
|
||||
def exists2(path: AnyStr) -> bool: ...
|
||||
|
||||
|
||||
def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]:
|
||||
...
|
||||
def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]: ...
|
||||
|
||||
|
||||
result = filter2(exists2, ["hello", "world"])
|
||||
|
@ -8,12 +8,10 @@
|
||||
from typing import Any, AnyStr, Optional, Protocol, TypeVar, Union
|
||||
|
||||
|
||||
class Array:
|
||||
...
|
||||
class Array: ...
|
||||
|
||||
|
||||
class MMap:
|
||||
...
|
||||
class MMap: ...
|
||||
|
||||
|
||||
# Note that this union contains types that are not compatible
|
||||
@ -25,29 +23,24 @@ _T_co = TypeVar("_T_co", covariant=True)
|
||||
|
||||
|
||||
class BufferedWriter:
|
||||
def write(self, __buffer: ReadableBuffer) -> int:
|
||||
...
|
||||
def write(self, __buffer: ReadableBuffer) -> int: ...
|
||||
|
||||
|
||||
class SupportsWrite(Protocol[_T_contra]):
|
||||
def write(self, __s: _T_contra) -> Any:
|
||||
...
|
||||
def write(self, __s: _T_contra) -> Any: ...
|
||||
|
||||
|
||||
class SupportsRead(Protocol[_T_co]):
|
||||
def read(self, __length: int = ...) -> _T_co:
|
||||
...
|
||||
def read(self, __length: int = ...) -> _T_co: ...
|
||||
|
||||
|
||||
class BufferedReader:
|
||||
def read(self, __size: Optional[int] = ...) -> bytes:
|
||||
...
|
||||
def read(self, __size: Optional[int] = ...) -> bytes: ...
|
||||
|
||||
|
||||
def copyfileobj(
|
||||
fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...
|
||||
) -> AnyStr:
|
||||
...
|
||||
) -> AnyStr: ...
|
||||
|
||||
|
||||
def f(fr: BufferedReader, fw: BufferedWriter):
|
||||
|
@ -9,13 +9,11 @@ T = TypeVar("T")
|
||||
|
||||
|
||||
class Async:
|
||||
def fn(self, returnable: T) -> Awaitable[T]:
|
||||
...
|
||||
def fn(self, returnable: T) -> Awaitable[T]: ...
|
||||
|
||||
|
||||
class Sync:
|
||||
def fn(self, returnable: T) -> T:
|
||||
...
|
||||
def fn(self, returnable: T) -> T: ...
|
||||
|
||||
|
||||
T = TypeVar("T", Async, Sync)
|
||||
|
@ -42,8 +42,7 @@ archive_path = data_dir / "hello"
|
||||
shutil.rmtree(archive_path)
|
||||
|
||||
|
||||
def func1(a: AnyStr, b: AnyStr) -> None:
|
||||
...
|
||||
def func1(a: AnyStr, b: AnyStr) -> None: ...
|
||||
|
||||
|
||||
def func2(a: Union[str, bytes], b: Union[str, bytes]):
|
||||
@ -51,27 +50,22 @@ def func2(a: Union[str, bytes], b: Union[str, bytes]):
|
||||
func1(a, b)
|
||||
|
||||
|
||||
class A:
|
||||
...
|
||||
class A: ...
|
||||
|
||||
|
||||
class B:
|
||||
...
|
||||
class B: ...
|
||||
|
||||
|
||||
class C:
|
||||
...
|
||||
class C: ...
|
||||
|
||||
|
||||
class D:
|
||||
...
|
||||
class D: ...
|
||||
|
||||
|
||||
T3 = TypeVar("T3", A, B, Union[C, D])
|
||||
|
||||
|
||||
def do_something(value: T3) -> T3:
|
||||
...
|
||||
def do_something(value: T3) -> T3: ...
|
||||
|
||||
|
||||
def func10(value: Union[C, D]):
|
||||
|
@ -4,8 +4,7 @@
|
||||
from typing import Iterator, Optional, Sequence, TypeVar, Union
|
||||
|
||||
|
||||
def func0(a: Union[int, float]):
|
||||
...
|
||||
def func0(a: Union[int, float]): ...
|
||||
|
||||
|
||||
_T1 = TypeVar("_T1", int, float)
|
||||
@ -39,12 +38,10 @@ def func5(xs: Sequence[Optional[_T2]]) -> Iterator[_T2]:
|
||||
return func3(xs)
|
||||
|
||||
|
||||
class A:
|
||||
...
|
||||
class A: ...
|
||||
|
||||
|
||||
class B(A):
|
||||
...
|
||||
class B(A): ...
|
||||
|
||||
|
||||
_T4 = TypeVar("_T4", A, B)
|
||||
|
@ -10,8 +10,7 @@ _T = TypeVar("_T")
|
||||
|
||||
|
||||
class A(Iterator[_T_co]):
|
||||
def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]":
|
||||
...
|
||||
def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]": ...
|
||||
|
||||
def __next__(self) -> _T_co: ...
|
||||
|
||||
@ -22,8 +21,7 @@ def func1(iterable: Iterable[_T]) -> Iterator[tuple[_T, _T, _T]]:
|
||||
|
||||
|
||||
class B(Generic[_T_co]):
|
||||
def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]":
|
||||
...
|
||||
def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]": ...
|
||||
|
||||
|
||||
def func2(p1: list[dict]):
|
||||
|
@ -9,38 +9,32 @@ _M = TypeVar("_M")
|
||||
|
||||
|
||||
class A(Generic[_M, _N]):
|
||||
def __new__(cls, m: _M, n: _N) -> "A[_M, _N]":
|
||||
...
|
||||
def __new__(cls, m: _M, n: _N) -> "A[_M, _N]": ...
|
||||
|
||||
|
||||
a: A[Literal[3], Literal[4]] = A(3, 4)
|
||||
|
||||
|
||||
class B(Generic[_M, _N]):
|
||||
def __new__(cls, m: _M, n: _N) -> "B[_M, _N]":
|
||||
...
|
||||
def __new__(cls, m: _M, n: _N) -> "B[_M, _N]": ...
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
...
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
|
||||
|
||||
b: B[Literal[3], Literal[4]] = B(3, 4)
|
||||
|
||||
|
||||
class C(Generic[_M, _N]):
|
||||
def __new__(cls, m: _M, n: _N) -> "C[_M, _N]":
|
||||
...
|
||||
def __new__(cls, m: _M, n: _N) -> "C[_M, _N]": ...
|
||||
|
||||
def __init__(self, m: _M, n: _N) -> None:
|
||||
...
|
||||
def __init__(self, m: _M, n: _N) -> None: ...
|
||||
|
||||
|
||||
c: C[Literal[3], Literal[4]] = C(3, 4)
|
||||
|
||||
|
||||
class D(Generic[_M, _N]):
|
||||
def __new__(cls, m: _M, n: _N) -> Self:
|
||||
...
|
||||
def __new__(cls, m: _M, n: _N) -> Self: ...
|
||||
|
||||
|
||||
d: D[Literal[3], Literal[4]] = D(3, 4)
|
||||
|
@ -13,24 +13,21 @@ class A(Generic[T]):
|
||||
|
||||
|
||||
class B(Generic[T]):
|
||||
def __init__(self):
|
||||
...
|
||||
def __init__(self): ...
|
||||
|
||||
|
||||
class C(Generic[T]):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
return super().__new__(cls, *args, **kwargs)
|
||||
|
||||
def __init__(self):
|
||||
...
|
||||
def __init__(self): ...
|
||||
|
||||
|
||||
class D(Generic[T]):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
return super().__new__(cls, *args, **kwargs)
|
||||
|
||||
def __init__(self, a: T):
|
||||
...
|
||||
def __init__(self, a: T): ...
|
||||
|
||||
|
||||
class E(Generic[T]):
|
||||
|
@ -178,8 +178,7 @@ def s18():
|
||||
|
||||
|
||||
class Plant(Generic[_T1]):
|
||||
def __new__(cls, o: _T1) -> Self:
|
||||
...
|
||||
def __new__(cls, o: _T1) -> Self: ...
|
||||
|
||||
|
||||
plant: Plant[float] = Plant(0)
|
||||
|
@ -9,14 +9,11 @@ T = TypeVar("T", covariant=True)
|
||||
|
||||
|
||||
class A(Protocol[T]):
|
||||
def a(self) -> "A[Tuple[T]]":
|
||||
...
|
||||
def a(self) -> "A[Tuple[T]]": ...
|
||||
|
||||
def b(self) -> "A[Tuple[T]]":
|
||||
...
|
||||
def b(self) -> "A[Tuple[T]]": ...
|
||||
|
||||
def c(self) -> "T":
|
||||
...
|
||||
def c(self) -> "T": ...
|
||||
|
||||
|
||||
class B(Generic[T]):
|
||||
|
@ -72,20 +72,17 @@ def func1(obv: Container[T], default_value: T = None) -> None:
|
||||
obv.on_next(default_value)
|
||||
|
||||
|
||||
class A:
|
||||
...
|
||||
class A: ...
|
||||
|
||||
|
||||
T_A = TypeVar("T_A", bound=A)
|
||||
|
||||
|
||||
class B(Generic[T]):
|
||||
def __init__(self, c: Callable[[], T]):
|
||||
...
|
||||
def __init__(self, c: Callable[[], T]): ...
|
||||
|
||||
|
||||
def func2(cls: type[T_A] = A) -> Callable[[], T_A]:
|
||||
...
|
||||
def func2(cls: type[T_A] = A) -> Callable[[], T_A]: ...
|
||||
|
||||
|
||||
B(func2())
|
||||
|
@ -11,22 +11,18 @@ T = TypeVar("T", contravariant=True)
|
||||
S = TypeVar("S", contravariant=True)
|
||||
|
||||
|
||||
class ClassA(Generic[T]):
|
||||
...
|
||||
class ClassA(Generic[T]): ...
|
||||
|
||||
|
||||
class ClassB(Generic[S, T], ClassA[T]):
|
||||
...
|
||||
class ClassB(Generic[S, T], ClassA[T]): ...
|
||||
|
||||
|
||||
class ClassC(ClassB[S, T]):
|
||||
def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]:
|
||||
...
|
||||
def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]: ...
|
||||
|
||||
|
||||
class ClassD(ClassB[S, T]):
|
||||
def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]:
|
||||
...
|
||||
def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]: ...
|
||||
|
||||
|
||||
c = ClassA[int]()
|
||||
|
@ -29,3 +29,11 @@ def func1(t: type[TA]) -> TA: ...
|
||||
|
||||
b = B(func1, A)
|
||||
reveal_type(b, expected_text="B[(t: type[A]), A]")
|
||||
|
||||
|
||||
class C(Generic[TA]):
|
||||
def __init__(self, _type: type[TA]) -> None: ...
|
||||
|
||||
|
||||
c = B(C, A)
|
||||
reveal_type(c, expected_text="B[(_type: type[A]), C[A]]")
|
||||
|
@ -9,8 +9,7 @@ T_A = TypeVar("T_A", bound="A")
|
||||
|
||||
class A(ABC):
|
||||
@abstractmethod
|
||||
def some_method(self) -> str:
|
||||
...
|
||||
def some_method(self) -> str: ...
|
||||
|
||||
def some_factory_method_1(self):
|
||||
return type(self)()
|
||||
|
17
packages/pyright-internal/src/tests/samples/coroutines4.py
Normal file
17
packages/pyright-internal/src/tests/samples/coroutines4.py
Normal file
@ -0,0 +1,17 @@
|
||||
# This sample tests the case where an inner coroutine with an inferred
|
||||
# return type is referenced in a manner that results in recursion.
|
||||
|
||||
import asyncio
|
||||
|
||||
|
||||
def func1(replace_inner: bool) -> None:
|
||||
inner = lambda: None
|
||||
|
||||
async def wrapper():
|
||||
inner()
|
||||
|
||||
wrapped_fn = wrapper()
|
||||
asyncio.create_task(wrapped_fn)
|
||||
|
||||
if replace_inner:
|
||||
inner = lambda: None
|
@ -12,8 +12,9 @@ class IsDataclass(Protocol):
|
||||
__dataclass_fields__: ClassVar[dict[str, Any]]
|
||||
|
||||
|
||||
def dataclass_only(x: IsDataclass):
|
||||
... # do something that only makes sense with a dataclass
|
||||
def dataclass_only(
|
||||
x: IsDataclass,
|
||||
): ... # do something that only makes sense with a dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -7,12 +7,10 @@ from typing import Any, cast, overload
|
||||
|
||||
class MyDescriptor:
|
||||
@overload
|
||||
def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor":
|
||||
...
|
||||
def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor": ...
|
||||
|
||||
@overload
|
||||
def __get__(self, __obj: object, __owner: Any) -> int:
|
||||
...
|
||||
def __get__(self, __obj: object, __owner: Any) -> int: ...
|
||||
|
||||
def __get__(self, __obj: object | None, __owner: Any) -> "int | MyDescriptor":
|
||||
if __obj is None:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user