UNPKG

@hadss/hmrouter-plugin

Version:

HMRouter Compiler Plugin

218 lines (217 loc) 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConstantResolver = void 0; const ts_morph_1 = require("ts-morph"); const framework_1 = require("../../../framework"); const constants_1 = require("../../constants"); const ImportAnalyzer_1 = require("./ImportAnalyzer"); const PluginError_1 = require("../../error/PluginError"); class ConstantResolver { constructor(modulePath) { this.importMapCache = new Map(); this.modulePath = modulePath; } resolveConstant(value, sourceFile, filePath) { if (value.type === 'constant') { return this.parseConstantValue(framework_1.TsAstUtil.getSourceFile(value.variableFilePath), value.variableName); } else if (value.type === 'object') { return this.parseConstantValue(framework_1.TsAstUtil.getSourceFile(value.variableFilePath), value.variableName, value.propertyName); } else if (value.type === 'array') { return value.value.map((item) => { return this.resolveConstant(item, sourceFile, filePath); }); } else { return value; } } resolvePropertyValue(value, sourceFile, filePath) { switch (value.getKind()) { case ts_morph_1.SyntaxKind.Identifier: if (value.getText() === 'undefined') { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.INVALID_STRING_VALUE, '', filePath); } return { type: 'constant', variableName: value.getText(), variableFilePath: this.getVariableFilePath(value.getText(), sourceFile, filePath), }; case ts_morph_1.SyntaxKind.PropertyAccessExpression: return { type: 'object', variableName: value.getExpression().getText(), propertyName: value?.getName(), variableFilePath: this.getVariableFilePath(value?.getExpression().getText(), sourceFile, filePath), }; case ts_morph_1.SyntaxKind.ArrayLiteralExpression: return { type: 'array', value: value .asKind(ts_morph_1.SyntaxKind.ArrayLiteralExpression) ?.getElements() .map((item) => this.resolvePropertyValue(item, sourceFile, filePath)), }; default: return this.parsePrimitiveValue(value); } } getVariableFilePath(variableName, sourceFile, filePath) { let resultPath = ''; const classesNames = sourceFile.getClasses().map((classes) => classes.getName()); const variableNames = sourceFile .getVariableDeclarations() .map((variableDeclaration) => variableDeclaration.getName()); if (classesNames.includes(variableName) || variableNames.includes(variableName)) { return filePath; } let importMap; if (this.importMapCache.has(filePath)) { importMap = this.importMapCache.get(filePath); } else { importMap = ImportAnalyzer_1.ImportAnalyzer.analyzeImports(sourceFile); this.importMapCache.set(filePath, importMap); } for (const [importPath, importNames] of importMap.entries()) { if (importNames.includes(variableName)) { const currentDir = framework_1.PluginFileUtil.pathResolve(filePath, constants_1.FilePathConstants.PARENT_DELIMITER); const tempFilePath = framework_1.PluginFileUtil.pathResolve(currentDir, importPath + constants_1.FilePathConstants.ETS_SUFFIX); if (framework_1.PluginFileUtil.exist(tempFilePath)) { resultPath = tempFilePath; break; } } } if (!resultPath) { for (const [importPath, importNames] of importMap.entries()) { if (importNames.includes(variableName)) { resultPath = this.getOtherModuleVariableFilePath(importPath, variableName, this.modulePath); break; } } } return resultPath; } getOtherModuleVariableFilePath(moduleName, variableName, modulePath) { let moduleFilePath = framework_1.PluginFileUtil.pathResolve(modulePath, constants_1.FilePathConstants.OH_MODULE_PATH, moduleName, constants_1.FilePathConstants.DEFAULT_SCAN_DIR); if (!framework_1.PluginFileUtil.exist(moduleFilePath)) { moduleFilePath = framework_1.PluginFileUtil.pathResolve(framework_1.PluginStore.getInstance().get('projectFilePath'), constants_1.FilePathConstants.OH_MODULE_PATH, moduleName, constants_1.FilePathConstants.DEFAULT_SCAN_DIR); } const variableCache = framework_1.PluginStore.getInstance().get('variableCache'); if (!variableCache) { framework_1.PluginStore.getInstance().set('variableCache', new Map()); } let variableMap; if (variableCache?.has(moduleName)) { variableMap = variableCache.get(moduleName); } else { variableMap = this.parseCrossModuleVariable(moduleFilePath); variableCache?.set(moduleName, variableMap); } for (let [key, value] of variableMap) { if (value.includes(variableName)) { return key; } } throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.UNKNOWN_VARIABLE, '', variableName); } parsePrimitiveValue(value) { let propertyValue; switch (value.getKind()) { case ts_morph_1.SyntaxKind.StringLiteral: propertyValue = value.asKind(ts_morph_1.SyntaxKind.StringLiteral)?.getLiteralValue(); break; case ts_morph_1.SyntaxKind.NumericLiteral: propertyValue = value.asKind(ts_morph_1.SyntaxKind.NumericLiteral)?.getLiteralValue(); break; case ts_morph_1.SyntaxKind.TrueKeyword: propertyValue = true; break; case ts_morph_1.SyntaxKind.FalseKeyword: propertyValue = false; break; case ts_morph_1.SyntaxKind.ArrayLiteralExpression: propertyValue = value .asKind(ts_morph_1.SyntaxKind.ArrayLiteralExpression) ?.getElements() .map((item) => item.asKind(ts_morph_1.SyntaxKind.StringLiteral)?.getLiteralValue()); break; } return propertyValue; } parseConstantValue(sourceFile, variableName, propertyName) { let result; if (propertyName) { let classInstance = sourceFile.getClasses().find((classes) => { return classes.getName() === variableName; }); if (!classInstance) { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.UNKNOWN_CLASS, '', variableName); } let property = classInstance.getProperties().find((properties) => { return properties.getName() === propertyName; }); if (!property) { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.UNKNOWN_PROPERTY, '', propertyName); } result = property.getInitializer(); } else { let constant = sourceFile.getVariableDeclarations().find((declaration) => { return declaration.getName() === variableName; }); if (!constant) { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.UNKNOWN_CONSTANT, '', variableName); } result = constant.getInitializer(); } if (result.getKind() !== ts_morph_1.SyntaxKind.StringLiteral) { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.INVALID_STRING_VALUE, '', variableName); } const resultValue = result.asKind(ts_morph_1.SyntaxKind.StringLiteral)?.getLiteralValue(); if (!resultValue) { throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.NOT_EMPTY_STRING, '', variableName); } return resultValue; } parseCrossModuleVariable(scanDir) { let sourceFiles = framework_1.TsAstUtil.project.addSourceFilesAtPaths(`${scanDir}/**/*.ets`); const exportMap = new Map(); for (let sourceFile of sourceFiles) { const exportedNames = this.getExportedVariables(sourceFile); if (exportedNames.length > 0) { exportMap.set(sourceFile.getFilePath(), exportedNames); } } return exportMap; } getExportedVariables(sourceFile) { const exportSymbols = []; let exportKeywordNodes = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.ExportKeyword); exportKeywordNodes.forEach((node) => { let parentNodeKind = node.getParent()?.getKind(); switch (parentNodeKind) { case ts_morph_1.SyntaxKind.VariableStatement: let variableStatement = node.getParent()?.asKind(ts_morph_1.SyntaxKind.VariableStatement); let variableNames = variableStatement .getDeclarationList() .getDeclarations() .map((declaration) => { return declaration.getName(); }); exportSymbols.push(...variableNames); break; case ts_morph_1.SyntaxKind.ClassDeclaration: let classDeclaration = node.getParent(); let className = classDeclaration?.asKind(ts_morph_1.SyntaxKind.ClassDeclaration)?.getName(); exportSymbols.push(className); break; } }); return exportSymbols; } } exports.ConstantResolver = ConstantResolver;