@@ -401,6 +401,7 @@ namespace ts {
401401 const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
402402 const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
403403 const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
404+ const resolvingSignaturesArray = [resolvingSignature];
404405
405406 const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
406407 const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
@@ -4024,6 +4025,10 @@ namespace ts {
40244025
40254026 function determineIfDeclarationIsVisible() {
40264027 switch (node.kind) {
4028+ case SyntaxKind.JSDocTypedefTag:
4029+ // Top-level jsdoc typedefs are considered exported
4030+ // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file
4031+ return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent));
40274032 case SyntaxKind.BindingElement:
40284033 return isDeclarationVisible(node.parent.parent);
40294034 case SyntaxKind.VariableDeclaration:
@@ -5163,8 +5168,8 @@ namespace ts {
51635168 let result: TypeParameter[];
51645169 for (const node of symbol.declarations) {
51655170 if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration ||
5166- node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration) {
5167- const declaration = <InterfaceDeclaration | TypeAliasDeclaration>node;
5171+ node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration || node.kind === SyntaxKind.JSDocTypedefTag ) {
5172+ const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag >node;
51685173 const typeParameters = getEffectiveTypeParameterDeclarations(declaration);
51695174 if (typeParameters) {
51705175 result = appendTypeParameters(result, typeParameters);
@@ -9046,7 +9051,7 @@ namespace ts {
90469051 }
90479052
90489053 function getAliasSymbolForTypeNode(node: TypeNode) {
9049- return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined;
9054+ return ( node.parent.kind === SyntaxKind.TypeAliasDeclaration || node.parent.kind === SyntaxKind.JSDocTypedefTag) ? getSymbolOfNode(node.parent) : undefined;
90509055 }
90519056
90529057 function getAliasTypeArgumentsForTypeNode(node: TypeNode) {
@@ -15355,8 +15360,17 @@ namespace ts {
1535515360 }
1535615361 }
1535715362
15358- if (context.typeArguments) {
15359- signatures = mapDefined(signatures, s => getJsxSignatureTypeArgumentInstantiation(s, context, isJs));
15363+ const links = getNodeLinks(context);
15364+ if (!links.resolvedSignatures) {
15365+ links.resolvedSignatures = createMap();
15366+ }
15367+ const cacheKey = "" + getTypeId(valueType);
15368+ if (links.resolvedSignatures.get(cacheKey) && links.resolvedSignatures.get(cacheKey) !== resolvingSignaturesArray) {
15369+ signatures = links.resolvedSignatures.get(cacheKey);
15370+ }
15371+ else if (!links.resolvedSignatures.get(cacheKey)) {
15372+ links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray);
15373+ links.resolvedSignatures.set(cacheKey, signatures = instantiateJsxSignatures(context, signatures));
1536015374 }
1536115375
1536215376 return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromClassType(t, isJs, context, /*reportErrors*/ false) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
@@ -16337,6 +16351,40 @@ namespace ts {
1633716351 return undefined;
1633816352 }
1633916353
16354+ function getInstantiatedJsxSignatures(openingLikeElement: JsxOpeningLikeElement, elementType: Type, reportErrors?: boolean) {
16355+ const links = getNodeLinks(openingLikeElement);
16356+ if (!links.resolvedSignatures) {
16357+ links.resolvedSignatures = createMap();
16358+ }
16359+ const cacheKey = "" + getTypeId(elementType);
16360+ if (links.resolvedSignatures.get(cacheKey) && links.resolvedSignatures.get(cacheKey) === resolvingSignaturesArray) {
16361+ return;
16362+ }
16363+ else if (links.resolvedSignatures.get(cacheKey)) {
16364+ return links.resolvedSignatures.get(cacheKey);
16365+ }
16366+
16367+ links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray);
16368+ // Resolve the signatures, preferring constructor
16369+ let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
16370+ if (signatures.length === 0) {
16371+ // No construct signatures, try call signatures
16372+ signatures = getSignaturesOfType(elementType, SignatureKind.Call);
16373+ if (signatures.length === 0) {
16374+ // We found no signatures at all, which is an error
16375+ if (reportErrors) {
16376+ error(openingLikeElement.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(openingLikeElement.tagName));
16377+ }
16378+ return;
16379+ }
16380+ }
16381+
16382+ // Instantiate in context of source type
16383+ const results = instantiateJsxSignatures(openingLikeElement, signatures);
16384+ links.resolvedSignatures.set(cacheKey, results);
16385+ return results;
16386+ }
16387+
1634016388 /**
1634116389 * Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType.
1634216390 * For instance:
@@ -16399,20 +16447,10 @@ namespace ts {
1639916447
1640016448 // Get the element instance type (the result of newing or invoking this tag)
1640116449
16402- // Resolve the signatures, preferring constructor
16403- let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
16404- if (signatures.length === 0) {
16405- // No construct signatures, try call signatures
16406- signatures = getSignaturesOfType(elementType, SignatureKind.Call);
16407- if (signatures.length === 0) {
16408- // We found no signatures at all, which is an error
16409- error(openingLikeElement.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(openingLikeElement.tagName));
16410- return unknownType;
16411- }
16450+ const instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, /*reportErrors*/ true);
16451+ if (!length(instantiatedSignatures)) {
16452+ return unknownType;
1641216453 }
16413-
16414- // Instantiate in context of source type
16415- const instantiatedSignatures = instantiateJsxSignatures(openingLikeElement, signatures);
1641616454 const elemInstanceType = getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
1641716455
1641816456 // If we should include all stateless attributes type, then get all attributes type from all stateless function signature.
@@ -18102,11 +18140,11 @@ namespace ts {
1810218140
1810318141 let typeArguments: NodeArray<TypeNode>;
1810418142
18105- if (!isDecorator && !isJsxOpeningOrSelfClosingElement ) {
18143+ if (!isDecorator) {
1810618144 typeArguments = (<CallExpression>node).typeArguments;
1810718145
1810818146 // We already perform checking on the type arguments on the class declaration itself.
18109- if (isTaggedTemplate || (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
18147+ if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
1811018148 forEach(typeArguments, checkSourceElement);
1811118149 }
1811218150 }
@@ -18695,30 +18733,6 @@ namespace ts {
1869518733 */
1869618734 function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined {
1869718735 Debug.assert(!(elementType.flags & TypeFlags.Union));
18698- return resolveStatelessJsxOpeningLikeElement(openingLikeElement, elementType, candidatesOutArray);
18699- }
18700-
18701- /**
18702- * Try treating a given opening-like element as stateless function component and resolve a tagName to a function signature.
18703- * @param openingLikeElement an JSX opening-like element we want to try resolve its stateless function if possible
18704- * @param elementType a type of the opening-like JSX element, a result of resolving tagName in opening-like element.
18705- * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
18706- * the function will fill it up with appropriate candidate signatures
18707- * @return a resolved signature if we can find function matching function signature through resolve call or a first signature in the list of functions.
18708- * otherwise return undefined if tag-name of the opening-like element doesn't have call signatures
18709- */
18710- function resolveStatelessJsxOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined {
18711- // If this function is called from language service, elementType can be a union type. This is not possible if the function is called from compiler (see: resolveCustomJsxElementAttributesType)
18712- if (elementType.flags & TypeFlags.Union) {
18713- const types = (elementType as UnionType).types;
18714- let result: Signature;
18715- for (const type of types) {
18716- result = result || resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray);
18717- }
18718-
18719- return result;
18720- }
18721-
1872218736 const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
1872318737 if (callSignatures && callSignatures.length > 0) {
1872418738 return resolveCall(openingLikeElement, callSignatures, candidatesOutArray);
@@ -18740,7 +18754,18 @@ namespace ts {
1874018754 case SyntaxKind.JsxOpeningElement:
1874118755 case SyntaxKind.JsxSelfClosingElement:
1874218756 // This code-path is called by language service
18743- return resolveStatelessJsxOpeningLikeElement(node, checkExpression(node.tagName), candidatesOutArray) || unknownSignature;
18757+ const exprTypes = checkExpression(node.tagName);
18758+ return forEachType(exprTypes, exprType => {
18759+ const sfcResult = getResolvedJsxStatelessFunctionSignature(node, exprType, candidatesOutArray);
18760+ if (sfcResult && sfcResult !== unknownSignature) {
18761+ return sfcResult;
18762+ }
18763+ const sigs = getInstantiatedJsxSignatures(node, exprType);
18764+ if (candidatesOutArray && length(sigs)) {
18765+ candidatesOutArray.push(...sigs);
18766+ }
18767+ return length(sigs) ? sigs[0] : unknownSignature;
18768+ }) || unknownSignature;
1874418769 }
1874518770 Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable.");
1874618771 }
0 commit comments