-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Enable TypeForm support by default #11412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0fee2d8
b310584
43adeea
7233033
7e27e4c
b87b75f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1117,10 +1117,7 @@ export function createTypeEvaluator( | |
|
|
||
| if (isAny(anySpecialForm)) { | ||
| TypeBase.setSpecialForm(anySpecialForm, anyClass); | ||
|
|
||
| if (isTypeFormSupported(node)) { | ||
| TypeBase.setTypeForm(anySpecialForm, convertToInstance(anySpecialForm)); | ||
| } | ||
| TypeBase.setTypeForm(anySpecialForm, convertToInstance(anySpecialForm)); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1314,7 +1311,7 @@ export function createTypeEvaluator( | |
| expectingInstantiable = false; | ||
| } | ||
|
|
||
| typeResult = getTypeOfStringList(node, flags); | ||
| typeResult = getTypeOfStringList(node, flags, inferenceContext); | ||
| break; | ||
| } | ||
|
|
||
|
|
@@ -1656,7 +1653,11 @@ export function createTypeEvaluator( | |
| return typeResult; | ||
| } | ||
|
|
||
| function getTypeOfStringList(node: StringListNode, flags: EvalFlags): TypeResult { | ||
| function getTypeOfStringList( | ||
| node: StringListNode, | ||
| flags: EvalFlags, | ||
| inferenceContext?: InferenceContext | ||
| ): TypeResult { | ||
| let typeResult: TypeResult | undefined; | ||
|
|
||
| if ((flags & EvalFlags.StrLiteralAsType) !== 0 && (flags & EvalFlags.TypeFormArg) === 0) { | ||
|
|
@@ -1743,11 +1744,15 @@ export function createTypeEvaluator( | |
| }; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copilot generated: [verified] |
||
| } | ||
|
|
||
| if ( | ||
| node.d.strings.length !== 1 || | ||
| node.d.strings[0].nodeType !== ParseNodeType.String || | ||
| !isTypeFormSupported(node) | ||
| ) { | ||
| // Only attempt to interpret the string as a TypeForm forward reference when | ||
| // there's a signal that a TypeForm value is wanted in this context. Doing it | ||
| // unconditionally can trigger expensive (and recursion-prone) type lookups | ||
| // for plain string literals in non-type contexts. | ||
| const wantsTypeForm = | ||
| (flags & EvalFlags.TypeFormArg) !== 0 || | ||
| (inferenceContext !== undefined && expectedTypeWantsTypeForm(inferenceContext.expectedType)); | ||
|
|
||
| if (node.d.strings.length !== 1 || node.d.strings[0].nodeType !== ParseNodeType.String || !wantsTypeForm) { | ||
| return typeResult; | ||
| } | ||
|
|
||
|
|
@@ -5014,10 +5019,6 @@ export function createTypeEvaluator( | |
| } | ||
|
|
||
| function addTypeFormForSymbol(node: ExpressionNode, type: Type, flags: EvalFlags, includesVarDecl: boolean): Type { | ||
| if (!isTypeFormSupported(node)) { | ||
| return type; | ||
| } | ||
|
|
||
| const isValid = isSymbolValidTypeExpression(type, includesVarDecl); | ||
|
|
||
| // If the type already has type information associated with it, don't replace. | ||
|
|
@@ -7659,9 +7660,7 @@ export function createTypeEvaluator( | |
| typeArgs: aliasTypeArgs, | ||
| }); | ||
|
|
||
| if (isTypeFormSupported(node)) { | ||
| type = TypeBase.cloneWithTypeForm(type, reportedError ? undefined : convertToInstance(type)); | ||
| } | ||
| type = TypeBase.cloneWithTypeForm(type, reportedError ? undefined : convertToInstance(type)); | ||
|
|
||
| if (baseType.props?.typeAliasInfo) { | ||
| return { type, node }; | ||
|
|
@@ -8832,7 +8831,7 @@ export function createTypeEvaluator( | |
| } | ||
|
|
||
| const typeFormResult = getTypeOfArgExpectingType(convertNodeToArg(node.d.args[0]), { | ||
| typeFormArg: isTypeFormSupported(node), | ||
| typeFormArg: true, | ||
| noNonTypeSpecialForms: true, | ||
| typeExpression: true, | ||
| }); | ||
|
|
@@ -13852,9 +13851,7 @@ export function createTypeEvaluator( | |
| ? prefetched.noneTypeClass | ||
| : convertToInstance(prefetched.noneTypeClass); | ||
|
|
||
| if (isTypeFormSupported(node)) { | ||
| type = TypeBase.cloneWithTypeForm(type, convertToInstance(type)); | ||
| } | ||
| type = TypeBase.cloneWithTypeForm(type, convertToInstance(type)); | ||
| } | ||
| } else if ( | ||
| node.d.constType === KeywordType.True || | ||
|
|
@@ -15738,7 +15735,7 @@ export function createTypeEvaluator( | |
| FunctionType.addParamSpecVariadics(functionType, convertToInstance(paramSpec)); | ||
| } | ||
|
|
||
| if (isTypeFormSupported(errorNode) && isValidTypeForm) { | ||
| if (isValidTypeForm) { | ||
| functionType = TypeBase.cloneWithTypeForm(functionType, convertToInstance(functionType)); | ||
| } | ||
|
|
||
|
|
@@ -15954,7 +15951,7 @@ export function createTypeEvaluator( | |
| result = TypeBase.cloneAsSpecialForm(result, ClassType.cloneAsInstance(prefetched.unionTypeClass)); | ||
| } | ||
|
|
||
| if (isTypeFormSupported(node) && isValidTypeForm) { | ||
| if (isValidTypeForm) { | ||
| result = TypeBase.cloneWithTypeForm(result, convertToInstance(result)); | ||
| } | ||
|
|
||
|
|
@@ -16025,9 +16022,7 @@ export function createTypeEvaluator( | |
| }); | ||
| let resultType = ClassType.specialize(classType, convertedTypeArgs); | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
| } | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
|
|
||
| return resultType; | ||
| } | ||
|
|
@@ -16059,9 +16054,7 @@ export function createTypeEvaluator( | |
|
|
||
| let resultType = ClassType.specialize(classType, convertedTypeArgs); | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
| } | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
|
|
||
| return resultType; | ||
| } | ||
|
|
@@ -16664,7 +16657,7 @@ export function createTypeEvaluator( | |
| if (unionType.props?.typeForm) { | ||
| unionType = TypeBase.cloneWithTypeForm(unionType, undefined); | ||
| } | ||
| } else if (isTypeFormSupported(errorNode)) { | ||
| } else { | ||
| const typeFormType = combineTypes(types.map((t) => t.props!.typeForm!)); | ||
| unionType = TypeBase.cloneWithTypeForm(unionType, typeFormType); | ||
| } | ||
|
|
@@ -17025,9 +17018,7 @@ export function createTypeEvaluator( | |
| specialType.shared.baseClasses.push(prefetched?.strClass ?? AnyType.create()); | ||
| computeMroLinearization(specialType); | ||
|
|
||
| if (isTypeFormSupported(node)) { | ||
| specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); | ||
| } | ||
| specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); | ||
| } | ||
|
|
||
| // Handle 'Never' and 'NoReturn' specially. | ||
|
|
@@ -17037,9 +17028,7 @@ export function createTypeEvaluator( | |
| specialType | ||
| ); | ||
|
|
||
| if (isTypeFormSupported(node)) { | ||
| specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); | ||
| } | ||
| specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); | ||
| } | ||
|
|
||
| writeTypeCache(node, { type: specialType }, EvalFlags.None); | ||
|
|
@@ -21244,9 +21233,7 @@ export function createTypeEvaluator( | |
|
|
||
| let resultType = aliasedName === 'Never' ? NeverType.createNever() : NeverType.createNoReturn(); | ||
| resultType = TypeBase.cloneAsSpecialForm(resultType, classType); | ||
| if (isTypeFormSupported(errorNode)) { | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
| } | ||
| resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); | ||
|
|
||
| return { type: resultType }; | ||
| } | ||
|
|
@@ -21268,9 +21255,7 @@ export function createTypeEvaluator( | |
| typeType = explodeGenericClass(typeType); | ||
| } | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); | ||
| } | ||
| typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); | ||
|
|
||
| return { type: typeType }; | ||
| } | ||
|
|
@@ -21430,9 +21415,7 @@ export function createTypeEvaluator( | |
| typeType = explodeGenericClass(typeType); | ||
| } | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); | ||
| } | ||
| typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); | ||
|
|
||
| return { type: typeType }; | ||
| } | ||
|
|
@@ -21449,12 +21432,7 @@ export function createTypeEvaluator( | |
| /* isSpecialForm */ false | ||
| ); | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| specializedClass = TypeBase.cloneWithTypeForm( | ||
| specializedClass, | ||
| convertToInstance(specializedClass) | ||
| ); | ||
| } | ||
| specializedClass = TypeBase.cloneWithTypeForm(specializedClass, convertToInstance(specializedClass)); | ||
|
|
||
| return { type: specializedClass }; | ||
| } | ||
|
|
@@ -21715,12 +21693,10 @@ export function createTypeEvaluator( | |
|
|
||
| let specializedClass = ClassType.specialize(classType, typeArgTypes, typeArgs !== undefined); | ||
|
|
||
| if (isTypeFormSupported(errorNode)) { | ||
| specializedClass = TypeBase.cloneWithTypeForm( | ||
| specializedClass, | ||
| isValidTypeForm ? convertToInstance(specializedClass) : undefined | ||
| ); | ||
| } | ||
| specializedClass = TypeBase.cloneWithTypeForm( | ||
| specializedClass, | ||
| isValidTypeForm ? convertToInstance(specializedClass) : undefined | ||
| ); | ||
|
|
||
| return { type: specializedClass }; | ||
| } | ||
|
|
@@ -25598,6 +25574,16 @@ export function createTypeEvaluator( | |
| return isAssignable; | ||
| } | ||
|
|
||
| function expectedTypeWantsTypeForm(expectedType: Type): boolean { | ||
| let result = false; | ||
| doForEachSubtype(expectedType, (subtype) => { | ||
| if (isClassInstance(subtype) && ClassType.isBuiltIn(subtype, 'TypeForm')) { | ||
| result = true; | ||
| } | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| // If the expected type is an explicit TypeForm type, see if the source | ||
| // type has an implicit TypeForm type that can be assigned to it. If so, | ||
| // convert to an explicit TypeForm type. | ||
|
|
@@ -28701,13 +28687,6 @@ export function createTypeEvaluator( | |
| return { sourceType: simpleSrcType, destType: simpleDestType }; | ||
| } | ||
|
|
||
| function isTypeFormSupported(node: ParseNode) { | ||
|
rchiodo marked this conversation as resolved.
|
||
| const fileInfo = AnalyzerNodeInfo.getFileInfo(node); | ||
|
|
||
| // For now, enable only if enableExperimentalFeatures is true. | ||
| return fileInfo.diagnosticRuleSet.enableExperimentalFeatures; | ||
| } | ||
|
|
||
| function printType(type: Type, options?: PrintTypeOptions): string { | ||
| let flags = evaluatorOptions.printTypeFlags; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Misspelling in commit message: "current interence context" -> "current inference context"