PR feedback

This commit is contained in:
Ron Buckton 2015-04-02 15:22:53 -07:00
parent f15ff32d5c
commit 9a590dbbe5
2 changed files with 132 additions and 114 deletions

View file

@ -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);

View file

@ -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 {