mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Report circular JSDoc type references (#27404)
JSDoc types references can often be to values, which can often be circular in ways that types tied to declarations cannot. I decided to create a separate property on SymbolLinks rather than reusing declaredType, although I'm not sure that's strictly required.
This commit is contained in:
@@ -666,6 +666,7 @@ namespace ts {
|
||||
ResolvedReturnType,
|
||||
ImmediateBaseConstraint,
|
||||
EnumTagType,
|
||||
JSDocTypeReference,
|
||||
}
|
||||
|
||||
const enum CheckMode {
|
||||
@@ -4503,6 +4504,8 @@ namespace ts {
|
||||
return !!(<Signature>target).resolvedReturnType;
|
||||
case TypeSystemPropertyName.ImmediateBaseConstraint:
|
||||
return !!(<Type>target).immediateBaseConstraint;
|
||||
case TypeSystemPropertyName.JSDocTypeReference:
|
||||
return !!getSymbolLinks(target as Symbol).resolvedJSDocType;
|
||||
}
|
||||
return Debug.assertNever(propertyName);
|
||||
}
|
||||
@@ -8275,7 +8278,7 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
// JS are 'string' or 'number', not an enum type.
|
||||
// JS enums are 'string' or 'number', not an enum type.
|
||||
const enumTag = isInJSFile(node) && symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
|
||||
if (enumTag) {
|
||||
const links = getNodeLinks(enumTag);
|
||||
@@ -8318,12 +8321,21 @@ namespace ts {
|
||||
* the type of this reference is just the type of the value we resolved to.
|
||||
*/
|
||||
function getJSDocTypeReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.JSDocTypeReference)) {
|
||||
return errorType;
|
||||
}
|
||||
const assignedType = getAssignedClassType(symbol);
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
const referenceType = valueType.symbol && valueType.symbol !== symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
|
||||
if (!popTypeResolution()) {
|
||||
getSymbolLinks(symbol).resolvedJSDocType = errorType;
|
||||
error(node, Diagnostics.JSDoc_type_0_circularly_references_itself, symbolToString(symbol));
|
||||
return errorType;
|
||||
}
|
||||
if (referenceType || assignedType) {
|
||||
// TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?)
|
||||
return (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType)!;
|
||||
const type = (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType)!;
|
||||
return getSymbolLinks(symbol).resolvedJSDocType = type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8460,7 +8472,7 @@ namespace ts {
|
||||
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning);
|
||||
type = getTypeReferenceType(node, symbol);
|
||||
}
|
||||
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
|
||||
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed when we check the
|
||||
// type reference in checkTypeReferenceNode.
|
||||
links.resolvedSymbol = symbol;
|
||||
links.resolvedType = type;
|
||||
|
||||
@@ -2116,6 +2116,10 @@
|
||||
"category": "Error",
|
||||
"code": 2586
|
||||
},
|
||||
"JSDoc type '{0}' circularly references itself.": {
|
||||
"category": "Error",
|
||||
"code": 2587
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -4684,4 +4688,4 @@
|
||||
"category": "Message",
|
||||
"code": 95068
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3536,6 +3536,7 @@ namespace ts {
|
||||
type?: Type; // Type of value symbol
|
||||
uniqueESSymbolType?: Type; // UniqueESSymbol type for a symbol
|
||||
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
|
||||
resolvedJSDocType?: Type; // Resolved type of a JSDoc type reference
|
||||
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
|
||||
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
|
||||
inferredClassType?: Type; // Type of an inferred ES5 class
|
||||
|
||||
Reference in New Issue
Block a user