Merge pull request #3690 from Microsoft/moveTypeSerializationToEmitter
Move type serialization to emitter
This commit is contained in:
commit
a78421fea0
|
@ -876,7 +876,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Resolves a qualified name and any involved aliases
|
||||
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags): Symbol {
|
||||
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean): Symbol {
|
||||
if (nodeIsMissing(name)) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -885,7 +885,7 @@ namespace ts {
|
|||
if (name.kind === SyntaxKind.Identifier) {
|
||||
let message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0;
|
||||
|
||||
symbol = resolveName(name, (<Identifier>name).text, meaning, message, <Identifier>name);
|
||||
symbol = resolveName(name, (<Identifier>name).text, meaning, ignoreErrors ? undefined : message, <Identifier>name);
|
||||
if (!symbol) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -894,13 +894,15 @@ namespace ts {
|
|||
let left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression>name).expression;
|
||||
let right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
|
||||
|
||||
let namespace = resolveEntityName(left, SymbolFlags.Namespace);
|
||||
let namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
|
||||
if (!namespace || namespace === unknownSymbol || nodeIsMissing(right)) {
|
||||
return undefined;
|
||||
}
|
||||
symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
|
||||
if (!symbol) {
|
||||
error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right));
|
||||
if (!ignoreErrors) {
|
||||
error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -2486,10 +2488,6 @@ namespace ts {
|
|||
return links.type;
|
||||
}
|
||||
|
||||
function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode {
|
||||
return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
|
||||
}
|
||||
|
||||
function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type {
|
||||
if (accessor) {
|
||||
if (accessor.kind === SyntaxKind.GetAccessor) {
|
||||
|
@ -3381,6 +3379,15 @@ namespace ts {
|
|||
return getSignaturesOfStructuredType(getApparentType(type), kind);
|
||||
}
|
||||
|
||||
function typeHasConstructSignatures(type: Type): boolean {
|
||||
let apparentType = getApparentType(type);
|
||||
if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
return resolved.constructSignatures.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function typeHasCallOrConstructSignatures(type: Type): boolean {
|
||||
let apparentType = getApparentType(type);
|
||||
if (apparentType.flags & TypeFlags.StructuredType) {
|
||||
|
@ -6765,7 +6772,7 @@ namespace ts {
|
|||
let restArrayType = checkExpression((<SpreadElementExpression>e).expression, contextualMapper);
|
||||
let restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
|
||||
(languageVersion >= ScriptTarget.ES6 ? getElementTypeOfIterable(restArrayType, /*errorNode*/ undefined) : undefined);
|
||||
if (restElementType) {
|
||||
if (restElementType) {
|
||||
elementTypes.push(restElementType);
|
||||
}
|
||||
}
|
||||
|
@ -8012,8 +8019,8 @@ namespace ts {
|
|||
return args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Returns the effective argument count for a node that works like a function invocation.
|
||||
* If 'node' is a Decorator, the number of arguments is derived from the decoration
|
||||
* target and the signature:
|
||||
|
@ -8090,11 +8097,11 @@ namespace ts {
|
|||
let classSymbol = getSymbolOfNode(node);
|
||||
return getTypeOfSymbol(classSymbol);
|
||||
}
|
||||
|
||||
|
||||
// fall-through
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// For a property or method decorator, the `target` is the
|
||||
|
@ -8137,14 +8144,14 @@ namespace ts {
|
|||
// For a constructor parameter decorator, the `propertyKey` will be `undefined`.
|
||||
return anyType;
|
||||
}
|
||||
|
||||
|
||||
// For a non-constructor parameter decorator, the `propertyKey` will be either
|
||||
// a string or a symbol, based on the name of the parameter's containing method.
|
||||
|
||||
// fall-through
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// The `propertyKey` for a property or method decorator will be a
|
||||
|
@ -8172,8 +8179,8 @@ namespace ts {
|
|||
return unknownType;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
|
||||
default:
|
||||
Debug.fail("Unsupported decorator target.");
|
||||
return unknownType;
|
||||
}
|
||||
|
@ -10981,13 +10988,10 @@ namespace ts {
|
|||
// as if it were an expression so that we can emit the type in a value position when we
|
||||
// serialize the type metadata.
|
||||
if (node && node.kind === SyntaxKind.TypeReference) {
|
||||
let type = getTypeFromTypeNode(node);
|
||||
let shouldCheckIfUnknownType = type === unknownType && compilerOptions.isolatedModules;
|
||||
if (!type || (!shouldCheckIfUnknownType && type.flags & (TypeFlags.Intrinsic | TypeFlags.NumberLike | TypeFlags.StringLike))) {
|
||||
return;
|
||||
}
|
||||
if (shouldCheckIfUnknownType || type.symbol.valueDeclaration) {
|
||||
checkExpression((<TypeReferenceNode>node).typeName);
|
||||
let root = getFirstIdentifier((<TypeReferenceNode>node).typeName);
|
||||
let rootSymbol = resolveName(root, root.text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
|
||||
markAliasSymbolAsReferenced(rootSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11459,19 +11463,19 @@ namespace ts {
|
|||
forEach(node.declarationList.declarations, checkSourceElement);
|
||||
}
|
||||
|
||||
function checkGrammarDisallowedModifiersOnObjectLiteralExpressionMethod(node: Node) {
|
||||
function checkGrammarDisallowedModifiersOnObjectLiteralExpressionMethod(node: Node) {
|
||||
// We only disallow modifier on a method declaration if it is a property of object-literal-expression
|
||||
if (node.modifiers && node.parent.kind === SyntaxKind.ObjectLiteralExpression){
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
if (node.modifiers.length > 1) {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkExpressionStatement(node: ExpressionStatement) {
|
||||
// Grammar checking
|
||||
|
@ -12812,7 +12816,7 @@ namespace ts {
|
|||
Debug.assert(node.kind === SyntaxKind.Identifier);
|
||||
return <Identifier>node;
|
||||
}
|
||||
|
||||
|
||||
function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
|
||||
let moduleName = getExternalModuleName(node);
|
||||
if (!nodeIsMissing(moduleName) && moduleName.kind !== SyntaxKind.StringLiteral) {
|
||||
|
@ -13958,205 +13962,54 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeEntityName(node: EntityName, fallbackPath?: string[]): string {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
// TODO(ron.buckton): The getExpressionNameSubstitution function has been removed, but calling it
|
||||
// here has no effect anyway as an identifier in a type name is not an expression.
|
||||
// var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
|
||||
// var text = substitution || (<Identifier>node).text;
|
||||
let text = (<Identifier>node).text;
|
||||
if (fallbackPath) {
|
||||
fallbackPath.push(text);
|
||||
}
|
||||
else {
|
||||
return text;
|
||||
}
|
||||
function isFunctionType(type: Type): boolean {
|
||||
return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0;
|
||||
}
|
||||
|
||||
function getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind {
|
||||
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
|
||||
let symbol = resolveEntityName(node.typeName, SymbolFlags.Value, /*ignoreErrors*/ true);
|
||||
let constructorType = symbol ? getTypeOfSymbol(symbol) : undefined;
|
||||
if (constructorType && isConstructorType(constructorType)) {
|
||||
return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
|
||||
}
|
||||
|
||||
let type = getTypeFromTypeNode(node);
|
||||
if (type === unknownType) {
|
||||
return TypeReferenceSerializationKind.Unknown;
|
||||
}
|
||||
else if (type.flags & TypeFlags.Any) {
|
||||
return TypeReferenceSerializationKind.ObjectType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.Void)) {
|
||||
return TypeReferenceSerializationKind.VoidType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.Boolean)) {
|
||||
return TypeReferenceSerializationKind.BooleanType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.NumberLike)) {
|
||||
return TypeReferenceSerializationKind.NumberLikeType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.StringLike)) {
|
||||
return TypeReferenceSerializationKind.StringLikeType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.Tuple)) {
|
||||
return TypeReferenceSerializationKind.ArrayLikeType;
|
||||
}
|
||||
else if (allConstituentTypesHaveKind(type, TypeFlags.ESSymbol)) {
|
||||
return TypeReferenceSerializationKind.ESSymbolType;
|
||||
}
|
||||
else if (isFunctionType(type)) {
|
||||
return TypeReferenceSerializationKind.TypeWithCallSignature;
|
||||
}
|
||||
else if (isArrayType(type)) {
|
||||
return TypeReferenceSerializationKind.ArrayLikeType;
|
||||
}
|
||||
else {
|
||||
let left = serializeEntityName((<QualifiedName>node).left, fallbackPath);
|
||||
let right = serializeEntityName((<QualifiedName>node).right, fallbackPath);
|
||||
if (!fallbackPath) {
|
||||
return left + "." + right;
|
||||
}
|
||||
return TypeReferenceSerializationKind.ObjectType;
|
||||
}
|
||||
}
|
||||
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeReferenceNode(node: TypeReferenceNode): string | string[] {
|
||||
// serialization of a TypeReferenceNode uses the following rules:
|
||||
//
|
||||
// * The serialized type of a TypeReference that is `void` is "void 0".
|
||||
// * The serialized type of a TypeReference that is a `boolean` is "Boolean".
|
||||
// * The serialized type of a TypeReference that is an enum or `number` is "Number".
|
||||
// * The serialized type of a TypeReference that is a string literal or `string` is "String".
|
||||
// * The serialized type of a TypeReference that is a tuple is "Array".
|
||||
// * The serialized type of a TypeReference that is a `symbol` is "Symbol".
|
||||
// * The serialized type of a TypeReference with a value declaration is its entity name.
|
||||
// * The serialized type of a TypeReference with a call or construct signature is "Function".
|
||||
// * The serialized type of any other type is "Object".
|
||||
let type = getTypeFromTypeNode(node);
|
||||
if (type.flags & TypeFlags.Void) {
|
||||
return "void 0";
|
||||
}
|
||||
else if (type.flags & TypeFlags.Boolean) {
|
||||
return "Boolean";
|
||||
}
|
||||
else if (type.flags & TypeFlags.NumberLike) {
|
||||
return "Number";
|
||||
}
|
||||
else if (type.flags & TypeFlags.StringLike) {
|
||||
return "String";
|
||||
}
|
||||
else if (type.flags & TypeFlags.Tuple) {
|
||||
return "Array";
|
||||
}
|
||||
else if (type.flags & TypeFlags.ESSymbol) {
|
||||
return "Symbol";
|
||||
}
|
||||
else if (type === unknownType) {
|
||||
let fallbackPath: string[] = [];
|
||||
serializeEntityName(node.typeName, fallbackPath);
|
||||
return fallbackPath;
|
||||
}
|
||||
else if (type.symbol && type.symbol.valueDeclaration) {
|
||||
return serializeEntityName(node.typeName);
|
||||
}
|
||||
else if (typeHasCallOrConstructSignatures(type)) {
|
||||
return "Function";
|
||||
}
|
||||
|
||||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeNode(node: TypeNode | LiteralExpression): string | string[] {
|
||||
// serialization of a TypeNode uses the following rules:
|
||||
//
|
||||
// * The serialized type of `void` is "void 0" (undefined).
|
||||
// * The serialized type of a parenthesized type is the serialized type of its nested type.
|
||||
// * The serialized type of a Function or Constructor type is "Function".
|
||||
// * The serialized type of an Array or Tuple type is "Array".
|
||||
// * The serialized type of `boolean` is "Boolean".
|
||||
// * The serialized type of `string` or a string-literal type is "String".
|
||||
// * The serialized type of a type reference is handled by `serializeTypeReferenceNode`.
|
||||
// * The serialized type of any other type node is "Object".
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return "void 0";
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return serializeTypeNode((<ParenthesizedTypeNode>node).type);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return "Function";
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
return "Array";
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
return "Boolean";
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return "String";
|
||||
case SyntaxKind.NumberKeyword:
|
||||
return "Number";
|
||||
case SyntaxKind.TypeReference:
|
||||
return serializeTypeReferenceNode(<TypeReferenceNode>node);
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.AnyKeyword:
|
||||
break;
|
||||
default:
|
||||
Debug.fail("Cannot serialize unexpected type node.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
|
||||
function serializeTypeOfNode(node: Node): string | string[] {
|
||||
// serialization of the type of a declaration uses the following rules:
|
||||
//
|
||||
// * The serialized type of a ClassDeclaration is "Function"
|
||||
// * The serialized type of a ParameterDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of a PropertyDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
|
||||
// * The serialized type of any other FunctionLikeDeclaration is "Function".
|
||||
// * The serialized type of any other node is "void 0".
|
||||
//
|
||||
// For rules on serializing type annotations, see `serializeTypeNode`.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration: return "Function";
|
||||
case SyntaxKind.PropertyDeclaration: return serializeTypeNode((<PropertyDeclaration>node).type);
|
||||
case SyntaxKind.Parameter: return serializeTypeNode((<ParameterDeclaration>node).type);
|
||||
case SyntaxKind.GetAccessor: return serializeTypeNode((<AccessorDeclaration>node).type);
|
||||
case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
|
||||
}
|
||||
if (isFunctionLike(node)) {
|
||||
return "Function";
|
||||
}
|
||||
return "void 0";
|
||||
}
|
||||
|
||||
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
|
||||
function serializeParameterTypesOfNode(node: Node): (string | string[])[] {
|
||||
// serialization of parameter types uses the following rules:
|
||||
//
|
||||
// * If the declaration is a class, the parameters of the first constructor with a body are used.
|
||||
// * If the declaration is function-like and has a body, the parameters of the function are used.
|
||||
//
|
||||
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
|
||||
if (node) {
|
||||
let valueDeclaration: FunctionLikeDeclaration;
|
||||
if (node.kind === SyntaxKind.ClassDeclaration) {
|
||||
valueDeclaration = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
}
|
||||
else if (isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
valueDeclaration = <FunctionLikeDeclaration>node;
|
||||
}
|
||||
if (valueDeclaration) {
|
||||
let result: (string | string[])[];
|
||||
let parameters = valueDeclaration.parameters;
|
||||
let parameterCount = parameters.length;
|
||||
if (parameterCount > 0) {
|
||||
result = new Array<string>(parameterCount);
|
||||
for (let i = 0; i < parameterCount; i++) {
|
||||
if (parameters[i].dotDotDotToken) {
|
||||
let parameterType = parameters[i].type;
|
||||
if (parameterType.kind === SyntaxKind.ArrayType) {
|
||||
parameterType = (<ArrayTypeNode>parameterType).elementType;
|
||||
}
|
||||
else if (parameterType.kind === SyntaxKind.TypeReference && (<TypeReferenceNode>parameterType).typeArguments && (<TypeReferenceNode>parameterType).typeArguments.length === 1) {
|
||||
parameterType = (<TypeReferenceNode>parameterType).typeArguments[0];
|
||||
}
|
||||
else {
|
||||
parameterType = undefined;
|
||||
}
|
||||
result[i] = serializeTypeNode(parameterType);
|
||||
}
|
||||
else {
|
||||
result[i] = serializeTypeOfNode(parameters[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
|
||||
function serializeReturnTypeOfNode(node: Node): string | string[] {
|
||||
if (node && isFunctionLike(node)) {
|
||||
return serializeTypeNode((<FunctionLikeDeclaration>node).type);
|
||||
}
|
||||
return "void 0";
|
||||
}
|
||||
|
||||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
|
||||
// Get type of the symbol if this is the valid symbol otherwise get type at location
|
||||
let symbol = getSymbolOfNode(declaration);
|
||||
|
@ -14254,9 +14107,7 @@ namespace ts {
|
|||
collectLinkedAliases,
|
||||
getBlockScopedVariableId,
|
||||
getReferencedValueDeclaration,
|
||||
serializeTypeOfNode,
|
||||
serializeParameterTypesOfNode,
|
||||
serializeReturnTypeOfNode,
|
||||
getTypeReferenceSerializationKind,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -14516,7 +14367,7 @@ namespace ts {
|
|||
}
|
||||
flags |= NodeFlags.Ambient;
|
||||
lastDeclare = modifier;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
if (flags & NodeFlags.Abstract) {
|
||||
|
@ -14552,7 +14403,7 @@ namespace ts {
|
|||
}
|
||||
flags |= NodeFlags.Async;
|
||||
lastAsync = modifier;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2069,13 +2069,52 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
|||
emit(node.name);
|
||||
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
|
||||
}
|
||||
|
||||
|
||||
function emitQualifiedName(node: QualifiedName) {
|
||||
emit(node.left);
|
||||
write(".");
|
||||
emit(node.right);
|
||||
}
|
||||
|
||||
function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean) {
|
||||
if (node.left.kind === SyntaxKind.Identifier) {
|
||||
emitEntityNameAsExpression(node.left, useFallback);
|
||||
}
|
||||
else if (useFallback) {
|
||||
let temp = createAndRecordTempVariable(TempFlags.Auto);
|
||||
write("(");
|
||||
emitNodeWithoutSourceMap(temp);
|
||||
write(" = ");
|
||||
emitEntityNameAsExpression(node.left, /*useFallback*/ true);
|
||||
write(") && ");
|
||||
emitNodeWithoutSourceMap(temp);
|
||||
}
|
||||
else {
|
||||
emitEntityNameAsExpression(node.left, /*useFallback*/ false);
|
||||
}
|
||||
|
||||
write(".");
|
||||
emitNodeWithoutSourceMap(node.right);
|
||||
}
|
||||
|
||||
function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
if (useFallback) {
|
||||
write("typeof ");
|
||||
emitExpressionIdentifier(<Identifier>node);
|
||||
write(" !== 'undefined' && ");
|
||||
}
|
||||
|
||||
emitExpressionIdentifier(<Identifier>node);
|
||||
break;
|
||||
|
||||
case SyntaxKind.QualifiedName:
|
||||
emitQualifiedNameAsExpression(<QualifiedName>node, useFallback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function emitIndexedAccess(node: ElementAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
|
@ -4750,83 +4789,267 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
|
||||
function emitSerializedTypeOfNode(node: Node) {
|
||||
// serialization of the type of a declaration uses the following rules:
|
||||
//
|
||||
// * The serialized type of a ClassDeclaration is "Function"
|
||||
// * The serialized type of a ParameterDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of a PropertyDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
|
||||
// * The serialized type of any other FunctionLikeDeclaration is "Function".
|
||||
// * The serialized type of any other node is "void 0".
|
||||
//
|
||||
// For rules on serializing type annotations, see `serializeTypeNode`.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
write("Function");
|
||||
return;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
emitSerializedTypeNode((<PropertyDeclaration>node).type);
|
||||
return;
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
emitSerializedTypeNode((<ParameterDeclaration>node).type);
|
||||
return;
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
emitSerializedTypeNode((<AccessorDeclaration>node).type);
|
||||
return;
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
emitSerializedTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (isFunctionLike(node)) {
|
||||
write("Function");
|
||||
return;
|
||||
}
|
||||
|
||||
write("void 0");
|
||||
}
|
||||
|
||||
function emitSerializedTypeNode(node: TypeNode) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VoidKeyword:
|
||||
write("void 0");
|
||||
return;
|
||||
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
emitSerializedTypeNode((<ParenthesizedTypeNode>node).type);
|
||||
return;
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
write("Function");
|
||||
return;
|
||||
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
write("Array");
|
||||
return;
|
||||
|
||||
case SyntaxKind.TypePredicate:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
write("Boolean");
|
||||
return;
|
||||
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
write("String");
|
||||
return;
|
||||
|
||||
case SyntaxKind.NumberKeyword:
|
||||
write("Number");
|
||||
return;
|
||||
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
write("Symbol");
|
||||
return;
|
||||
|
||||
case SyntaxKind.TypeReference:
|
||||
emitSerializedTypeReferenceNode(<TypeReferenceNode>node);
|
||||
return;
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.AnyKeyword:
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.fail("Cannot serialize unexpected type node.");
|
||||
break;
|
||||
}
|
||||
|
||||
write("Object");
|
||||
}
|
||||
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function emitSerializedTypeReferenceNode(node: TypeReferenceNode) {
|
||||
let typeName = node.typeName;
|
||||
let result = resolver.getTypeReferenceSerializationKind(node);
|
||||
switch (result) {
|
||||
case TypeReferenceSerializationKind.Unknown:
|
||||
let temp = createAndRecordTempVariable(TempFlags.Auto);
|
||||
write("(typeof (");
|
||||
emitNodeWithoutSourceMap(temp);
|
||||
write(" = ")
|
||||
emitEntityNameAsExpression(typeName, /*useFallback*/ true);
|
||||
write(") === 'function' && ");
|
||||
emitNodeWithoutSourceMap(temp);
|
||||
write(") || Object");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
|
||||
emitEntityNameAsExpression(typeName, /*useFallback*/ false);
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.VoidType:
|
||||
write("void 0");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.BooleanType:
|
||||
write("Boolean");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.NumberLikeType:
|
||||
write("Number");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.StringLikeType:
|
||||
write("String");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.ArrayLikeType:
|
||||
write("Array");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.ESSymbolType:
|
||||
if (languageVersion < ScriptTarget.ES6) {
|
||||
write("typeof Symbol === 'function' ? Symbol : Object");
|
||||
}
|
||||
else {
|
||||
write("Symbol");
|
||||
}
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.TypeWithCallSignature:
|
||||
write("Function");
|
||||
break;
|
||||
|
||||
case TypeReferenceSerializationKind.ObjectType:
|
||||
write("Object");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
|
||||
function emitSerializedParameterTypesOfNode(node: Node) {
|
||||
// serialization of parameter types uses the following rules:
|
||||
//
|
||||
// * If the declaration is a class, the parameters of the first constructor with a body are used.
|
||||
// * If the declaration is function-like and has a body, the parameters of the function are used.
|
||||
//
|
||||
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
|
||||
if (node) {
|
||||
var valueDeclaration: FunctionLikeDeclaration;
|
||||
if (node.kind === SyntaxKind.ClassDeclaration) {
|
||||
valueDeclaration = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
}
|
||||
else if (isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
valueDeclaration = <FunctionLikeDeclaration>node;
|
||||
}
|
||||
|
||||
if (valueDeclaration) {
|
||||
var parameters = valueDeclaration.parameters;
|
||||
var parameterCount = parameters.length;
|
||||
if (parameterCount > 0) {
|
||||
for (var i = 0; i < parameterCount; i++) {
|
||||
if (i > 0) {
|
||||
write(", ");
|
||||
}
|
||||
|
||||
if (parameters[i].dotDotDotToken) {
|
||||
var parameterType = parameters[i].type;
|
||||
if (parameterType.kind === SyntaxKind.ArrayType) {
|
||||
parameterType = (<ArrayTypeNode>parameterType).elementType;
|
||||
}
|
||||
else if (parameterType.kind === SyntaxKind.TypeReference && (<TypeReferenceNode>parameterType).typeArguments && (<TypeReferenceNode>parameterType).typeArguments.length === 1) {
|
||||
parameterType = (<TypeReferenceNode>parameterType).typeArguments[0];
|
||||
}
|
||||
else {
|
||||
parameterType = undefined;
|
||||
}
|
||||
|
||||
emitSerializedTypeNode(parameterType);
|
||||
}
|
||||
else {
|
||||
emitSerializedTypeOfNode(parameters[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
|
||||
function emitSerializedReturnTypeOfNode(node: Node): string | string[] {
|
||||
if (node && isFunctionLike(node)) {
|
||||
emitSerializedTypeNode((<FunctionLikeDeclaration>node).type);
|
||||
return;
|
||||
}
|
||||
|
||||
write("void 0");
|
||||
}
|
||||
|
||||
|
||||
function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number {
|
||||
// This method emits the serialized type metadata for a decorator target.
|
||||
// The caller should have already tested whether the node has decorators.
|
||||
let argumentsWritten = 0;
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldEmitTypeMetadata(node)) {
|
||||
let serializedType = resolver.serializeTypeOfNode(node);
|
||||
if (serializedType) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:type', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:type', ");
|
||||
emitSerializedTypeOfNode(node);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
if (shouldEmitParamTypesMetadata(node)) {
|
||||
let serializedTypes = resolver.serializeParameterTypesOfNode(node);
|
||||
if (serializedTypes) {
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:paramtypes', [");
|
||||
for (var i = 0; i < serializedTypes.length; ++i) {
|
||||
if (i > 0) {
|
||||
write(", ");
|
||||
}
|
||||
emitSerializedType(node, serializedTypes[i]);
|
||||
}
|
||||
write("])");
|
||||
argumentsWritten++;
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:paramtypes', [");
|
||||
emitSerializedParameterTypesOfNode(node);
|
||||
write("])");
|
||||
argumentsWritten++;
|
||||
}
|
||||
if (shouldEmitReturnTypeMetadata(node)) {
|
||||
let serializedType = resolver.serializeReturnTypeOfNode(node);
|
||||
if (serializedType) {
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:returntype', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
|
||||
writeLine();
|
||||
write("__metadata('design:returntype', ");
|
||||
emitSerializedReturnTypeOfNode(node);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
}
|
||||
|
||||
return argumentsWritten;
|
||||
}
|
||||
|
||||
function serializeTypeNameSegment(location: Node, path: string[], index: number): string {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return `typeof ${path[index]} !== 'undefined' && ${path[index]}`;
|
||||
case 1:
|
||||
return `${serializeTypeNameSegment(location, path, index - 1) }.${path[index]}`;
|
||||
default:
|
||||
let temp = createAndRecordTempVariable(TempFlags.Auto).text;
|
||||
return `(${temp} = ${serializeTypeNameSegment(location, path, index - 1) }) && ${temp}.${path[index]}`;
|
||||
}
|
||||
}
|
||||
|
||||
function emitSerializedType(location: Node, name: string | string[]): void {
|
||||
if (typeof name === "string") {
|
||||
write(name);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Debug.assert(name.length > 0, "Invalid serialized type name");
|
||||
write(`(${serializeTypeNameSegment(location, name, name.length - 1) }) || Object`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function emitInterfaceDeclaration(node: InterfaceDeclaration) {
|
||||
emitOnlyPinnedOrTripleSlashComments(node);
|
||||
}
|
||||
|
@ -5933,6 +6156,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
|||
Debug.assert(!exportFunctionForFile);
|
||||
// make sure that name of 'exports' function does not conflict with existing identifiers
|
||||
exportFunctionForFile = makeUniqueName("exports");
|
||||
writeLine();
|
||||
write("System.register(");
|
||||
if (node.moduleName) {
|
||||
write(`"${node.moduleName}", `);
|
||||
|
@ -6686,4 +6910,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1528,6 +1528,27 @@ namespace ts {
|
|||
export interface SymbolAccessiblityResult extends SymbolVisibilityResult {
|
||||
errorModuleName?: string; // If the symbol is not visible from module, module's name
|
||||
}
|
||||
|
||||
/** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator
|
||||
* metadata */
|
||||
/* @internal */
|
||||
export enum TypeReferenceSerializationKind {
|
||||
Unknown, // The TypeReferenceNode could not be resolved. The type name
|
||||
// should be emitted using a safe fallback.
|
||||
TypeWithConstructSignatureAndValue, // The TypeReferenceNode resolves to a type with a constructor
|
||||
// function that can be reached at runtime (e.g. a `class`
|
||||
// declaration or a `var` declaration for the static side
|
||||
// of a type, such as the global `Promise` type in lib.d.ts).
|
||||
VoidType, // The TypeReferenceNode resolves to a Void-like type.
|
||||
NumberLikeType, // The TypeReferenceNode resolves to a Number-like type.
|
||||
StringLikeType, // The TypeReferenceNode resolves to a String-like type.
|
||||
BooleanType, // The TypeReferenceNode resolves to a Boolean-like type.
|
||||
ArrayLikeType, // The TypeReferenceNode resolves to an Array-like type.
|
||||
ESSymbolType, // The TypeReferenceNode resolves to the ESSymbol type.
|
||||
TypeWithCallSignature, // The TypeReferenceNode resolves to a Function type or a type
|
||||
// with call signatures.
|
||||
ObjectType, // The TypeReferenceNode resolves to any other type.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitResolver {
|
||||
|
@ -1552,9 +1573,7 @@ namespace ts {
|
|||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
getBlockScopedVariableId(node: Identifier): number;
|
||||
getReferencedValueDeclaration(reference: Identifier): Declaration;
|
||||
serializeTypeOfNode(node: Node): string | string[];
|
||||
serializeParameterTypesOfNode(node: Node): (string | string[])[];
|
||||
serializeReturnTypeOfNode(node: Node): string | string[];
|
||||
getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
|
|
|
@ -1706,6 +1706,10 @@ namespace ts {
|
|||
});
|
||||
}
|
||||
|
||||
export function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode {
|
||||
return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
|
||||
}
|
||||
|
||||
export function shouldEmitToOwnFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean {
|
||||
if (!isDeclarationFile(sourceFile)) {
|
||||
if ((isExternalModule(sourceFile) || !compilerOptions.out)) {
|
||||
|
|
Loading…
Reference in a new issue