Merge branch 'master' of github.com:Microsoft/TypeScript

This commit is contained in:
Wesley Wigham
2018-05-16 13:11:36 -07:00
12 changed files with 348 additions and 199 deletions

View File

@@ -401,6 +401,7 @@ namespace ts {
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignaturesArray = [resolvingSignature];
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
@@ -4024,6 +4025,10 @@ namespace ts {
function determineIfDeclarationIsVisible() {
switch (node.kind) {
case SyntaxKind.JSDocTypedefTag:
// Top-level jsdoc typedefs are considered exported
// 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
return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent));
case SyntaxKind.BindingElement:
return isDeclarationVisible(node.parent.parent);
case SyntaxKind.VariableDeclaration:
@@ -5163,8 +5168,8 @@ namespace ts {
let result: TypeParameter[];
for (const node of symbol.declarations) {
if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration ||
node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration) {
const declaration = <InterfaceDeclaration | TypeAliasDeclaration>node;
node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration || node.kind === SyntaxKind.JSDocTypedefTag) {
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag>node;
const typeParameters = getEffectiveTypeParameterDeclarations(declaration);
if (typeParameters) {
result = appendTypeParameters(result, typeParameters);
@@ -9046,7 +9051,7 @@ namespace ts {
}
function getAliasSymbolForTypeNode(node: TypeNode) {
return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined;
return (node.parent.kind === SyntaxKind.TypeAliasDeclaration || node.parent.kind === SyntaxKind.JSDocTypedefTag) ? getSymbolOfNode(node.parent) : undefined;
}
function getAliasTypeArgumentsForTypeNode(node: TypeNode) {
@@ -15355,8 +15360,17 @@ namespace ts {
}
}
if (context.typeArguments) {
signatures = mapDefined(signatures, s => getJsxSignatureTypeArgumentInstantiation(s, context, isJs));
const links = getNodeLinks(context);
if (!links.resolvedSignatures) {
links.resolvedSignatures = createMap();
}
const cacheKey = "" + getTypeId(valueType);
if (links.resolvedSignatures.get(cacheKey) && links.resolvedSignatures.get(cacheKey) !== resolvingSignaturesArray) {
signatures = links.resolvedSignatures.get(cacheKey);
}
else if (!links.resolvedSignatures.get(cacheKey)) {
links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray);
links.resolvedSignatures.set(cacheKey, signatures = instantiateJsxSignatures(context, signatures));
}
return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromClassType(t, isJs, context, /*reportErrors*/ false) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
@@ -16337,6 +16351,40 @@ namespace ts {
return undefined;
}
function getInstantiatedJsxSignatures(openingLikeElement: JsxOpeningLikeElement, elementType: Type, reportErrors?: boolean) {
const links = getNodeLinks(openingLikeElement);
if (!links.resolvedSignatures) {
links.resolvedSignatures = createMap();
}
const cacheKey = "" + getTypeId(elementType);
if (links.resolvedSignatures.get(cacheKey) && links.resolvedSignatures.get(cacheKey) === resolvingSignaturesArray) {
return;
}
else if (links.resolvedSignatures.get(cacheKey)) {
return links.resolvedSignatures.get(cacheKey);
}
links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray);
// Resolve the signatures, preferring constructor
let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
if (signatures.length === 0) {
// No construct signatures, try call signatures
signatures = getSignaturesOfType(elementType, SignatureKind.Call);
if (signatures.length === 0) {
// We found no signatures at all, which is an error
if (reportErrors) {
error(openingLikeElement.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(openingLikeElement.tagName));
}
return;
}
}
// Instantiate in context of source type
const results = instantiateJsxSignatures(openingLikeElement, signatures);
links.resolvedSignatures.set(cacheKey, results);
return results;
}
/**
* Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType.
* For instance:
@@ -16399,20 +16447,10 @@ namespace ts {
// Get the element instance type (the result of newing or invoking this tag)
// Resolve the signatures, preferring constructor
let signatures = getSignaturesOfType(elementType, SignatureKind.Construct);
if (signatures.length === 0) {
// No construct signatures, try call signatures
signatures = getSignaturesOfType(elementType, SignatureKind.Call);
if (signatures.length === 0) {
// We found no signatures at all, which is an error
error(openingLikeElement.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(openingLikeElement.tagName));
return unknownType;
}
const instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, /*reportErrors*/ true);
if (!length(instantiatedSignatures)) {
return unknownType;
}
// Instantiate in context of source type
const instantiatedSignatures = instantiateJsxSignatures(openingLikeElement, signatures);
const elemInstanceType = getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
// If we should include all stateless attributes type, then get all attributes type from all stateless function signature.
@@ -18102,11 +18140,11 @@ namespace ts {
let typeArguments: NodeArray<TypeNode>;
if (!isDecorator && !isJsxOpeningOrSelfClosingElement) {
if (!isDecorator) {
typeArguments = (<CallExpression>node).typeArguments;
// We already perform checking on the type arguments on the class declaration itself.
if (isTaggedTemplate || (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
forEach(typeArguments, checkSourceElement);
}
}
@@ -18695,30 +18733,6 @@ namespace ts {
*/
function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined {
Debug.assert(!(elementType.flags & TypeFlags.Union));
return resolveStatelessJsxOpeningLikeElement(openingLikeElement, elementType, candidatesOutArray);
}
/**
* Try treating a given opening-like element as stateless function component and resolve a tagName to a function signature.
* @param openingLikeElement an JSX opening-like element we want to try resolve its stateless function if possible
* @param elementType a type of the opening-like JSX element, a result of resolving tagName in opening-like element.
* @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
* the function will fill it up with appropriate candidate signatures
* @return a resolved signature if we can find function matching function signature through resolve call or a first signature in the list of functions.
* otherwise return undefined if tag-name of the opening-like element doesn't have call signatures
*/
function resolveStatelessJsxOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined {
// 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)
if (elementType.flags & TypeFlags.Union) {
const types = (elementType as UnionType).types;
let result: Signature;
for (const type of types) {
result = result || resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray);
}
return result;
}
const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call);
if (callSignatures && callSignatures.length > 0) {
return resolveCall(openingLikeElement, callSignatures, candidatesOutArray);
@@ -18740,7 +18754,18 @@ namespace ts {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
// This code-path is called by language service
return resolveStatelessJsxOpeningLikeElement(node, checkExpression(node.tagName), candidatesOutArray) || unknownSignature;
const exprTypes = checkExpression(node.tagName);
return forEachType(exprTypes, exprType => {
const sfcResult = getResolvedJsxStatelessFunctionSignature(node, exprType, candidatesOutArray);
if (sfcResult && sfcResult !== unknownSignature) {
return sfcResult;
}
const sigs = getInstantiatedJsxSignatures(node, exprType);
if (candidatesOutArray && length(sigs)) {
candidatesOutArray.push(...sigs);
}
return length(sigs) ? sigs[0] : unknownSignature;
}) || unknownSignature;
}
Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable.");
}

View File

@@ -3625,6 +3625,7 @@ namespace ts {
flags?: NodeCheckFlags; // Set of flags specific to Node
resolvedType?: Type; // Cached type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSignatures?: Map<Signature[]>; // Cached signatures of jsx node
resolvedSymbol?: Symbol; // Cached name resolution result
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate

View File

@@ -3093,11 +3093,13 @@ namespace ts {
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*/
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters) {
return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined);
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters | JSDocTypedefTag) {
return isJSDocTypedefTag(node)
? getJSDocTypeParameterDeclarations(node)
: node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined);
}
export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters) {
export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters | JSDocTypedefTag) {
const templateTag = getJSDocTemplateTag(node);
return templateTag && templateTag.typeParameters;
}