PR feedback
This commit is contained in:
parent
f15ff32d5c
commit
9a590dbbe5
|
@ -8747,6 +8747,9 @@ module ts {
|
|||
|
||||
/** Checks a type reference node as an expression. */
|
||||
function checkTypeNodeAsExpression(node: TypeNode | LiteralExpression) {
|
||||
// When we are emitting type metadata for decorators, we need to try to check the type
|
||||
// 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 = getTypeFromTypeNodeOrHeritageClauseElement(node);
|
||||
let shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
|
||||
|
@ -8785,29 +8788,35 @@ module ts {
|
|||
function checkDecorators(node: Node): void {
|
||||
if (!node.decorators) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
var constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
if (constructor) {
|
||||
checkParameterTypeAnnotationsAsExpressions(constructor);
|
||||
}
|
||||
break;
|
||||
// skip this check for nodes that cannot have decorators. These should have already had an error reported by
|
||||
// checkGrammarDecorators.
|
||||
if (!nodeCanBeDecorated(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
// fall-through
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
// we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
var constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
if (constructor) {
|
||||
checkParameterTypeAnnotationsAsExpressions(constructor);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
// fall-through
|
||||
|
||||
default:
|
||||
return;
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emitDecorate = true;
|
||||
|
@ -11510,7 +11519,7 @@ module ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the `@type`, `@paramtypes`, and `@returntype` decorators. */
|
||||
/** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
|
||||
|
@ -11531,7 +11540,7 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the `@type`, `@paramtypes`, and `@returntype` decorators. */
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeReferenceNode(node: TypeReferenceNode, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of a TypeReferenceNode uses the following rules:
|
||||
//
|
||||
|
@ -11578,7 +11587,7 @@ module ts {
|
|||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes a TypeNode to an appropriate JS constructor value. Used by the `@type`, `@paramtypes`, and `@returntype` decorators. */
|
||||
/** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeNode(node: TypeNode | LiteralExpression, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of a TypeNode uses the following rules:
|
||||
//
|
||||
|
@ -11623,11 +11632,11 @@ module ts {
|
|||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the `@type` and `@paramtypes` decorators. */
|
||||
/** 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, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of the type of a declaration uses the following rules:
|
||||
//
|
||||
// * The serialized type of a ClassDeclaration is the class name (see serializeEntityName).
|
||||
// * 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.
|
||||
|
@ -11648,7 +11657,7 @@ module ts {
|
|||
return "void 0";
|
||||
}
|
||||
|
||||
/** Serializes the parameter types of a function or the constructor of a class. Used by the `@paramtypes` decorator. */
|
||||
/** 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, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[] {
|
||||
// serialization of parameter types uses the following rules:
|
||||
//
|
||||
|
@ -11695,7 +11704,7 @@ module ts {
|
|||
return emptyArray;
|
||||
}
|
||||
|
||||
/** Serializes the return type of function. Used by the `@returntype` decorator. */
|
||||
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
|
||||
function serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
if (node && isFunctionLike(node)) {
|
||||
return serializeTypeNode((<FunctionLikeDeclaration>node).type, getGeneratedNameForNode);
|
||||
|
|
|
@ -796,27 +796,34 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
}
|
||||
}
|
||||
|
||||
function emitList(nodes: Node[], start: number, count: number, multiLine: boolean, trailingComma: boolean) {
|
||||
function emitList<TNode extends Node>(nodes: TNode[], start: number, count: number, multiLine: boolean, trailingComma: boolean, leadingComma?: boolean, noTrailingNewLine?: boolean, emitNode?: (node: TNode) => void): number {
|
||||
if (!emitNode) {
|
||||
emitNode = emit;
|
||||
}
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (multiLine) {
|
||||
if (i) {
|
||||
if (i || leadingComma) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
}
|
||||
else {
|
||||
if (i) {
|
||||
if (i || leadingComma) {
|
||||
write(", ");
|
||||
}
|
||||
}
|
||||
emit(nodes[start + i]);
|
||||
emitNode(nodes[start + i]);
|
||||
leadingComma = true;
|
||||
}
|
||||
if (trailingComma) {
|
||||
write(",");
|
||||
}
|
||||
if (multiLine) {
|
||||
if (multiLine && !noTrailingNewLine) {
|
||||
writeLine();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[]) {
|
||||
|
@ -3752,10 +3759,15 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
let writeComma = false;
|
||||
writeComma = emitDecoratorArray(decorators, writeComma);
|
||||
writeComma = emitDecoratorsOfParameters(constructor, writeComma);
|
||||
emitSerializedTypeMetadata(node, writeComma);
|
||||
let decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
|
||||
emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
|
@ -3861,10 +3873,15 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
let writeComma = false;
|
||||
writeComma = emitDecoratorArray(decorators, writeComma);
|
||||
writeComma = emitDecoratorsOfParameters(functionLikeMember, writeComma);
|
||||
emitSerializedTypeMetadata(member, writeComma);
|
||||
let decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
|
||||
emitSerializedTypeMetadata(member, argumentsWritten > 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
|
@ -3892,45 +3909,32 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
}
|
||||
}
|
||||
|
||||
function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, writeComma: boolean): boolean {
|
||||
function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, leadingComma: boolean): number {
|
||||
let argumentsWritten = 0;
|
||||
if (node) {
|
||||
let parameterIndex = 0;
|
||||
for (let parameter of node.parameters) {
|
||||
if (nodeIsDecorated(parameter)) {
|
||||
writeComma = emitDecoratorArray(parameter.decorators, writeComma, `__param(${parameterIndex}, `, ")");
|
||||
let decorators = parameter.decorators;
|
||||
argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
write(`__param(${parameterIndex}, `);
|
||||
emit(decorator.expression);
|
||||
write(")");
|
||||
emitEnd(decorator);
|
||||
});
|
||||
leadingComma = true;
|
||||
}
|
||||
++parameterIndex;
|
||||
}
|
||||
}
|
||||
return writeComma;
|
||||
}
|
||||
|
||||
function emitDecoratorArray(decorators: NodeArray<Decorator>, writeComma: boolean, prefix?: string, postfix?: string): boolean {
|
||||
if (decorators) {
|
||||
let decoratorCount = decorators ? decorators.length : 0;
|
||||
for (let i = 0; i < decoratorCount; i++) {
|
||||
if (writeComma) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
|
||||
let decorator = decorators[i];
|
||||
emitStart(decorator);
|
||||
write(prefix);
|
||||
emit(decorator.expression);
|
||||
write(postfix);
|
||||
emitEnd(decorator);
|
||||
writeComma = true;
|
||||
}
|
||||
}
|
||||
return writeComma;
|
||||
return argumentsWritten;
|
||||
}
|
||||
|
||||
function shouldEmitTypeMetadata(node: Declaration): boolean {
|
||||
if (!compilerOptions.emitDecoratorMetadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This method determines whether to emit the "design:type" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
|
@ -3943,10 +3947,9 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
}
|
||||
|
||||
function shouldEmitReturnTypeMetadata(node: Declaration): boolean {
|
||||
if (!compilerOptions.emitDecoratorMetadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This method determines whether to emit the "design:returntype" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return true;
|
||||
|
@ -3955,10 +3958,9 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
}
|
||||
|
||||
function shouldEmitParamTypesMetadata(node: Declaration): boolean {
|
||||
if (!compilerOptions.emitDecoratorMetadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This method determines whether to emit the "design:paramtypes" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
|
@ -3968,50 +3970,57 @@ var __param = this.__param || function(index, decorator) { return function (targ
|
|||
return false;
|
||||
}
|
||||
|
||||
function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): void {
|
||||
if (shouldEmitTypeMetadata(node)) {
|
||||
var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:type', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
writeComma = true;
|
||||
}
|
||||
}
|
||||
if (shouldEmitParamTypesMetadata(node)) {
|
||||
var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedTypes) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:paramtypes', [");
|
||||
for (var i = 0; i < serializedTypes.length; ++i) {
|
||||
if (i > 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)) {
|
||||
var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
emitSerializedType(node, serializedTypes[i]);
|
||||
writeLine();
|
||||
write("__metadata('design:type', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
}
|
||||
if (shouldEmitParamTypesMetadata(node)) {
|
||||
var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
|
||||
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 (shouldEmitReturnTypeMetadata(node)) {
|
||||
var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:returntype', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
write("])");
|
||||
writeComma = true;
|
||||
}
|
||||
}
|
||||
if (shouldEmitReturnTypeMetadata(node)) {
|
||||
var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:returntype', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
return argumentsWritten;
|
||||
}
|
||||
|
||||
function serializeTypeNameSegment(location: Node, path: string[], index: number): string {
|
||||
|
|
Loading…
Reference in a new issue