Mark as referenced aliases in Union that will get emitted as part of decorator metadaa

Fixes #13449
This commit is contained in:
Sheetal Nandi
2017-01-17 11:22:27 -08:00
parent b345a781d7
commit 839dde3cf2
7 changed files with 197 additions and 6 deletions
+68 -6
View File
@@ -16732,7 +16732,10 @@ namespace ts {
* marked as referenced to prevent import elision.
*/
function markTypeNodeAsReferenced(node: TypeNode) {
const typeName = node && getEntityNameFromTypeNode(node);
markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node));
}
function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression) {
const rootName = typeName && getFirstIdentifier(typeName);
const rootSymbol = rootName && resolveName(rootName, rootName.text, (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
if (rootSymbol
@@ -16743,6 +16746,65 @@ namespace ts {
}
}
function markDecoratorMedataDataTypeNodeAsReferenced(node: TypeNode): void {
const entityNameOrToken = getEntityNameForDecoratoryMetadata(node);
if (entityNameOrToken && isEntityName(entityNameOrToken)) {
markEntityNameOrEntityExpressionAsReference(entityNameOrToken);
}
}
type voidUndefinedNullOrNeverTypeNode = Token<SyntaxKind.VoidKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.NullKeyword | SyntaxKind.NeverKeyword>;
function getEntityNameForDecoratoryMetadata(node: TypeNode): EntityName | voidUndefinedNullOrNeverTypeNode {
if (node) {
switch (node.kind) {
case SyntaxKind.IntersectionType:
case SyntaxKind.UnionType:
let commonEntityName: EntityName | voidUndefinedNullOrNeverTypeNode;
for (const typeNode of (<UnionOrIntersectionTypeNode>node).types) {
const individualEntityName = getEntityNameForDecoratoryMetadata(typeNode);
if (!individualEntityName) {
// Individual is something like string number
// So it would be serialized to either that type or object
// Safe to return here
return undefined;
}
const isCommonEntityName = commonEntityName && isEntityName(commonEntityName);
const isIndividualEntityName = isEntityName(individualEntityName);
if (isCommonEntityName && isIndividualEntityName) {
// Note this is in sync with the transformation that happens for type node.
// Keep this in sync with serializeUnionOrIntersectionType
// Verify if they refer to same entity and is identifier
// return undefined if they dont match because we would emit object
if (!isIdentifier(commonEntityName) ||
!isIdentifier(individualEntityName) ||
commonEntityName.text !== individualEntityName.text) {
return undefined;
}
}
else if (!isCommonEntityName) {
commonEntityName = individualEntityName;
}
}
return commonEntityName;
case SyntaxKind.ParenthesizedType:
return getEntityNameForDecoratoryMetadata((<ParenthesizedTypeNode>node).type);
case SyntaxKind.TypeReference:
return (<TypeReferenceNode>node).typeName;
case SyntaxKind.VoidKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.NeverKeyword:
return <voidUndefinedNullOrNeverTypeNode>node;
}
}
}
function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode {
return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type;
}
@@ -16778,7 +16840,7 @@ namespace ts {
const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
if (constructor) {
for (const parameter of constructor.parameters) {
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
}
}
break;
@@ -16787,17 +16849,17 @@ namespace ts {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
}
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
markDecoratorMedataDataTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
break;
case SyntaxKind.PropertyDeclaration:
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
break;
case SyntaxKind.Parameter:
markTypeNodeAsReferenced((<PropertyDeclaration>node).type);
markDecoratorMedataDataTypeNodeAsReferenced((<PropertyDeclaration>node).type);
break;
}
}
+2
View File
@@ -1739,6 +1739,8 @@ namespace ts {
}
function serializeUnionOrIntersectionType(node: UnionOrIntersectionTypeNode): SerializedTypeNode {
// Note when updating logic here also update getEntityNameForDecoratoryMetadata
// so that aliases can be marked as referenced
let serializedUnion: SerializedTypeNode;
for (const typeNode of node.types) {
const serializedIndividual = serializeTypeNode(typeNode);