Partial transform for class decorators

This commit is contained in:
Ron Buckton 2015-07-15 12:13:34 -07:00
parent f3d310360b
commit 4652f053b1
11 changed files with 642 additions and 99 deletions

View File

@ -802,7 +802,7 @@ function generateTransform(outputFile: string) {
return;
}
writer.write(`export function visitNodeArrayOf${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, nodes: NodeArray<${typeName}>, visitor: Visitor): NodeArray<${typeName}> {`);
writer.write(`export function visitNodeArrayOf${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, nodes: Array<${typeName}>, visitor: Visitor): NodeArray<${typeName}> {`);
writer.writeLine();
writer.increaseIndent();

View File

@ -854,8 +854,9 @@ namespace ts {
case SyntaxKind.BindingElement:
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
case SyntaxKind.PropertyDeclaration:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
case SyntaxKind.PropertySignature:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertyDeclaration>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertySignature>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
@ -1056,4 +1057,4 @@ namespace ts {
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
}
}
}

View File

@ -304,6 +304,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return generateNameForExportDefault();
case SyntaxKind.ClassExpression:
return generateNameForClassExpression();
case SyntaxKind.ComputedPropertyName:
return makeTempVariableName(TempFlags.Auto);
}
}
@ -4297,7 +4299,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(")");
}
else {
writeLine();
if (!isClassExpression(node)) {
writeLine();
}
emitPropertyDeclarations(node, staticProperties);
emitDecoratorsOfClass(node);
}
@ -6122,7 +6127,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Process tree transformations
let statements = node.statements;
if (compilerOptions.experimentalTransforms) {
let context = new transform.VisitorContext(currentSourceFile, resolver, generatedNameSet, getGeneratedNameForNode);
let context = new transform.VisitorContext(compilerOptions, currentSourceFile, resolver, generatedNameSet, nodeToGeneratedName);
statements = transformationChain(context, node.statements);
}

View File

@ -130,7 +130,7 @@ namespace ts {
}
return node;
}
export function createPropertySignature(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: DeclarationName, questionToken?: Node,
export function createPropertySignature(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: PropertyName, questionToken?: Node,
type?: TypeNode, location?: TextRange, flags?: NodeFlags): PropertySignature {
let node = createNode<PropertySignature>(SyntaxKind.PropertySignature, location, flags);
if (arguments.length) {
@ -142,7 +142,7 @@ namespace ts {
}
return node;
}
export function updatePropertySignature(node: PropertySignature, decorators: Array<Decorator>, modifiers: Array<Node>, name: DeclarationName
export function updatePropertySignature(node: PropertySignature, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, type: TypeNode): PropertySignature {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type) {
let newNode = createPropertySignature(decorators, modifiers, name, node.questionToken, type);
@ -150,29 +150,28 @@ namespace ts {
}
return node;
}
export function createPropertyDeclaration(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: DeclarationName,
questionToken?: Node, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyDeclaration {
export function createPropertyDeclaration(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: PropertyName, type?: TypeNode,
initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyDeclaration {
let node = createNode<PropertyDeclaration>(SyntaxKind.PropertyDeclaration, location, flags);
if (arguments.length) {
node.decorators = decorators && createNodeArray(decorators)
setModifiers(node, modifiers);
node.name = name;
node.questionToken = questionToken;
node.type = type;
node.initializer = initializer;
}
return node;
}
export function updatePropertyDeclaration(node: PropertyDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>
, name: DeclarationName, type: TypeNode, initializer: Expression): PropertyDeclaration {
export function updatePropertyDeclaration(node: PropertyDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, type: TypeNode, initializer: Expression): PropertyDeclaration {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type ||
initializer !== node.initializer) {
let newNode = createPropertyDeclaration(decorators, modifiers, name, node.questionToken, type, initializer);
let newNode = createPropertyDeclaration(decorators, modifiers, name, type, initializer);
return updateFrom(node, newNode);
}
return node;
}
export function createMethodSignature(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: DeclarationName, questionToken?: Node,
export function createMethodSignature(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: PropertyName, questionToken?: Node,
typeParameters?: Array<TypeParameterDeclaration>, parameters?: Array<ParameterDeclaration>, type?: TypeNode,
location?: TextRange, flags?: NodeFlags): MethodSignature {
let node = createNode<MethodSignature>(SyntaxKind.MethodSignature, location, flags);
@ -187,7 +186,7 @@ namespace ts {
}
return node;
}
export function updateMethodSignature(node: MethodSignature, decorators: Array<Decorator>, modifiers: Array<Node>, name: DeclarationName
export function updateMethodSignature(node: MethodSignature, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, typeParameters: Array<TypeParameterDeclaration>, parameters: Array<ParameterDeclaration>, type: TypeNode): MethodSignature {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters ||
parameters !== node.parameters || type !== node.type) {
@ -196,7 +195,7 @@ namespace ts {
}
return node;
}
export function createMethodDeclaration(decorators?: Array<Decorator>, modifiers?: Array<Node>, asteriskToken?: Node, name?: DeclarationName,
export function createMethodDeclaration(decorators?: Array<Decorator>, modifiers?: Array<Node>, asteriskToken?: Node, name?: PropertyName,
typeParameters?: Array<TypeParameterDeclaration>, parameters?: Array<ParameterDeclaration>, type?: TypeNode, body?: Block,
location?: TextRange, flags?: NodeFlags): MethodDeclaration {
let node = createNode<MethodDeclaration>(SyntaxKind.MethodDeclaration, location, flags);
@ -212,7 +211,7 @@ namespace ts {
}
return node;
}
export function updateMethodDeclaration(node: MethodDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: DeclarationName
export function updateMethodDeclaration(node: MethodDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, typeParameters: Array<TypeParameterDeclaration>, parameters: Array<ParameterDeclaration>, type: TypeNode, body: Block
): MethodDeclaration {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters ||
@ -243,7 +242,7 @@ namespace ts {
}
return node;
}
export function createGetAccessor(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: DeclarationName,
export function createGetAccessor(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: PropertyName,
parameters?: Array<ParameterDeclaration>, type?: TypeNode, body?: Block,
location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration {
let node = createNode<GetAccessorDeclaration>(SyntaxKind.GetAccessor, location, flags);
@ -257,7 +256,7 @@ namespace ts {
}
return node;
}
export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: DeclarationName
export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, parameters: Array<ParameterDeclaration>, type: TypeNode, body: Block): GetAccessorDeclaration {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters ||
type !== node.type || body !== node.body) {
@ -266,7 +265,7 @@ namespace ts {
}
return node;
}
export function createSetAccessor(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: DeclarationName,
export function createSetAccessor(decorators?: Array<Decorator>, modifiers?: Array<Node>, name?: PropertyName,
parameters?: Array<ParameterDeclaration>, type?: TypeNode, body?: Block,
location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration {
let node = createNode<SetAccessorDeclaration>(SyntaxKind.SetAccessor, location, flags);
@ -280,7 +279,7 @@ namespace ts {
}
return node;
}
export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: DeclarationName
export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Array<Decorator>, modifiers: Array<Node>, name: PropertyName
, parameters: Array<ParameterDeclaration>, type: TypeNode, body: Block): SetAccessorDeclaration {
if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters ||
type !== node.type || body !== node.body) {
@ -1788,7 +1787,7 @@ namespace ts {
}
return node;
}
export function createPropertyAssignment(name?: DeclarationName, questionToken?: Node, initializer?: Expression,
export function createPropertyAssignment(name?: PropertyName, questionToken?: Node, initializer?: Expression,
location?: TextRange, flags?: NodeFlags): PropertyAssignment {
let node = createNode<PropertyAssignment>(SyntaxKind.PropertyAssignment, location, flags);
if (arguments.length) {
@ -1798,7 +1797,7 @@ namespace ts {
}
return node;
}
export function updatePropertyAssignment(node: PropertyAssignment, name: DeclarationName, initializer: Expression): PropertyAssignment {
export function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment {
if (name !== node.name || initializer !== node.initializer) {
let newNode = createPropertyAssignment(name, node.questionToken, initializer);
return updateFrom(node, newNode);
@ -2165,8 +2164,8 @@ namespace ts {
(<PropertySignature>node).name, (<PropertySignature>node).questionToken, (<PropertySignature>node).type, location, flags);
case SyntaxKind.PropertyDeclaration:
return factory.createPropertyDeclaration((<PropertyDeclaration>node).decorators, (<PropertyDeclaration>node).modifiers,
(<PropertyDeclaration>node).name, (<PropertyDeclaration>node).questionToken, (<PropertyDeclaration>node).type,
(<PropertyDeclaration>node).initializer, location, flags);
(<PropertyDeclaration>node).name, (<PropertyDeclaration>node).type, (<PropertyDeclaration>node).initializer,
location, flags);
case SyntaxKind.MethodSignature:
return factory.createMethodSignature((<MethodSignature>node).decorators, (<MethodSignature>node).modifiers,
(<MethodSignature>node).name, (<MethodSignature>node).questionToken, (<MethodSignature>node).typeParameters,
@ -3128,13 +3127,29 @@ namespace ts {
}
return false;
}
export function isPropertyName(node: Node): node is PropertyName {
if (node) {
switch (node.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.NumericLiteral:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail:
case SyntaxKind.StringLiteral:
case SyntaxKind.ComputedPropertyName:
return true;
}
}
return false;
}
export function isTypeElement(node: Node): node is TypeElement {
if (node) {
switch (node.kind) {
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.PropertySignature:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.MissingDeclaration:

View File

@ -233,9 +233,9 @@ namespace ts {
return factory.createVariableStatement(
factory.createVariableDeclarationList([
factory.createVariableDeclaration2(name, initializer)
]),
], /*location*/ undefined, flags & (NodeFlags.Let | NodeFlags.Const)),
location,
flags
flags & ~(NodeFlags.Let | NodeFlags.Const)
);
}
@ -251,6 +251,36 @@ namespace ts {
);
}
export function createClassDeclaration2(modifiers: Modifier[], name: Identifier, heritageClause: HeritageClause, members: ClassElement[]): ClassDeclaration {
return factory.createClassDeclaration(
/*decorators*/ undefined,
modifiers,
name,
/*typeParameters*/ undefined,
heritageClause ? [heritageClause] : undefined,
members
);
}
export function createClassExpression2(name: Identifier, heritageClause: HeritageClause, members: ClassElement[]): ClassExpression {
return factory.createClassExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
name,
/*typeParameters*/ undefined,
heritageClause ? [heritageClause] : undefined,
members
);
}
export function createClassExpression3(heritageClause: HeritageClause, members: ClassElement[]) {
return factory.createClassExpression2(
/*name*/ undefined,
heritageClause,
members
);
}
export function createFunctionDeclaration2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionDeclaration(
/*decorators*/ undefined,

View File

@ -1054,7 +1054,7 @@ namespace ts {
token === SyntaxKind.NumericLiteral;
}
function parsePropertyNameWorker(allowComputedPropertyNames: boolean): DeclarationName {
function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) {
return parseLiteralNode(/*internName*/ true);
}
@ -1064,7 +1064,7 @@ namespace ts {
return parseIdentifierName();
}
function parsePropertyName(): DeclarationName {
function parsePropertyName(): PropertyName {
return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true);
}
@ -4499,7 +4499,7 @@ namespace ts {
return finishNode(node);
}
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: DeclarationName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
let method = beginNode(factory.createMethodDeclaration(), fullStart);
method.decorators = decorators;
setModifiers(method, modifiers);
@ -4513,7 +4513,7 @@ namespace ts {
return finishNode(method);
}
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: DeclarationName, questionToken: Node): ClassElement {
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement {
let property = beginNode(factory.createPropertyDeclaration(), fullStart);
property.decorators = decorators;
setModifiers(property, modifiers);

View File

@ -40,14 +40,14 @@ namespace ts.transform {
<PropertySignature>node,
visitNodeArrayOfDecorator(context, (<PropertySignature>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<PropertySignature>node).modifiers, visitor),
visitDeclarationName(context, (<PropertySignature>node).name, visitor),
visitPropertyName(context, (<PropertySignature>node).name, visitor),
visitTypeNode(context, (<PropertySignature>node).type, visitor));
case SyntaxKind.PropertyDeclaration:
return factory.updatePropertyDeclaration(
<PropertyDeclaration>node,
visitNodeArrayOfDecorator(context, (<PropertyDeclaration>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<PropertyDeclaration>node).modifiers, visitor),
visitDeclarationName(context, (<PropertyDeclaration>node).name, visitor),
visitPropertyName(context, (<PropertyDeclaration>node).name, visitor),
visitTypeNode(context, (<PropertyDeclaration>node).type, visitor),
visitExpression(context, (<PropertyDeclaration>node).initializer, visitor));
case SyntaxKind.MethodSignature:
@ -55,7 +55,7 @@ namespace ts.transform {
<MethodSignature>node,
visitNodeArrayOfDecorator(context, (<MethodSignature>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<MethodSignature>node).modifiers, visitor),
visitDeclarationName(context, (<MethodSignature>node).name, visitor),
visitPropertyName(context, (<MethodSignature>node).name, visitor),
visitNodeArrayOfTypeParameter(context, (<MethodSignature>node).typeParameters, visitor),
visitNodeArrayOfParameter(context, (<MethodSignature>node).parameters, visitor),
visitTypeNode(context, (<MethodSignature>node).type, visitor));
@ -64,7 +64,7 @@ namespace ts.transform {
<MethodDeclaration>node,
visitNodeArrayOfDecorator(context, (<MethodDeclaration>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<MethodDeclaration>node).modifiers, visitor),
visitDeclarationName(context, (<MethodDeclaration>node).name, visitor),
visitPropertyName(context, (<MethodDeclaration>node).name, visitor),
visitNodeArrayOfTypeParameter(context, (<MethodDeclaration>node).typeParameters, visitor),
visitNodeArrayOfParameter(context, (<MethodDeclaration>node).parameters, visitor),
visitTypeNode(context, (<MethodDeclaration>node).type, visitor),
@ -82,7 +82,7 @@ namespace ts.transform {
<GetAccessorDeclaration>node,
visitNodeArrayOfDecorator(context, (<GetAccessorDeclaration>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<GetAccessorDeclaration>node).modifiers, visitor),
visitDeclarationName(context, (<GetAccessorDeclaration>node).name, visitor),
visitPropertyName(context, (<GetAccessorDeclaration>node).name, visitor),
visitNodeArrayOfParameter(context, (<GetAccessorDeclaration>node).parameters, visitor),
visitTypeNode(context, (<GetAccessorDeclaration>node).type, visitor),
visitBlockInNewLexicalScope(context, (<GetAccessorDeclaration>node).body, visitor));
@ -91,7 +91,7 @@ namespace ts.transform {
<SetAccessorDeclaration>node,
visitNodeArrayOfDecorator(context, (<SetAccessorDeclaration>node).decorators, visitor),
visitNodeArrayOfModifier(context, (<SetAccessorDeclaration>node).modifiers, visitor),
visitDeclarationName(context, (<SetAccessorDeclaration>node).name, visitor),
visitPropertyName(context, (<SetAccessorDeclaration>node).name, visitor),
visitNodeArrayOfParameter(context, (<SetAccessorDeclaration>node).parameters, visitor),
visitTypeNode(context, (<SetAccessorDeclaration>node).type, visitor),
visitBlockInNewLexicalScope(context, (<SetAccessorDeclaration>node).body, visitor));
@ -588,7 +588,7 @@ namespace ts.transform {
case SyntaxKind.PropertyAssignment:
return factory.updatePropertyAssignment(
<PropertyAssignment>node,
visitDeclarationName(context, (<PropertyAssignment>node).name, visitor),
visitPropertyName(context, (<PropertyAssignment>node).name, visitor),
visitExpression(context, (<PropertyAssignment>node).initializer, visitor));
case SyntaxKind.ShorthandPropertyAssignment:
return factory.updateShorthandPropertyAssignment(
@ -747,10 +747,10 @@ namespace ts.transform {
Debug.assert(!visited || isVariableDeclaration(visited), "Wrong node kind after visit.");
return <VariableDeclaration>visited;
}
export function visitDeclarationName(context: VisitorContext, node: DeclarationName, visitor: Visitor): DeclarationName {
export function visitPropertyName(context: VisitorContext, node: PropertyName, visitor: Visitor): PropertyName {
let visited = visit(context, node, visitor);
Debug.assert(!visited || isDeclarationName(visited), "Wrong node kind after visit.");
return <DeclarationName>visited;
Debug.assert(!visited || isPropertyName(visited), "Wrong node kind after visit.");
return <PropertyName>visited;
}
export function visitBindingElement(context: VisitorContext, node: BindingElement, visitor: Visitor): BindingElement {
let visited = visit(context, node, visitor);
@ -857,6 +857,11 @@ namespace ts.transform {
Debug.assert(!visited || isExpressionWithTypeArguments(visited), "Wrong node kind after visit.");
return <ExpressionWithTypeArguments>visited;
}
export function visitDeclarationName(context: VisitorContext, node: DeclarationName, visitor: Visitor): DeclarationName {
let visited = visit(context, node, visitor);
Debug.assert(!visited || isDeclarationName(visited), "Wrong node kind after visit.");
return <DeclarationName>visited;
}
export function visitEnumMember(context: VisitorContext, node: EnumMember, visitor: Visitor): EnumMember {
let visited = visit(context, node, visitor);
Debug.assert(!visited || isEnumMember(visited), "Wrong node kind after visit.");
@ -917,70 +922,70 @@ namespace ts.transform {
Debug.assert(!visited || isJSDocTypeExpression(visited), "Wrong node kind after visit.");
return <JSDocTypeExpression>visited;
}
export function visitNodeArrayOfTypeParameter(context: VisitorContext, nodes: NodeArray<TypeParameterDeclaration>, visitor: Visitor): NodeArray<TypeParameterDeclaration> {
export function visitNodeArrayOfTypeParameter(context: VisitorContext, nodes: Array<TypeParameterDeclaration>, visitor: Visitor): NodeArray<TypeParameterDeclaration> {
return <NodeArray<TypeParameterDeclaration>>visitNodes(context, nodes, visitor, visitTypeParameter);
}
export function visitNodeArrayOfParameter(context: VisitorContext, nodes: NodeArray<ParameterDeclaration>, visitor: Visitor): NodeArray<ParameterDeclaration> {
export function visitNodeArrayOfParameter(context: VisitorContext, nodes: Array<ParameterDeclaration>, visitor: Visitor): NodeArray<ParameterDeclaration> {
return <NodeArray<ParameterDeclaration>>visitNodes(context, nodes, visitor, visitParameter);
}
export function visitNodeArrayOfDecorator(context: VisitorContext, nodes: NodeArray<Decorator>, visitor: Visitor): NodeArray<Decorator> {
export function visitNodeArrayOfDecorator(context: VisitorContext, nodes: Array<Decorator>, visitor: Visitor): NodeArray<Decorator> {
return <NodeArray<Decorator>>visitNodes(context, nodes, visitor, visitDecorator);
}
export function visitNodeArrayOfModifier(context: VisitorContext, nodes: NodeArray<Modifier>, visitor: Visitor): NodeArray<Modifier> {
export function visitNodeArrayOfModifier(context: VisitorContext, nodes: Array<Modifier>, visitor: Visitor): NodeArray<Modifier> {
return <NodeArray<Modifier>>visitNodes(context, nodes, visitor, visitModifier);
}
export function visitNodeArrayOfVariableDeclaration(context: VisitorContext, nodes: NodeArray<VariableDeclaration>, visitor: Visitor): NodeArray<VariableDeclaration> {
export function visitNodeArrayOfVariableDeclaration(context: VisitorContext, nodes: Array<VariableDeclaration>, visitor: Visitor): NodeArray<VariableDeclaration> {
return <NodeArray<VariableDeclaration>>visitNodes(context, nodes, visitor, visitVariableDeclaration);
}
export function visitNodeArrayOfBindingElement(context: VisitorContext, nodes: NodeArray<BindingElement>, visitor: Visitor): NodeArray<BindingElement> {
export function visitNodeArrayOfBindingElement(context: VisitorContext, nodes: Array<BindingElement>, visitor: Visitor): NodeArray<BindingElement> {
return <NodeArray<BindingElement>>visitNodes(context, nodes, visitor, visitBindingElement);
}
export function visitNodeArrayOfTypeNode(context: VisitorContext, nodes: NodeArray<TypeNode>, visitor: Visitor): NodeArray<TypeNode> {
export function visitNodeArrayOfTypeNode(context: VisitorContext, nodes: Array<TypeNode>, visitor: Visitor): NodeArray<TypeNode> {
return <NodeArray<TypeNode>>visitNodes(context, nodes, visitor, visitTypeNode);
}
export function visitNodeArrayOfTypeElement(context: VisitorContext, nodes: NodeArray<TypeElement>, visitor: Visitor): NodeArray<TypeElement> {
export function visitNodeArrayOfTypeElement(context: VisitorContext, nodes: Array<TypeElement>, visitor: Visitor): NodeArray<TypeElement> {
return <NodeArray<TypeElement>>visitNodes(context, nodes, visitor, visitTypeElement);
}
export function visitNodeArrayOfTemplateSpan(context: VisitorContext, nodes: NodeArray<TemplateSpan>, visitor: Visitor): NodeArray<TemplateSpan> {
export function visitNodeArrayOfTemplateSpan(context: VisitorContext, nodes: Array<TemplateSpan>, visitor: Visitor): NodeArray<TemplateSpan> {
return <NodeArray<TemplateSpan>>visitNodes(context, nodes, visitor, visitTemplateSpan);
}
export function visitNodeArrayOfExpression(context: VisitorContext, nodes: NodeArray<Expression>, visitor: Visitor): NodeArray<Expression> {
export function visitNodeArrayOfExpression(context: VisitorContext, nodes: Array<Expression>, visitor: Visitor): NodeArray<Expression> {
return <NodeArray<Expression>>visitNodes(context, nodes, visitor, visitExpression);
}
export function visitNodeArrayOfObjectLiteralElement(context: VisitorContext, nodes: NodeArray<ObjectLiteralElement>, visitor: Visitor): NodeArray<ObjectLiteralElement> {
export function visitNodeArrayOfObjectLiteralElement(context: VisitorContext, nodes: Array<ObjectLiteralElement>, visitor: Visitor): NodeArray<ObjectLiteralElement> {
return <NodeArray<ObjectLiteralElement>>visitNodes(context, nodes, visitor, visitObjectLiteralElement);
}
export function visitNodeArrayOfJsxChild(context: VisitorContext, nodes: NodeArray<JsxChild>, visitor: Visitor): NodeArray<JsxChild> {
export function visitNodeArrayOfJsxChild(context: VisitorContext, nodes: Array<JsxChild>, visitor: Visitor): NodeArray<JsxChild> {
return <NodeArray<JsxChild>>visitNodes(context, nodes, visitor, visitJsxChild);
}
export function visitNodeArrayOfJsxAttributeOrJsxSpreadAttribute(context: VisitorContext, nodes: NodeArray<JsxAttribute | JsxSpreadAttribute>, visitor: Visitor): NodeArray<JsxAttribute | JsxSpreadAttribute> {
export function visitNodeArrayOfJsxAttributeOrJsxSpreadAttribute(context: VisitorContext, nodes: Array<JsxAttribute | JsxSpreadAttribute>, visitor: Visitor): NodeArray<JsxAttribute | JsxSpreadAttribute> {
return <NodeArray<JsxAttribute | JsxSpreadAttribute>>visitNodes(context, nodes, visitor, visitJsxAttributeOrJsxSpreadAttribute);
}
export function visitNodeArrayOfCaseOrDefaultClause(context: VisitorContext, nodes: NodeArray<CaseOrDefaultClause>, visitor: Visitor): NodeArray<CaseOrDefaultClause> {
export function visitNodeArrayOfCaseOrDefaultClause(context: VisitorContext, nodes: Array<CaseOrDefaultClause>, visitor: Visitor): NodeArray<CaseOrDefaultClause> {
return <NodeArray<CaseOrDefaultClause>>visitNodes(context, nodes, visitor, visitCaseOrDefaultClause);
}
export function visitNodeArrayOfHeritageClause(context: VisitorContext, nodes: NodeArray<HeritageClause>, visitor: Visitor): NodeArray<HeritageClause> {
export function visitNodeArrayOfHeritageClause(context: VisitorContext, nodes: Array<HeritageClause>, visitor: Visitor): NodeArray<HeritageClause> {
return <NodeArray<HeritageClause>>visitNodes(context, nodes, visitor, visitHeritageClause);
}
export function visitNodeArrayOfClassElement(context: VisitorContext, nodes: NodeArray<ClassElement>, visitor: Visitor): NodeArray<ClassElement> {
export function visitNodeArrayOfClassElement(context: VisitorContext, nodes: Array<ClassElement>, visitor: Visitor): NodeArray<ClassElement> {
return <NodeArray<ClassElement>>visitNodes(context, nodes, visitor, visitClassElement);
}
export function visitNodeArrayOfExpressionWithTypeArguments(context: VisitorContext, nodes: NodeArray<ExpressionWithTypeArguments>, visitor: Visitor): NodeArray<ExpressionWithTypeArguments> {
export function visitNodeArrayOfExpressionWithTypeArguments(context: VisitorContext, nodes: Array<ExpressionWithTypeArguments>, visitor: Visitor): NodeArray<ExpressionWithTypeArguments> {
return <NodeArray<ExpressionWithTypeArguments>>visitNodes(context, nodes, visitor, visitExpressionWithTypeArguments);
}
export function visitNodeArrayOfEnumMember(context: VisitorContext, nodes: NodeArray<EnumMember>, visitor: Visitor): NodeArray<EnumMember> {
export function visitNodeArrayOfEnumMember(context: VisitorContext, nodes: Array<EnumMember>, visitor: Visitor): NodeArray<EnumMember> {
return <NodeArray<EnumMember>>visitNodes(context, nodes, visitor, visitEnumMember);
}
export function visitNodeArrayOfImportOrExportSpecifier(context: VisitorContext, nodes: NodeArray<ImportOrExportSpecifier>, visitor: Visitor): NodeArray<ImportOrExportSpecifier> {
export function visitNodeArrayOfImportOrExportSpecifier(context: VisitorContext, nodes: Array<ImportOrExportSpecifier>, visitor: Visitor): NodeArray<ImportOrExportSpecifier> {
return <NodeArray<ImportOrExportSpecifier>>visitNodes(context, nodes, visitor, visitImportOrExportSpecifier);
}
export function visitNodeArrayOfJSDocType(context: VisitorContext, nodes: NodeArray<JSDocType>, visitor: Visitor): NodeArray<JSDocType> {
export function visitNodeArrayOfJSDocType(context: VisitorContext, nodes: Array<JSDocType>, visitor: Visitor): NodeArray<JSDocType> {
return <NodeArray<JSDocType>>visitNodes(context, nodes, visitor, visitJSDocType);
}
export function visitNodeArrayOfJSDocRecordMember(context: VisitorContext, nodes: NodeArray<JSDocRecordMember>, visitor: Visitor): NodeArray<JSDocRecordMember> {
export function visitNodeArrayOfJSDocRecordMember(context: VisitorContext, nodes: Array<JSDocRecordMember>, visitor: Visitor): NodeArray<JSDocRecordMember> {
return <NodeArray<JSDocRecordMember>>visitNodes(context, nodes, visitor, visitJSDocRecordMember);
}
export function visitNodeArrayOfJSDocTag(context: VisitorContext, nodes: NodeArray<JSDocTag>, visitor: Visitor): NodeArray<JSDocTag> {
export function visitNodeArrayOfJSDocTag(context: VisitorContext, nodes: Array<JSDocTag>, visitor: Visitor): NodeArray<JSDocTag> {
return <NodeArray<JSDocTag>>visitNodes(context, nodes, visitor, visitJSDocTag);
}
}

View File

@ -10,23 +10,25 @@ namespace ts.transform {
}
export class VisitorContext {
private generatedNameSet: Map<string> = {};
private getGeneratedNameForNode: (node: Node) => string;
private generatedNameSet: Map<string>;
private nodeToGeneratedName: string[];
private computedPropertyNamesToGeneratedNames: Identifier [] = [];
private tempFlagStack: number[] = [];
private hoistedVariableDeclarationsStack: VariableDeclaration[][] = [];
private hoistedFunctionDeclarationsStack: FunctionDeclaration[][] = [];
private statementsStack: Statement[][] = [];
private isPinnedOrTripleSlashComment = (comment: CommentRange) => this.isPinnedOrTripleSlashCommentWorker(comment);
public compilerOptions: CompilerOptions;
public currentSourceFile: SourceFile;
public resolver: EmitResolver;
constructor(currentSourceFile: SourceFile, resolver: EmitResolver, generatedNameSet: Map<string>, getGeneratedNameForNode: (node: Node) => string) {
constructor(compilerOptions: CompilerOptions, currentSourceFile: SourceFile, resolver: EmitResolver, generatedNameSet: Map<string>, nodeToGeneratedName: string[]) {
this.compilerOptions = compilerOptions;
this.currentSourceFile = currentSourceFile;
this.resolver = resolver;
this.generatedNameSet = generatedNameSet;
this.getGeneratedNameForNode = getGeneratedNameForNode;
this.nodeToGeneratedName = nodeToGeneratedName;
}
public pushLexicalEnvironment(): void {
@ -90,10 +92,23 @@ namespace ts.transform {
}
}
public getDeclarationName(node: Declaration) {
public getGeneratedNameForNode(node: Node) {
let id = getNodeId(node);
return this.nodeToGeneratedName[id] || (this.nodeToGeneratedName[id] = unescapeIdentifier(this.generateNameForNode(node)));
}
public nodeHasGeneratedName(node: Node) {
let id = getNodeId(node);
return this.nodeToGeneratedName[id] !== undefined;
}
public getDeclarationName(node: DeclarationStatement): Identifier;
public getDeclarationName(node: ClassLikeDeclaration): Identifier;
public getDeclarationName(node: Declaration): DeclarationName;
public getDeclarationName<T extends DeclarationName>(node: Declaration): T | Identifier {
let name = node.name;
if (name && !nodeIsSynthesized(name)) {
return factory.cloneNode(name);
return factory.cloneNode(<T>name);
}
else {
return factory.createIdentifier(
@ -101,6 +116,18 @@ namespace ts.transform {
);
}
}
public getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement) {
let expression: Expression = this.getDeclarationName(node);
if (!(member.flags & NodeFlags.Static)) {
expression = factory.createPropertyAccessExpression2(
expression,
factory.createIdentifier("prototype")
);
}
return expression;
}
public createUniqueIdentifier(baseName: string): Identifier {
let name = this.makeUniqueName(baseName);
@ -255,6 +282,61 @@ namespace ts.transform {
&& !hasProperty(this.currentSourceFile.identifiers, name)
&& !hasProperty(this.generatedNameSet, name);
}
private isUniqueLocalName(name: string, container: Node): boolean {
container = getOriginalNode(container);
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
return false;
}
}
}
return true;
}
private generateNameForNode(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
return this.makeUniqueName((<Identifier>node).text);
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
return this.generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
return this.generateNameForImportOrExportDeclaration(<ImportDeclaration | ExportDeclaration>node);
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ExportAssignment:
return this.generateNameForExportDefault();
case SyntaxKind.ClassExpression:
return this.generateNameForClassExpression();
case SyntaxKind.ComputedPropertyName:
return this.makeTempVariableName(TempFlags.Auto);
}
}
private generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
let name = node.name.text;
// Use module/enum name itself if it is unique, otherwise make a unique variation
return this.isUniqueLocalName(name, node) ? name : this.makeUniqueName(name);
}
private generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
let expr = getExternalModuleName(node);
let baseName = expr.kind === SyntaxKind.StringLiteral ?
escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
return this.makeUniqueName(baseName);
}
private generateNameForExportDefault() {
return this.makeUniqueName("default");
}
private generateNameForClassExpression() {
return this.makeUniqueName("class");
}
}
export type Visitor = (context: VisitorContext, node: Node) => Node;

View File

@ -80,7 +80,13 @@ namespace ts.transform {
case SyntaxKind.MethodDeclaration:
// TypeScript method declarations may be 'async', and may have decorators.
return transformMethodDeclaration(context, <MethodDeclaration>node);
case SyntaxKind.GetAccessor:
return transformGetAccessor(context, <GetAccessorDeclaration>node);
case SyntaxKind.SetAccessor:
return transformSetAccessor(context, <SetAccessorDeclaration>node);
default:
return transform.accept(context, node, transformNode);
}
@ -88,10 +94,6 @@ namespace ts.transform {
function transformClassDeclaration(context: VisitorContext, node: ClassDeclaration): ClassDeclaration {
// TODO(rbuckton): Handle decorators, for now we don't change the class and let the old emitter handle this
if (node.decorators) {
return node;
}
let baseTypeNode = getClassExtendsHeritageClauseElement(node);
let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNodeWorker);
let heritageClauses = visitNodeArrayOfHeritageClause(context, node.heritageClauses, transformNodeWorker);
@ -100,25 +102,41 @@ namespace ts.transform {
if (ctor) {
members = factory.createNodeArray([ctor, ...members]);
}
let newNode = factory.updateClassDeclaration(
node,
/*decorators*/ undefined,
/*modifiers*/ modifiers,
node.name,
/*typeParameters*/ undefined,
/*heritageClauses*/ heritageClauses,
/*members*/ members
);
if (node.decorators) {
let newNode = factory.createVariableStatement2(
<Identifier>context.getDeclarationName(node),
factory.createClassExpression2(
node.name ? context.createUniqueIdentifier(node.name.text) : undefined,
heritageClauses ? heritageClauses[0] : undefined,
members
),
/*location*/ node,
NodeFlags.Let
);
newNode.original = node;
context.emitStatement(newNode);
}
else {
let newNode = factory.updateClassDeclaration(
node,
/*decorators*/ undefined,
/*modifiers*/ modifiers,
node.name,
/*typeParameters*/ undefined,
/*heritageClauses*/ heritageClauses,
/*members*/ members
);
}
let staticPropertyAssignments = getInitializedProperties(node, /*isStatic*/ true);
if (staticPropertyAssignments) {
context.emitStatement(newNode);
emitPropertyDeclarations(context, node, staticPropertyAssignments);
return undefined;
}
return newNode;
// Transform any decorators into following statements
emitDecoratorsOfClass(context, node);
return undefined;
}
function transformClassExpression(context: VisitorContext, node: ClassExpression): LeftHandSideExpression {
@ -383,6 +401,376 @@ namespace ts.transform {
return missing;
}
return node;
let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode);
let name = transformPropertyName(context, node);
let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode);
let body = visitBlock(context, node.body, transformNode);
return factory.updateMethodDeclaration(
node,
/*decorators*/ undefined,
modifiers,
name,
/*typeParameters*/ undefined,
parameters,
/*typeNode*/ undefined,
body
);
}
function transformGetAccessor(context: VisitorContext, node: GetAccessorDeclaration) {
let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode);
let name = transformPropertyName(context, node);
let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode);
let body = visitBlock(context, node.body, transformNode);
return factory.updateGetAccessor(
node,
/*decorators*/ undefined,
modifiers,
name,
parameters,
/*typeNode*/ undefined,
body
);
}
function transformSetAccessor(context: VisitorContext, node: SetAccessorDeclaration) {
let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode);
let name = transformPropertyName(context, node);
let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode);
let body = visitBlock(context, node.body, transformNode);
return factory.updateSetAccessor(
node,
/*decorators*/ undefined,
modifiers,
name,
parameters,
/*typeNode*/ undefined,
body
);
}
function getExpressionForPropertyName(context: VisitorContext, container: Declaration): Expression {
let name = transformPropertyName(context, container);
if (isComputedPropertyName(name)) {
return name.expression;
}
else if (isStringLiteral(name)) {
return factory.createStringLiteral(name.text);
}
}
function transformPropertyName(context: VisitorContext, container: Declaration): PropertyName {
let name = context.getDeclarationName(container);
if (isComputedPropertyName(name)) {
if (context.nodeHasGeneratedName(name)) {
return factory.createIdentifier(context.getGeneratedNameForNode(name));
}
let expression = visitExpression(context, name.expression, transformNode);
if (nodeCanBeDecorated(container) && nodeIsDecorated(container)) {
let generatedName = factory.createIdentifier(context.getGeneratedNameForNode(name));
context.hoistVariableDeclaration(generatedName);
expression = factory.createAssignmentExpression(
generatedName,
expression
);
}
return factory.updateComputedPropertyName(
name,
expression
);
}
else if (isPropertyName(name)) {
return name;
}
Debug.fail("Binding patterns cannot be used as property names.");
}
function emitDecoratorsOfClass(context: VisitorContext, node: ClassLikeDeclaration) {
emitDecoratorsOfMembers(context, node, /*isStatic*/ false);
emitDecoratorsOfMembers(context, node, /*isStatic*/ true);
emitDecoratorsOfConstructor(context, node);
}
function emitDecoratorsOfMembers(context: VisitorContext, node: ClassLikeDeclaration, isStatic: boolean) {
for (let member of node.members) {
// only emit members in the correct group
if (isStatic !== ((member.flags & NodeFlags.Static) !== 0)) {
continue;
}
// skip members that cannot be decorated (such as the constructor)
// skip a member if it or any of its parameters are not decorated
if (!nodeCanBeDecorated(member) || !nodeOrChildIsDecorated(member)) {
continue;
}
emitDecoratorsOfMember(context, node, member);
}
}
function emitDecoratorsOfConstructor(context: VisitorContext, node: ClassLikeDeclaration) {
let decorators = node.decorators;
let constructor = getFirstConstructorWithBody(node);
let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
// skip decoration of the constructor if neither it nor its parameters are decorated
if (!decorators && !hasDecoratedParameters) {
return;
}
// Emit the call to __decorate. Given the class:
//
// @dec
// class C {
// }
//
// The emit for the class is:
//
// C = __decorate([dec], C);
//
let decoratorExpressions: Expression[] = [];
if (decorators) {
for (let decorator of decorators) {
decoratorExpressions.push(visitExpression(context, decorator.expression, transformNode))
}
}
if (constructor) {
emitDecoratorsOfParameters(context, constructor.parameters, decoratorExpressions);
}
if (context.compilerOptions.emitDecoratorMetadata) {
emitSerializedTypeMetadata(context, node, decoratorExpressions);
}
context.emitAssignmentStatement(
<Identifier>context.getDeclarationName(node),
factory.createCallExpression2(
factory.createIdentifier("__decorate"),
[
factory.createArrayLiteralExpression(decoratorExpressions),
<Identifier>context.getDeclarationName(node)
]
)
);
}
function emitDecoratorsOfMember(context: VisitorContext, node: ClassLikeDeclaration, member: ClassElement) {
let decorators: Decorator[];
let parameters: ParameterDeclaration[];
// skip an accessor declaration if it is not the first accessor
if (isAccessor(member) && member.body) {
let accessors = getAllAccessorDeclarations(node.members, member);
if (member !== accessors.firstAccessor) {
return;
}
// get the decorators from the first accessor with decorators
decorators = accessors.firstAccessor.decorators;
if (!decorators && accessors.secondAccessor) {
decorators = accessors.secondAccessor.decorators;
}
// we only decorate parameters of the set accessor
parameters = accessors.setAccessor
? accessors.setAccessor.parameters
: undefined;
}
else {
decorators = member.decorators;
// we only decorate the parameters here if this is a method
if (isMethodDeclaration(member) && member.body) {
parameters = member.parameters;
}
}
// Emit the call to __decorate. Given the following:
//
// class C {
// @dec method(@dec2 x) {}
// @dec get accessor() {}
// @dec prop;
// }
//
// The emit for a method is:
//
// Object.defineProperty(C.prototype, "method",
// __decorate([
// dec,
// __param(0, dec2),
// __metadata("design:type", Function),
// __metadata("design:paramtypes", [Object]),
// __metadata("design:returntype", void 0)
// ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
//
// The emit for an accessor is:
//
// Object.defineProperty(C.prototype, "accessor",
// __decorate([
// dec
// ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
//
// The emit for a property is:
//
// __decorate([
// dec
// ], C.prototype, "prop");
//
let decoratorExpressions: Expression[] = [];
if (decorators) {
for (let decorator of decorators) {
decoratorExpressions.push(visitExpression(context, decorator.expression, transformNode))
}
}
if (parameters) {
emitDecoratorsOfParameters(context, parameters, decoratorExpressions);
}
if (context.compilerOptions.emitDecoratorMetadata) {
emitSerializedTypeMetadata(context, node, decoratorExpressions);
}
let prefix = context.getClassMemberPrefix(node, member);
let decorateCallArguments: Expression[] = [
factory.createArrayLiteralExpression(decoratorExpressions),
prefix,
getExpressionForPropertyName(context, member)
];
let expression: Expression = factory.createCallExpression2(
factory.createIdentifier("__decorate"),
decorateCallArguments
);
if (!isPropertyDeclaration(member)) {
decorateCallArguments.push(
factory.createCallExpression2(
factory.createPropertyAccessExpression2(
factory.createIdentifier("Object"),
factory.createIdentifier("getOwnPropertyDescriptor")
),
[
prefix,
getExpressionForPropertyName(context, member)
]
)
);
expression = factory.createCallExpression2(
factory.createPropertyAccessExpression2(
factory.createIdentifier("Object"),
factory.createIdentifier("defineProperty")
),
[
prefix,
getExpressionForPropertyName(context, member),
expression
]
);
}
context.emitExpressionStatement(expression);
}
function emitDecoratorsOfParameters(context: VisitorContext, parameters: ParameterDeclaration[], expressions: Expression[]) {
for (let parameterIndex = 0; parameterIndex < parameters.length; parameterIndex++) {
let parameter = parameters[parameterIndex];
if (nodeIsDecorated(parameter)) {
for (let decorator of parameter.decorators) {
expressions.push(
factory.createCallExpression2(
factory.createIdentifier("__param"),
[
factory.createNumericLiteral2(parameterIndex),
visitExpression(context, decorator.expression, transformNode)
]
)
);
}
}
}
}
function emitSerializedTypeMetadata(context: VisitorContext, node: Declaration, expressions: Expression[]) {
if (shouldEmitTypeMetadata(node)) {
expressions.push(
factory.createCallExpression2(
factory.createIdentifier("__metadata"),
[
factory.createStringLiteral("design:type"),
// TODO
]
)
);
}
if (shouldEmitParamTypesMetadata(node)) {
expressions.push(
factory.createCallExpression2(
factory.createIdentifier("__metadata"),
[
factory.createStringLiteral("design:paramtypes"),
// TODO
]
)
);
}
if (shouldEmitReturnTypeMetadata(node)) {
expressions.push(
factory.createCallExpression2(
factory.createIdentifier("__metadata"),
[
factory.createStringLiteral("design:returntype"),
// TODO
]
)
);
}
}
function shouldEmitTypeMetadata(node: Declaration): boolean {
// 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:
case SyntaxKind.SetAccessor:
case SyntaxKind.PropertyDeclaration:
return true;
}
return false;
}
function shouldEmitReturnTypeMetadata(node: Declaration): boolean {
// 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;
}
return false;
}
function shouldEmitParamTypesMetadata(node: Declaration): boolean {
// 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:
case SyntaxKind.SetAccessor:
return true;
}
return false;
}
}

View File

@ -730,6 +730,8 @@ namespace ts {
export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern;
export type PropertyName = Identifier | LiteralExpression | ComputedPropertyName;
// @factoryhidden("decorators", false)
// @factoryhidden("modifiers", false)
export interface Declaration extends Node {
@ -817,30 +819,34 @@ namespace ts {
}
// @kind(SyntaxKind.PropertySignature)
// @factoryorder("decorators", "modifiers", "name", "questionToken", "type")
export interface PropertySignature extends TypeElement {
name: DeclarationName; // Declared property name
name: PropertyName;
// @factoryparam
questionToken?: Node; // Present on optional property
type?: TypeNode; // Optional type annotation
}
// @kind(SyntaxKind.PropertyDeclaration)
// @factoryorder("decorators", "modifiers", "name", "questionToken", "type", "initializer")
export interface PropertyDeclaration extends PropertySignature, ClassElement {
name: DeclarationName; // Declared property name
// @factoryorder("decorators", "modifiers", "name", "type", "initializer")
export interface PropertyDeclaration extends ClassElement {
// @factoryhidden
questionToken?: Node; // Present for use with reporting a grammar error
name: PropertyName;
type?: TypeNode;
initializer?: Expression; // Optional initializer
}
export interface ObjectLiteralElement extends Declaration {
_objectLiteralBrandBrand: any;
}
}
// @kind(SyntaxKind.PropertyAssignment)
// @factoryhidden("decorators", true)
// @factoryhidden("modifiers", true)
export interface PropertyAssignment extends ObjectLiteralElement {
_propertyAssignmentBrand: any;
name: DeclarationName;
name: PropertyName;
// @factoryparam
questionToken?: Node;
initializer: Expression;
@ -918,6 +924,7 @@ namespace ts {
// @factoryhidden("body", true)
// @factoryorder("decorators", "modifiers", "asteriskToken", "name", "questionToken", "typeParameters", "parameters", "type")
export interface MethodSignature extends SignatureDeclaration, TypeElement {
name: PropertyName;
}
// Note that a MethodDeclaration is considered both a ClassElement and an ObjectLiteralElement.
@ -934,6 +941,7 @@ namespace ts {
// @factoryhidden("body", false)
// @factoryorder("decorators", "modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body")
export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
name: PropertyName;
body?: Block;
}
@ -962,7 +970,7 @@ namespace ts {
// SyntaxKind.SetAccessor
export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
_accessorDeclarationBrand: any;
name: PropertyName;
// @visitor("visitBlockInNewLexicalScope")
body: Block;
}

View File

@ -594,7 +594,7 @@ namespace ts {
return false;
}
export function isAccessor(node: Node): boolean {
export function isAccessor(node: Node): node is AccessorDeclaration {
return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor);
}
@ -758,6 +758,15 @@ namespace ts {
}
}
export function isNodeDescendentOf(node: Node, ancestor: Node): boolean {
while (node) {
if (node === ancestor) return true;
node = node.parent;
}
return false;
}
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
if (node) {
switch (node.kind) {