@@ -401,6 +401,7 @@ namespace ts {
401
401
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
402
402
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
403
403
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
404
+ const resolvingSignaturesArray = [resolvingSignature];
404
405
405
406
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
406
407
const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
@@ -4024,6 +4025,10 @@ namespace ts {
4024
4025
4025
4026
function determineIfDeclarationIsVisible() {
4026
4027
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));
4027
4032
case SyntaxKind.BindingElement:
4028
4033
return isDeclarationVisible(node.parent.parent);
4029
4034
case SyntaxKind.VariableDeclaration:
@@ -5163,8 +5168,8 @@ namespace ts {
5163
5168
let result: TypeParameter[];
5164
5169
for (const node of symbol.declarations) {
5165
5170
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;
5168
5173
const typeParameters = getEffectiveTypeParameterDeclarations(declaration);
5169
5174
if (typeParameters) {
5170
5175
result = appendTypeParameters(result, typeParameters);
@@ -9046,7 +9051,7 @@ namespace ts {
9046
9051
}
9047
9052
9048
9053
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;
9050
9055
}
9051
9056
9052
9057
function getAliasTypeArgumentsForTypeNode(node: TypeNode) {
@@ -15355,8 +15360,17 @@ namespace ts {
15355
15360
}
15356
15361
}
15357
15362
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));
15360
15374
}
15361
15375
15362
15376
return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromClassType(t, isJs, context, /*reportErrors*/ false) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
@@ -16337,6 +16351,40 @@ namespace ts {
16337
16351
return undefined;
16338
16352
}
16339
16353
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
+
16340
16388
/**
16341
16389
* Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType.
16342
16390
* For instance:
@@ -16399,20 +16447,10 @@ namespace ts {
16399
16447
16400
16448
// Get the element instance type (the result of newing or invoking this tag)
16401
16449
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;
16412
16453
}
16413
-
16414
- // Instantiate in context of source type
16415
- const instantiatedSignatures = instantiateJsxSignatures(openingLikeElement, signatures);
16416
16454
const elemInstanceType = getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
16417
16455
16418
16456
// If we should include all stateless attributes type, then get all attributes type from all stateless function signature.
@@ -18102,11 +18140,11 @@ namespace ts {
18102
18140
18103
18141
let typeArguments: NodeArray<TypeNode>;
18104
18142
18105
- if (!isDecorator && !isJsxOpeningOrSelfClosingElement ) {
18143
+ if (!isDecorator) {
18106
18144
typeArguments = (<CallExpression>node).typeArguments;
18107
18145
18108
18146
// 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) {
18110
18148
forEach(typeArguments, checkSourceElement);
18111
18149
}
18112
18150
}
@@ -18695,30 +18733,6 @@ namespace ts {
18695
18733
*/
18696
18734
function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined {
18697
18735
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
-
18722
18736
const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
18723
18737
if (callSignatures && callSignatures.length > 0) {
18724
18738
return resolveCall(openingLikeElement, callSignatures, candidatesOutArray);
@@ -18740,7 +18754,18 @@ namespace ts {
18740
18754
case SyntaxKind.JsxOpeningElement:
18741
18755
case SyntaxKind.JsxSelfClosingElement:
18742
18756
// 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;
18744
18769
}
18745
18770
Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable.");
18746
18771
}
0 commit comments