in src/decorator_downlevel_transformer.ts [468:536]
function transformClassDeclaration(classDecl: ts.ClassDeclaration): ts.ClassDeclaration {
const newMembers: ts.ClassElement[] = [];
const decoratedProperties = new Map<string, ts.Decorator[]>();
let classParameters: ParameterDecorationInfo[]|null = null;
for (const member of classDecl.members) {
switch (member.kind) {
case ts.SyntaxKind.PropertyDeclaration:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
case ts.SyntaxKind.MethodDeclaration: {
const [name, newMember, decorators] = transformClassElement(
member as ts.PropertyDeclaration | ts.GetAccessorDeclaration |
ts.SetAccessorDeclaration | ts.MethodDeclaration);
newMembers.push(newMember);
if (name) decoratedProperties.set(name, decorators);
continue;
}
case ts.SyntaxKind.Constructor: {
const ctor = member as ts.ConstructorDeclaration;
if (!ctor.body) break;
const [newMember, parametersInfo] =
transformConstructor(member as ts.ConstructorDeclaration);
classParameters = parametersInfo;
newMembers.push(newMember);
continue;
}
default:
break;
}
newMembers.push(ts.visitEachChild(member, visitor, context));
}
const decorators = classDecl.decorators || [];
const decoratorsToLower = [];
const decoratorsToKeep: ts.Decorator[] = [];
for (const decorator of decorators) {
if (shouldLower(decorator, typeChecker)) {
decoratorsToLower.push(extractMetadataFromSingleDecorator(decorator, diagnostics));
} else {
decoratorsToKeep.push(decorator);
}
}
if (decoratorsToLower.length) {
newMembers.push(createDecoratorClassProperty(decoratorsToLower));
}
if (classParameters) {
if ((decoratorsToLower.length) || classParameters.some(p => !!p.decorators.length)) {
// emit ctorParameters if the class was decoratored at all, or if any of its ctors
// were classParameters
newMembers.push(createCtorParametersClassProperty(
diagnostics, entityNameToExpression, classParameters));
}
}
if (decoratedProperties.size) {
newMembers.push(createPropDecoratorsClassProperty(diagnostics, decoratedProperties));
}
const newDecorators = decoratorsToKeep.length ?
ts.factory.createNodeArray(decoratorsToKeep) :
undefined;
return ts.factory.updateClassDeclaration(
classDecl, newDecorators, classDecl.modifiers, classDecl.name,
classDecl.typeParameters, classDecl.heritageClauses,
ts.setTextRange(
ts.factory.createNodeArray(
newMembers, classDecl.members.hasTrailingComma),
classDecl.members));
}