genezio
Version:
Command line utility to interact with Genezio infrastructure.
197 lines (196 loc) • 9.2 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _AstGenerator_instances, _AstGenerator_compileGenezioKotlinAstExtractor, _AstGenerator_parseList, _AstGenerator_parseMap, _AstGenerator_parseCoroutine, _AstGenerator_mapTypesToParamType;
import os from "os";
import path from "path";
import fs from "fs";
import { AstNodeType, MethodKindEnum, SourceType, } from "../../models/genezioModels.js";
import { checkIfKotlinReqsAreInstalled } from "../../utils/kotlin.js";
import { createTemporaryFolder, fileExists } from "../../utils/file.js";
import { runNewProcess, runNewProcessWithResult } from "../../utils/process.js";
import { default as fsExtra } from "fs-extra";
import { UserError } from "../../errors.js";
export class AstGenerator {
constructor() {
_AstGenerator_instances.add(this);
}
async generateAst(input) {
// Check if java sdk, kotlin and gradle are installed
checkIfKotlinReqsAreInstalled();
// Check if the kotlin ast extractor is compiled and installed in home.
const genezioAstGeneratorPath = path.join(os.homedir(), ".genezio", ".kotlin_ast_generator", "ast-generator.jar");
const compiled = await fileExists(genezioAstGeneratorPath);
if (!compiled) {
await __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_compileGenezioKotlinAstExtractor).call(this);
}
// Run the Kotlin AST generator program
const classAbsolutePath = path.resolve(input.class.path);
const result = await runNewProcessWithResult(`java -jar ${genezioAstGeneratorPath} ${classAbsolutePath}`);
// Map serialization workaround because JavaScript...
const ast = {
projectClasses: {},
};
ast.projectClasses = new Map(Object.entries(JSON.parse(result).projectClasses));
// Convert the Kotlin AST to Genezio AST
const mainClass = ast.projectClasses.get(input.class.name || "");
if (!mainClass) {
throw new UserError(`No class named ${input.class.name} found. Check in the 'genezio.yaml' file and make sure the path is correct.`);
}
const genezioClass = {
type: AstNodeType.ClassDefinition,
name: mainClass.className,
methods: mainClass.classMethods.map((m) => {
return {
type: AstNodeType.MethodDefinition,
name: m.funcName,
params: m.funcParams.map((p) => {
return {
type: AstNodeType.ParameterDefinition,
name: p.paramName,
paramType: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, p.paramType),
rawType: p.paramType,
};
}),
returnType: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, m.funcRetType),
static: false,
kind: MethodKindEnum.method,
};
}),
};
const body = [genezioClass];
// Parse other data classes
ast.projectClasses.forEach((c) => {
// Skip main class defined earlier
if (c.className === mainClass.className) {
return;
}
const genezioClass = {
type: AstNodeType.StructLiteral,
name: c.className,
path: c.className,
typeLiteral: {
type: AstNodeType.TypeLiteral,
properties: c.classConstructor.map((p) => {
return {
name: p.paramName,
type: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, p.paramType),
rawType: p.paramType,
optional: false,
};
}),
},
};
body.push(genezioClass);
});
return {
program: {
body,
originalLanguage: "kotlin",
sourceType: SourceType.module,
},
};
}
}
_AstGenerator_instances = new WeakSet(), _AstGenerator_compileGenezioKotlinAstExtractor = async function _AstGenerator_compileGenezioKotlinAstExtractor() {
const folder = await createTemporaryFolder();
const ast_clone_success = await runNewProcess("git clone --quiet https://github.com/Genez-io/kotlin-ast.git .", folder);
if (!ast_clone_success) {
throw new UserError("Error: Failed to clone Kotlin AST parser repository to " +
folder +
" temporary folder!");
}
const gradlew = "." + path.sep + "gradlew" + (os.platform() === "win32" ? ".bat" : "");
const gradle_build_success = await runNewProcess(gradlew + " --quiet fatJar", folder);
if (!gradle_build_success) {
throw new UserError('Error: Failed to build Kotlin AST parser while executing "./gradlew --quiet fatJar" in ' +
folder +
" temporary folder!");
}
if (!fs.existsSync(path.join(os.homedir(), ".genezio", ".kotlin_ast_generator"))) {
fs.mkdirSync(path.join(os.homedir(), ".genezio", ".kotlin_ast_generator"));
}
const ast_gen_path = path.join(folder, "app", "build", "libs", "app-standalone.jar");
const ast_gen_dest = path.join(os.homedir(), ".genezio", ".kotlin_ast_generator", "ast-generator.jar");
fsExtra.copyFileSync(ast_gen_path, ast_gen_dest);
}, _AstGenerator_parseList = function _AstGenerator_parseList(type) {
const listToken = "List<";
if (type.startsWith(listToken)) {
const extractedString = type.substring(listToken.length, type.length - 1);
return {
type: AstNodeType.ArrayType,
generic: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, extractedString),
};
}
else {
return undefined;
}
}, _AstGenerator_parseMap = function _AstGenerator_parseMap(type) {
const mapToken = "Map<";
if (type.startsWith(mapToken)) {
const cleanedType = type.replace(" ", "");
const extractedString = cleanedType.substring(mapToken.length, cleanedType.length - 1);
const components = extractedString.split(",");
const key = components[0];
const value = components.slice(1).join(",");
return {
type: AstNodeType.MapType,
genericKey: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, key),
genericValue: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, value),
};
}
}, _AstGenerator_parseCoroutine = function _AstGenerator_parseCoroutine(type) {
const promiseToken = "Future<";
if (type.startsWith(promiseToken)) {
const extractedString = type.substring(promiseToken.length, type.length - 1);
return {
type: AstNodeType.PromiseType,
generic: __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_mapTypesToParamType).call(this, extractedString),
};
}
}, _AstGenerator_mapTypesToParamType = function _AstGenerator_mapTypesToParamType(type) {
const list = __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_parseList).call(this, type);
if (list) {
return list;
}
const map = __classPrivateFieldGet(this, _AstGenerator_instances, "m", _AstGenerator_parseMap).call(this, type);
if (map) {
return map;
}
switch (type) {
case "String":
return {
type: AstNodeType.StringLiteral,
};
case "Int":
return {
type: AstNodeType.IntegerLiteral,
};
case "Double":
return {
type: AstNodeType.DoubleLiteral,
};
case "Boolean":
return {
type: AstNodeType.BooleanLiteral,
};
case "Void": {
return {
type: AstNodeType.VoidLiteral,
};
}
case "Any":
return {
type: AstNodeType.AnyLiteral,
};
default:
return {
type: AstNodeType.CustomNodeLiteral,
rawValue: type,
};
}
};
const supportedExtensions = ["kt"];
export default { supportedExtensions, AstGenerator };