UNPKG

@rightcapital/php-parser

Version:

TypeScript types for PHP Parser JSON representation

141 lines (140 loc) 7.6 kB
#!/usr/bin/env ts-node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const node_fs_1 = require("node:fs"); const os = require("node:os"); const node_path_1 = require("node:path"); const path = require("node:path"); const _ = require("lodash"); const Mustache = require("mustache"); const constants_1 = require("../constants"); const cli_helpers_1 = require("./helpers/cli-helpers"); const file_path_helpers_1 = require("./helpers/file-path-helpers"); const node_retriever_helpers_1 = require("./helpers/node-retriever-helpers"); const type_generation_helpers_1 = require("./helpers/type-generation-helpers"); const PHP_PARSER_ROOT_PATH = (0, node_path_1.resolve)(constants_1.PROJECT_ROOT, 'vendor/nikic/php-parser/lib/PhpParser'); const PHP_PARSER_NODE_DIRECTORY_PATH = (0, node_path_1.resolve)(PHP_PARSER_ROOT_PATH, 'Node'); class GenerateType { static main() { const typesRootPath = file_path_helpers_1.FilePathHelpers.getTypesRootPath(); const nodeTypeRootPath = (0, node_path_1.resolve)(typesRootPath, 'node'); (0, node_fs_1.mkdirSync)(GenerateType.cliContext.temporaryNodeTypeRootPath, { recursive: true, }); GenerateType.walkSync(PHP_PARSER_NODE_DIRECTORY_PATH, GenerateType.generateTypeForNodeByFile); const typesFileName = (0, node_path_1.resolve)(typesRootPath, 'types.ts'); const temporaryTypesFileName = (0, node_path_1.resolve)(typesRootPath, 'tmp-types.ts'); (0, node_fs_1.writeFileSync)(temporaryTypesFileName, type_generation_helpers_1.TypeGenerationHelpers.generateCombinationTypesFromNodes(GenerateType.cliContext), { encoding: 'utf8' }); (0, node_fs_1.rmSync)(nodeTypeRootPath, { recursive: true, force: true }); (0, node_fs_1.rmSync)(typesFileName, { force: true }); (0, node_fs_1.renameSync)(GenerateType.cliContext.temporaryNodeTypeRootPath, nodeTypeRootPath); (0, node_fs_1.renameSync)(temporaryTypesFileName, typesFileName); } static generateTypeForNodeByFile(filePath) { const fileRelativePath = path.relative(PHP_PARSER_NODE_DIRECTORY_PATH, filePath); const filePathParts = filePath.split('/'); const directoryRelativePath = fileRelativePath .split('/') .slice(0, -1) .map((part) => _.kebabCase(part)) .join('/'); const fileName = _.kebabCase(fileRelativePath .split('/') .pop() .replace(/\.php$/, '')); const ast = cli_helpers_1.CliHelpers.parsePhpFileToAst(filePath); const classNode = node_retriever_helpers_1.NodeRetrieverHelpers.getRootClassNode(ast); const uses = node_retriever_helpers_1.NodeRetrieverHelpers.getUsesMap(ast); if (classNode) { const properties = node_retriever_helpers_1.NodeRetrieverHelpers.getPropertiesFromClassNode(classNode, filePathParts, fileRelativePath, uses); const uniqueImportDeclarationGeneratedStrings = [ ...new Set(properties .map((property) => property.typeGenerationPackage .importDeclarationGeneratedStrings) .flat()), ]; const parentNodeFilePath = file_path_helpers_1.FilePathHelpers.getFilePathFromNameNodeParts(node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name), classNode.extends.nodeType, filePathParts, uses); const fullyQualifiedNodeName = file_path_helpers_1.FilePathHelpers.getFullyQualifiedNodeNameByFilePath(fileRelativePath); const parentNodeName = node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name).at(-1); const fullyQualifiedParentNodeName = file_path_helpers_1.FilePathHelpers.getFullyQualifiedParentNodeNameByFilePath(fileRelativePath, parentNodeFilePath, parentNodeName); const nodeOutput = { fileName, filePath: path.join(directoryRelativePath, fileName), filePathParts, fullyQualifiedNodeName, fullyQualifiedParentNodeName, nodeName: classNode.name.name, parentNodeParts: node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name), parentNodeName, parentNodeFilePath, properties, uniqueImportDeclarationGeneratedStrings, nodeType: node_retriever_helpers_1.NodeRetrieverHelpers.getGetTypeFunctionReturnValue(classNode), uses, }; GenerateType.appendNodeToContext(nodeOutput); const templateFileName = path.resolve(constants_1.SRC_ROOT, 'templates/php-parser-node.mustache'); const templateFileContent = (0, node_fs_1.readFileSync)(templateFileName, 'utf8'); try { if (directoryRelativePath) { (0, node_fs_1.mkdirSync)(path.resolve(GenerateType.cliContext.temporaryNodeTypeRootPath, directoryRelativePath), { recursive: true, }); } } finally { (0, node_fs_1.writeFileSync)((0, node_path_1.resolve)(GenerateType.cliContext.temporaryNodeTypeRootPath, directoryRelativePath, `${fileName}.ts`), Mustache.render(templateFileContent, nodeOutput)); } } } static walkSync(directoryPath, callback) { const fileNames = (0, node_fs_1.readdirSync)(directoryPath); fileNames.forEach((fileName) => { const filePath = path.join(directoryPath, fileName); const stats = (0, node_fs_1.statSync)(filePath); if (stats.isDirectory()) { GenerateType.walkSync(filePath, callback); } else if (stats.isFile()) { callback(filePath); } }); } static appendNodeToContext(node) { GenerateType.cliContext.allNodeNames.push(node.nodeName); if (!(node.fullyQualifiedNodeName in GenerateType.cliContext.allNodes)) { GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName] = { name: node.fullyQualifiedNodeName, subNodeNames: [], parentNodeName: '', filePath: '', properties: [], nodeType: '', }; } if (!(node.fullyQualifiedParentNodeName in GenerateType.cliContext.allNodes)) { GenerateType.cliContext.allNodes[node.fullyQualifiedParentNodeName] = { name: node.fullyQualifiedParentNodeName, subNodeNames: [], parentNodeName: '', filePath: '', properties: [], nodeType: '', }; } GenerateType.cliContext.allNodes[node.fullyQualifiedParentNodeName].subNodeNames.push(node.fullyQualifiedNodeName); GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].parentNodeName = node.fullyQualifiedParentNodeName; GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].filePath = node.filePath; GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].properties = node.properties; GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].nodeType = node.nodeType; } } GenerateType.cliContext = { allNodeNames: [], allNodes: {}, temporaryNodeTypeRootPath: (0, node_path_1.resolve)(os.tmpdir(), 'node'), }; GenerateType.main();