UNPKG

@hadss/hmrouter-plugin

Version:

HMRouter Compiler Plugin

301 lines (300 loc) 13.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; 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"); const path_1 = __importDefault(require("path")); class ConstantResolver { constructor() { this.importMapCache = new Map(); this.importMapCacheFilePath = []; } setContext(context) { this.context = context; } 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); break; } } } return resultPath; } getOtherModuleVariableFilePath(moduleName, variableName) { const dependencies = this.context?.moduleContext.getOhpmDependencyInfo() || {}; for (const [dependencyName, dependencyInfo] of Object.entries(dependencies)) { if (moduleName.indexOf(dependencyName) === 0) { const cacheImport = this.importMapCacheFilePath.find((f) => f.dependencyName === dependencyName && f.importConstantName === variableName && f.importPath === moduleName); if (cacheImport) { return cacheImport.importFullPath; } const isFullPathImport = dependencyName !== moduleName; let dependencyFilePath = ''; if (isFullPathImport) { dependencyFilePath = dependencyInfo.packagePath + moduleName.replace(dependencyName, '') + constants_1.FilePathConstants.ETS_SUFFIX; } else { const dependPackageFileName = framework_1.PluginFileUtil.readJson5(framework_1.PluginFileUtil.pathResolve(dependencyInfo.packagePath, constants_1.FilePathConstants.OH_PACKAGE_FILE_NAME)); dependencyFilePath = framework_1.PluginFileUtil.pathResolve(dependencyInfo.packagePath, dependPackageFileName.main || 'Index.ets'); } const path = this.findExportInFile(dependencyFilePath, variableName); if (path) { this.importMapCacheFilePath.push({ dependencyName: dependencyName, importPath: moduleName, importConstantName: variableName, importFullPath: path }); return path; } } } throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.UNKNOWN_VARIABLE, '', variableName); } findExportInFile(filePath, variableName) { if (!this.isFileExists(filePath)) { return undefined; } const sourceFile = framework_1.TsAstUtil.getSourceFile(filePath); const localDefinitionPath = this.findLocalDefinition(sourceFile, filePath, variableName); if (localDefinitionPath) { return localDefinitionPath; } const reExportedPath = this.findReExportedDeclaration(sourceFile, filePath, variableName); if (reExportedPath) { return reExportedPath; } const namedExportPath = this.findNamedExport(sourceFile, filePath, variableName); if (namedExportPath) { return namedExportPath; } return undefined; } isFileExists(filePath) { if (!framework_1.PluginFileUtil.exist(filePath)) { const alternativePath = filePath.replace(constants_1.FilePathConstants.ETS_SUFFIX, constants_1.FilePathConstants.D_ETS_SUFFIX); return framework_1.PluginFileUtil.exist(alternativePath); } return true; } findLocalDefinition(sourceFile, filePath, variableName) { const localDefinitions = [ ...sourceFile.getVariableDeclarations(), ...sourceFile.getClasses(), ...sourceFile.getInterfaces(), ].filter(node => node.getName() === variableName); if (localDefinitions.length > 0) { framework_1.Logger.debug('', `Object "${variableName}" is defined locally in file: ${filePath}`); return filePath; } return undefined; } findReExportedDeclaration(sourceFile, filePath, variableName) { const exportDeclarations = sourceFile.getExportDeclarations(); for (const exportDecl of exportDeclarations) { const moduleSpecifier = exportDecl.getModuleSpecifierValue(); if (!moduleSpecifier) { continue; } if (!this.shouldCheckReExport(exportDecl, variableName)) { continue; } const originalDefinitionPath = this.findReExport(moduleSpecifier, filePath, variableName); if (originalDefinitionPath) { return originalDefinitionPath; } } for (const exportDecl of exportDeclarations) { const moduleSpecifier = exportDecl.getModuleSpecifierValue(); if (!moduleSpecifier) { continue; } if (!exportDecl.isNamespaceExport()) { continue; } const originalDefinitionPath = this.findReExport(moduleSpecifier, filePath, variableName); if (originalDefinitionPath) { return originalDefinitionPath; } } return undefined; } findReExport(moduleSpecifier, filePath, variableName) { const resolvedPath = framework_1.PluginFileUtil.pathResolve(path_1.default.dirname(filePath), moduleSpecifier + constants_1.FilePathConstants.ETS_SUFFIX); const originalDefinitionPath = this.findExportInFile(resolvedPath, variableName); if (originalDefinitionPath) { framework_1.Logger.debug('', `Object "${variableName}" is re-exported from: ${resolvedPath}`); return originalDefinitionPath; } return undefined; } shouldCheckReExport(exportDecl, variableName) { const namedExports = exportDecl.getNamedExports(); if (namedExports.some(specifier => specifier.getAliasNode()?.getText() === variableName || specifier.getName() === variableName)) { return true; } return false; } findNamedExport(sourceFile, filePath, variableName) { const exportSpecifiers = sourceFile.getExportedDeclarations().get(variableName); if (!exportSpecifiers || exportSpecifiers.length === 0) { return undefined; } const exportSpecifier = exportSpecifiers[0]; const symbol = exportSpecifier.getSymbol(); if (!symbol) { return undefined; } const definitions = symbol.getDeclarations(); for (const definition of definitions) { const definitionFilePath = definition.getSourceFile().getFilePath(); if (definitionFilePath !== filePath) { framework_1.Logger.debug('', `Object "${variableName}" is exported from: ${definitionFilePath}`); return definitionFilePath; } } return undefined; } 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; } } exports.ConstantResolver = ConstantResolver;