UNPKG

genezio

Version:

Command line utility to interact with Genezio infrastructure.

197 lines (196 loc) 9.2 kB
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 };