mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-13 06:20:23 -06:00
Partial transform for class decorators
This commit is contained in:
parent
f3d310360b
commit
4652f053b1
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user