ts-bakery
Version:
Baked dependency injection for Typescript.
508 lines • 25.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const typescript = require("typescript");
const TsClassDefinition_1 = require("../Types/TsClassDefinition");
const TsClassDefinitionType_1 = require("../Types/TsClassDefinitionType");
const TsEnumDefinition_1 = require("../Types/TsEnumDefinition");
const TsFile_1 = require("../Types/TsFile");
const TsFunctionCall_1 = require("../Types/TsFunctionCall");
const TsFunctionDefinition_1 = require("../Types/TsFunctionDefinition");
const TsImportDefinition_1 = require("../Types/TsImportDefinition");
const TsImportType_1 = require("../Types/TsImportType");
const TsNodeSequence_1 = require("../Types/TsNodeSequence");
const TsParameterDefinition_1 = require("../Types/TsParameterDefinition");
const TsPropertyDefinition_1 = require("../Types/TsPropertyDefinition");
const TsTypeAlias_1 = require("../Types/TsTypeAlias");
const TsTypeReference_1 = require("../Types/TsTypeReference");
const TsNodeConverter_1 = require("./TsNodeConverter");
class TsBakeryConverter {
constructor() {
this.nodeConverter = new TsNodeConverter_1.default();
}
convertPath(path) {
const sourceFile = this.nodeConverter.convertToSourceFile(path);
const file = this.convertSourceFile(sourceFile);
file.path = path;
return file;
}
convertSourceFile(sourceFile) {
const convertedFile = new TsFile_1.default(sourceFile);
for (const statement of sourceFile.statements) {
switch (statement.kind) {
case typescript.SyntaxKind.ImportDeclaration:
const importDeclaration = this.nodeConverter.convertToImportDeclaration(statement);
const importDefinition = this.convertImportDeclaration(importDeclaration);
importDefinition.parent = convertedFile;
convertedFile.imports.push(importDefinition);
break;
case typescript.SyntaxKind.EnumDeclaration:
const enumDeclaration = this.nodeConverter.convertToEnumDeclaration(statement);
const enumDefinition = this.convertEnumDeclaration(enumDeclaration);
enumDefinition.parent = convertedFile;
convertedFile.enums.push(enumDefinition);
break;
case typescript.SyntaxKind.InterfaceDeclaration:
const interfaceDeclaration = this.nodeConverter.convertToInterfaceDeclaration(statement);
const interfaceDefinition = this.convertInterfaceDeclaration(interfaceDeclaration);
interfaceDefinition.parent = convertedFile;
convertedFile.interfaces.push(interfaceDefinition);
break;
case typescript.SyntaxKind.ClassDeclaration:
const classDeclaration = this.nodeConverter.convertToClassDeclaration(statement);
const classDefinition = this.convertClassDeclaration(classDeclaration);
classDefinition.parent = convertedFile;
convertedFile.classes.push(classDefinition);
break;
case typescript.SyntaxKind.FunctionDeclaration:
const functionDeclaration = this.nodeConverter.convertToFunctionDeclaration(statement);
const functionDefintion = this.convertFunctionDeclaration(functionDeclaration);
functionDefintion.parent = convertedFile;
convertedFile.functions.push(functionDefintion);
break;
case typescript.SyntaxKind.ExportAssignment:
const exportAssignment = this.nodeConverter.convertToExportAssignment(statement);
convertedFile.export = this.convertExportAssignment(exportAssignment);
break;
case typescript.SyntaxKind.TypeAliasDeclaration:
//TODO: Implement
break;
case typescript.SyntaxKind.ImportEqualsDeclaration:
//TODO: Implement
break;
case typescript.SyntaxKind.FirstStatement:
case typescript.SyntaxKind.ExpressionStatement:
case typescript.SyntaxKind.SemicolonToken:
case typescript.SyntaxKind.IfStatement:
//ignore
break;
default:
console.error('Unknown content node.');
this.logNode(statement);
break;
}
}
return convertedFile;
}
convertImportDeclaration(importDeclaration) {
const tsImportDefinition = new TsImportDefinition_1.default(importDeclaration);
const importClause = importDeclaration.importClause;
if (importClause.namedBindings != null) {
const namedBindings = importClause.namedBindings;
if (namedBindings.kind == typescript.SyntaxKind.NamespaceImport) {
tsImportDefinition.importType = TsImportType_1.default.Namespace;
const nameSpaceImport = this.nodeConverter.convertToNamespaceImport(namedBindings);
const name = this.convertIdentifier(nameSpaceImport.name);
tsImportDefinition.names.push(name);
}
else if (namedBindings.kind == typescript.SyntaxKind.NamedImports) {
tsImportDefinition.importType = TsImportType_1.default.Named;
const namedImport = this.nodeConverter.convertToNamedImports(namedBindings);
for (const element of namedImport.elements) {
const importSpecifier = this.nodeConverter.convertToImportSpecifier(element);
const elementName = this.convertIdentifier(importSpecifier.name);
tsImportDefinition.names.push(elementName);
}
}
else {
console.warn('Unknown import type.');
}
}
else if (importClause.name != null) {
const name = this.convertIdentifier(importClause.name);
tsImportDefinition.importType = TsImportType_1.default.Identifier;
tsImportDefinition.names.push(name);
}
const moduleSpecifier = this.nodeConverter.convertToStringLiteral(importDeclaration.moduleSpecifier);
tsImportDefinition.modulePath = moduleSpecifier.text;
return tsImportDefinition;
}
convertEnumDeclaration(enumDeclaration) {
const tsEnumDefinition = new TsEnumDefinition_1.default(enumDeclaration);
tsEnumDefinition.name = this.convertIdentifier(enumDeclaration.name);
for (const member of enumDeclaration.members) {
switch (member.kind) {
case typescript.SyntaxKind.EnumMember:
const memberName = this.convertIdentifier(member.name);
tsEnumDefinition.members.push(memberName);
break;
default:
console.error('Unknown enum member.');
this.logNode(member);
}
}
return tsEnumDefinition;
}
convertInterfaceDeclaration(interfaceDeclaration) {
const tsInterfaceDefinition = new TsClassDefinition_1.default(interfaceDeclaration);
tsInterfaceDefinition.definitionType = TsClassDefinitionType_1.default.Interface;
tsInterfaceDefinition.name = this.convertIdentifier(interfaceDeclaration.name);
this.convertClassModifiers(interfaceDeclaration.modifiers, tsInterfaceDefinition);
for (const member of interfaceDeclaration.members) {
switch (member.kind) {
case typescript.SyntaxKind.PropertySignature:
const propertySignature = this.nodeConverter.convertToPropertySignature(member);
const property = this.convertPropertySignature(propertySignature);
property.parent = tsInterfaceDefinition;
tsInterfaceDefinition.properties.push(property);
break;
case typescript.SyntaxKind.MethodSignature:
const methodSignature = this.nodeConverter.convertToMethodSignature(member);
const method = this.convertMethodSignature(methodSignature);
method.parent = tsInterfaceDefinition;
tsInterfaceDefinition.methods.push(method);
break;
case typescript.SyntaxKind.GetAccessor:
const getAccessor = this.nodeConverter.convertToGetAccessorDeclaration(member);
const getter = this.convertAccessorDeclaration(getAccessor);
tsInterfaceDefinition.getters.push(getter);
break;
case typescript.SyntaxKind.SetAccessor:
const setAccessor = this.nodeConverter.convertToSetAccessorDeclaration(member);
const setter = this.convertAccessorDeclaration(setAccessor);
tsInterfaceDefinition.setters.push(setter);
break;
default:
console.warn('Unknown interface member.');
this.logNode(member);
}
}
return tsInterfaceDefinition;
}
convertPropertySignature(propertySignature) {
const property = new TsPropertyDefinition_1.default(propertySignature);
property.name = this.convertIdentifier(propertySignature.name);
property.type = this.convertTypeNode(propertySignature.type);
return property;
}
convertMethodSignature(methodSignature) {
const method = new TsFunctionDefinition_1.default(methodSignature);
method.name = this.convertIdentifier(methodSignature.name);
method.type = this.convertTypeNode(methodSignature.type);
return method;
}
convertAccessorDeclaration(accessor) {
const tsFunctionDefinition = new TsFunctionDefinition_1.default(accessor);
tsFunctionDefinition.name = this.convertIdentifier(accessor.name);
tsFunctionDefinition.type = this.convertTypeNode(accessor.type);
return tsFunctionDefinition;
}
convertParameterDeclaration(parameter) {
const paramDefinition = new TsParameterDefinition_1.default(parameter);
paramDefinition.name = this.convertIdentifier(parameter.name);
paramDefinition.type = this.convertTypeNode(parameter.type);
return paramDefinition;
}
convertTypeNode(node) {
if (node == null) {
return null;
}
switch (node.kind) {
case typescript.SyntaxKind.StringKeyword:
const stringType = new TsTypeReference_1.TsSimpleTypeReference();
stringType.name = 'string';
return stringType;
case typescript.SyntaxKind.VoidKeyword:
const voidType = new TsTypeReference_1.TsSimpleTypeReference();
voidType.name = 'void';
return voidType;
case typescript.SyntaxKind.BooleanKeyword:
const booleanType = new TsTypeReference_1.TsSimpleTypeReference();
booleanType.name = 'boolean';
return booleanType;
case typescript.SyntaxKind.NumberKeyword:
const numberType = new TsTypeReference_1.TsSimpleTypeReference();
numberType.name = 'number';
return numberType;
case typescript.SyntaxKind.AnyKeyword:
const anyType = new TsTypeReference_1.TsSimpleTypeReference();
anyType.name = 'any';
return anyType;
case typescript.SyntaxKind.UnknownKeyword:
const unknownType = new TsTypeReference_1.TsSimpleTypeReference();
unknownType.name = 'unknown';
return unknownType;
case typescript.SyntaxKind.ArrayType:
const a = node;
const arrayType = new TsTypeReference_1.TsArrayTypeReference();
arrayType.type = this.convertTypeNode(a.elementType);
return arrayType;
case typescript.SyntaxKind.TypeReference:
const typeReferenceNode = node;
return this.convertTypeReferenceNode(typeReferenceNode);
case typescript.SyntaxKind.FunctionType:
const ftType = node;
return this.convertFunctionTypeNode(ftType);
case typescript.SyntaxKind.ConstructorType:
const cType = node;
return this.convertConstructorTypeNode(cType);
case typescript.SyntaxKind.TypeOperator:
const topType = node;
const topReference = new TsTypeReference_1.TsTypeOperatorTypeReference();
topReference.type = this.convertTypeNode(topType.type);
return topReference;
}
return null;
}
convertNodeToTypeReference(node) {
if (typescript.isIdentifier(node)) {
const classTypeReference = new TsTypeReference_1.TsClassTypeReference();
classTypeReference.name = this.convertIdentifier(node);
return classTypeReference;
}
if (typescript.isPropertyAccessExpression(node)) {
const pae = node;
const qualifiedTypeReference = new TsTypeReference_1.TsQualifiedTypeReference();
if (!typescript.isIdentifier(pae.expression)) {
return null;
}
qualifiedTypeReference.left = this.convertIdentifier(pae.expression);
qualifiedTypeReference.right = this.convertIdentifier(pae.name);
return qualifiedTypeReference;
}
if (typescript.isTypeNode(node)) {
return this.convertTypeNode(node);
}
return null;
}
convertFunctionTypeNode(node) {
const typeReference = new TsTypeReference_1.TsFunctionTypeReference();
typeReference.type = this.convertTypeNode(node.type);
for (const parameterDeclaration of node.parameters) {
const parameterDefinition = this.convertParameterDeclaration(parameterDeclaration);
typeReference.parameters.push(parameterDefinition);
}
return typeReference;
}
convertConstructorTypeNode(node) {
const typeReference = new TsTypeReference_1.TsConstructorTypeReference();
typeReference.type = this.convertTypeNode(node.type);
for (const parameter of node.parameters) {
const parameterDeclaration = this.convertParameterDeclaration(parameter);
typeReference.parameters.push(parameterDeclaration);
}
return typeReference;
}
convertTypeReferenceNode(node) {
if (node.typeName.kind == typescript.SyntaxKind.Identifier) {
const typeReference = new TsTypeReference_1.TsClassTypeReference();
typeReference.name = this.convertIdentifier(node.typeName);
return typeReference;
}
else if (node.typeName.kind == typescript.SyntaxKind.QualifiedName) {
const typeReference = new TsTypeReference_1.TsQualifiedTypeReference();
typeReference.left = this.convertIdentifier(node.typeName.left);
typeReference.right = this.convertIdentifier(node.typeName.right);
return typeReference;
}
console.error('Unknown type.');
return null;
}
convertClassDeclaration(classDeclaration) {
const tsClassDefinition = new TsClassDefinition_1.default(classDeclaration);
tsClassDefinition.name = this.convertIdentifier(classDeclaration.name);
if (typescript.canHaveDecorators(classDeclaration)) {
const decorators = typescript.getDecorators(classDeclaration);
if (decorators != null) {
for (const decorator of decorators) {
const tsFunctionCall = this.convertDecorator(decorator);
tsClassDefinition.decorators.push(tsFunctionCall);
}
}
}
if (typescript.canHaveModifiers(classDeclaration)) {
const modifiers = typescript.getModifiers(classDeclaration);
this.convertClassModifiers(modifiers, tsClassDefinition);
}
if (classDeclaration.members != null) {
for (const member of classDeclaration.members) {
switch (member.kind) {
case typescript.SyntaxKind.Constructor:
const constructorDeclaration = this.nodeConverter.convertToConstructorDeclaration(member);
const constructorDefinition = this.convertConstructorDeclaration(constructorDeclaration);
tsClassDefinition.classConstructor = constructorDefinition;
constructorDefinition.parent = tsClassDefinition;
break;
case typescript.SyntaxKind.PropertyDeclaration:
const propertyDeclaration = this.nodeConverter.convertToPropertyDeclaration(member);
const propertyDefinition = this.convertPropertyDeclaration(propertyDeclaration);
tsClassDefinition.properties.push(propertyDefinition);
propertyDefinition.parent = tsClassDefinition;
break;
case typescript.SyntaxKind.MethodDeclaration:
const methodDeclaration = this.nodeConverter.convertToMethodDeclaration(member);
const methodDefinition = this.convertMethodDeclaration(methodDeclaration);
tsClassDefinition.methods.push(methodDefinition);
methodDefinition.parent = tsClassDefinition;
break;
case typescript.SyntaxKind.GetAccessor:
const getAccessor = this.nodeConverter.convertToGetAccessorDeclaration(member);
const getter = this.convertAccessorDeclaration(getAccessor);
tsClassDefinition.getters.push(getter);
getter.parent = tsClassDefinition;
break;
case typescript.SyntaxKind.SetAccessor:
const setAccessor = this.nodeConverter.convertToSetAccessorDeclaration(member);
const setter = this.convertAccessorDeclaration(setAccessor);
tsClassDefinition.setters.push(setter);
setter.parent = tsClassDefinition;
break;
case typescript.SyntaxKind.SemicolonClassElement:
// Ignore
break;
default:
console.warn('Unknown class member.');
this.logNode(member);
break;
}
}
}
if (classDeclaration.heritageClauses != null) {
for (const clause of classDeclaration.heritageClauses) {
const heritageClause = this.nodeConverter.convertToHeritageClause(clause);
const heritageTypes = this.convertHeritageClause(heritageClause);
tsClassDefinition.heritageClauses.push(...heritageTypes);
}
}
return tsClassDefinition;
}
convertClassModifiers(modifiers, tsClassDefinition) {
if (modifiers == null) {
return;
}
for (const modifier of modifiers) {
switch (modifier.kind) {
case typescript.SyntaxKind.DefaultKeyword:
tsClassDefinition.isDefault = true;
break;
case typescript.SyntaxKind.ExportKeyword:
tsClassDefinition.isExported = true;
break;
case typescript.SyntaxKind.AbstractKeyword:
tsClassDefinition.isAbstract = true;
break;
default:
console.warn('Unknown modifier');
this.logNode(modifier);
}
}
}
convertDecorator(decorator) {
const tsFunctionCall = new TsFunctionCall_1.default(decorator);
switch (decorator.expression.kind) {
case typescript.SyntaxKind.CallExpression:
const expression = this.nodeConverter.convertToCallExpression(decorator.expression);
tsFunctionCall.name = this.convertIdentifier(expression.expression);
for (const arg of expression.arguments) {
const argString = this.nodeConverter.convertToStringLiteral(arg);
tsFunctionCall.arguments.push(argString.text);
}
break;
case typescript.SyntaxKind.Identifier:
tsFunctionCall.name = this.convertIdentifier(decorator.expression);
break;
default:
throw new Error('Unable to convert decorator');
}
return tsFunctionCall;
}
convertPropertyDeclaration(propertyDeclaration) {
const propertyDefinition = new TsPropertyDefinition_1.default(propertyDeclaration);
propertyDefinition.name = this.convertIdentifier(propertyDeclaration.name);
propertyDefinition.type = this.convertTypeNode(propertyDeclaration.type);
return propertyDefinition;
}
convertConstructorDeclaration(constructorDeclaration) {
return this.convertFunctionLikeDeclaration(constructorDeclaration);
}
convertFunctionDeclaration(functionDeclaration) {
return this.convertFunctionLikeDeclaration(functionDeclaration);
}
convertMethodDeclaration(methodDeclaration) {
return this.convertFunctionLikeDeclaration(methodDeclaration);
}
convertHeritageClause(heritageClause) {
const names = [];
for (const heritageType of heritageClause.types) {
const heritageName = this.convertIdentifier(heritageType.expression);
names.push(heritageName);
}
return names;
}
convertExpression(expression) {
const sequence = new TsNodeSequence_1.default();
this.buildExpressionSequence(expression, sequence);
return sequence;
}
buildExpressionSequence(expression, sequence) {
switch (expression.kind) {
case typescript.SyntaxKind.CallExpression:
const callExpression = expression;
sequence.addFirst(callExpression);
this.buildExpressionSequence(callExpression.expression, sequence);
break;
case typescript.SyntaxKind.PropertyAccessExpression:
const propertyAccessExpression = expression;
sequence.addFirst(propertyAccessExpression);
this.buildExpressionSequence(propertyAccessExpression.expression, sequence);
break;
case typescript.SyntaxKind.BinaryExpression:
case typescript.SyntaxKind.Identifier:
case typescript.SyntaxKind.VariableStatement:
case typescript.SyntaxKind.ThisKeyword:
case typescript.SyntaxKind.StringLiteral:
sequence.addFirst(expression);
break;
default:
console.warn('Unable to convert ExpressionSequence with kind ' + typescript.SyntaxKind[expression.kind]);
break;
}
}
convertExportAssignment(exportAssignment) {
return this.convertIdentifier(exportAssignment.expression);
}
convertTypeAliasDeclaration(typeAlias) {
const tsAlias = new TsTypeAlias_1.default();
tsAlias.name = this.convertIdentifier(typeAlias.name);
tsAlias.type = this.convertTypeNode(typeAlias.type);
return tsAlias;
}
convertIdentifier(node) {
if (node == null) {
return null;
}
if (node.kind == typescript.SyntaxKind.ComputedPropertyName) {
const computedPropertyName = this.nodeConverter.convertToComputedPropertyName(node);
return this.convertIdentifier(computedPropertyName.expression);
}
return this.nodeConverter.convertToIdentifier(node).escapedText;
}
convertFunctionLikeDeclaration(functionLikeDeclaration) {
const tsFunctionDefinition = new TsFunctionDefinition_1.default(functionLikeDeclaration);
tsFunctionDefinition.name = this.convertIdentifier(functionLikeDeclaration.name);
tsFunctionDefinition.type = this.convertTypeNode(functionLikeDeclaration.type);
for (let p of functionLikeDeclaration.parameters) {
const param = this.convertParameterDeclaration(p);
tsFunctionDefinition.addParameter(param);
}
if (!typescript.canHaveDecorators(functionLikeDeclaration)) {
return tsFunctionDefinition;
}
const decorators = typescript.getDecorators(functionLikeDeclaration);
if (decorators == null) {
return tsFunctionDefinition;
}
for (const d of decorators) {
const decorator = this.convertDecorator(d);
tsFunctionDefinition.decorators.push(decorator);
}
return tsFunctionDefinition;
}
logNode(node) {
console.log('/--- NODE BEGIN ---/');
console.log(typescript.SyntaxKind[node.kind]);
console.log(node);
console.log('/--- NODE END ---/');
}
}
exports.default = TsBakeryConverter;
//# sourceMappingURL=TsBakeryConverter.js.map