ts-budgie
Version:
Converts TypeScript code to Budgie.
71 lines (52 loc) • 2.97 kB
text/typescript
import { CaseStyle, CommandNames, KeywordNames } from "budgie";
import * as path from "path";
import * as ts from "typescript";
import { BudgieLine } from "../../output/budgieLine";
import { Transformation } from "../../output/transformation";
import { createUnsupportedBudgieLine } from "../../output/unsupported";
import { NodeVisitor } from "../visitor";
const noBaseDirectoryComplaint = "Import directory goes out of bounds of the base directory.";
const noImportClauseComplaint = "Import declarations must import items.";
const noNamespaceImportsComplaint = "Namespace imports are not supported.";
const noPackageImportsComplaint = "Package imports are not yet supported.";
export class ImportDeclarationVisitor extends NodeVisitor {
public visit(node: ts.ImportDeclaration) {
return [Transformation.fromNode(node, this.sourceFile, [this.getTransformationContents(node)])];
}
private getTransformationContents(node: ts.ImportDeclaration) {
if (node.importClause === undefined || node.importClause.namedBindings === undefined) {
return createUnsupportedBudgieLine(noImportClauseComplaint);
}
if (node.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) {
return createUnsupportedBudgieLine(noNamespaceImportsComplaint);
}
const packagePath = this.parsePackagePath(node);
if (packagePath instanceof BudgieLine) {
return packagePath;
}
const importedItems = node.importClause.namedBindings.elements.map((element) => element.name.text);
return new BudgieLine(CommandNames.ImportLocal, ...packagePath, KeywordNames.Use, ...importedItems);
}
private parsePackagePath(node: ts.ImportDeclaration): string[] | BudgieLine {
const packagePathRaw = node.moduleSpecifier.getText(this.sourceFile);
if (packagePathRaw[1] !== ".") {
return createUnsupportedBudgieLine(noPackageImportsComplaint);
}
const sourceDir = path.dirname(this.sourceFile.fileName);
const packagePath = packagePathRaw.replace(/"|'|`/g, "");
const pathResolved = path.posix.join(sourceDir, packagePath);
if (pathResolved.indexOf(this.context.options.baseDirectory) === -1) {
return createUnsupportedBudgieLine(noBaseDirectoryComplaint);
}
const pathWithNamespace = path.posix.join(
this.context.options.outputNamespace,
pathResolved.substring(this.context.options.baseDirectory.length),
);
const pathWithNamespaceAndFileSplit = pathWithNamespace
.split(/\//g)
.filter((pathComponent) => pathComponent !== "")
.map((pathComponent) => this.casing.convertToCase(CaseStyle.PascalCase, [pathComponent]));
pathWithNamespaceAndFileSplit.pop();
return pathWithNamespaceAndFileSplit;
}
}