@hadss/hmrouter-plugin
Version:
HMRouter Compiler Plugin
218 lines (217 loc) • 10.2 kB
JavaScript
;
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;