1/* 2 * Copyright (c) 2024 - 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { AbstractExpr, ArkAssignStmt, ArkFile, ArkNormalBinopExpr, ArkStaticFieldRef, ClassSignature, ClassType, Constant, ImportInfo, Local, Stmt, StringType, Value } from 'arkanalyzer'; 17import { ClassCategory } from 'arkanalyzer/lib/core/model/ArkClass'; 18import { VarInfo } from '../../model/VarInfo'; 19import { StmtExt } from '../../model/StmtExt'; 20import { CheckerStorage } from '../common/CheckerStorage'; 21import { Scope } from '../../model/Scope'; 22 23export class StringUtils { 24 public static getStringByScope(arkFile: ArkFile, valueStmtInfo: VarInfo, value: Value): string { 25 if (value instanceof Constant) { 26 return value.getValue(); 27 } else if (value instanceof Local) { 28 if (!value.toString().includes('%')) { 29 let importInfo = this.getValueImportInfo(arkFile, value); 30 if (importInfo) { 31 return this.getImportStringValue(importInfo, value); 32 } else { 33 return this.getMethodStringValue(arkFile, valueStmtInfo, value); 34 } 35 } else { 36 let declaringStmt = value.getDeclaringStmt(); 37 if (!declaringStmt) { 38 return ''; 39 } 40 let tmpStmt = declaringStmt; 41 if (!(declaringStmt instanceof ArkAssignStmt)) { 42 return ''; 43 } 44 let rightOp = declaringStmt.getRightOp(); 45 valueStmtInfo.stmt = declaringStmt; 46 valueStmtInfo.scope = (tmpStmt as StmtExt).scope; 47 return this.getStringByScope(arkFile, valueStmtInfo, rightOp); 48 } 49 } else if (value instanceof AbstractExpr && value.getType() instanceof StringType) { 50 return this.getExprStringValue(arkFile, valueStmtInfo, value); 51 } else if (value instanceof ArkStaticFieldRef && value.getType() instanceof StringType) { 52 return this.getStaticStringValue(arkFile, value); 53 } else if (value instanceof ArkStaticFieldRef && value.getType() instanceof ClassType) { 54 return this.getStaticStringValue(arkFile, value); 55 } 56 return ''; 57 } 58 59 private static getValueImportInfo(arkFile: ArkFile, value: Local): ImportInfo | undefined { 60 let importInfos = arkFile.getImportInfos(); 61 for (let importInfo of importInfos) { 62 if (importInfo.getImportClauseName() === value.getName()) { 63 return importInfo; 64 } 65 } 66 return undefined; 67 } 68 69 private static getImportStringValue(importInfo: ImportInfo, value: Local): string { 70 let exportInfo = importInfo.getLazyExportInfo(); 71 let importArkFile = exportInfo?.getDeclaringArkFile(); 72 if (!importArkFile) { 73 return ''; 74 } 75 let scope = CheckerStorage.getInstance().getScope(importArkFile.getFilePath()); 76 if (!scope) { 77 return ''; 78 } 79 for (let varDef of scope.defList) { 80 if (varDef.getName() === value.getName()) { 81 continue; 82 } 83 let stmt = varDef.defStmt; 84 const text = stmt.getOriginalText(); 85 if (!text || text.length === 0 || !text.includes('const')) { 86 continue; 87 } 88 if (stmt instanceof ArkAssignStmt) { 89 let defStmtInfo = new VarInfo(stmt, scope); 90 let rightOp = stmt.getRightOp(); 91 return this.getStringByScope(importArkFile, defStmtInfo, rightOp); 92 } 93 } 94 return ''; 95 } 96 97 private static getMethodStringValue(arkFile: ArkFile, valueStmtInfo: VarInfo, value: Local): string { 98 let scope: Scope = valueStmtInfo.scope; 99 let valueStmt: Stmt = valueStmtInfo.stmt; 100 let hasFind = false; 101 if (!scope || !scope.defList) { 102 return ''; 103 } 104 let defLists = scope.defList; 105 for (let defVar of defLists) { 106 if (defVar.getName() !== value.getName()) { 107 continue; 108 } 109 hasFind = true; 110 let nearReDefStmtInfo = new VarInfo(defVar.defStmt, scope); 111 let reDefStmtInfos = defVar.redefInfo; 112 for (let reDefStmtInfo of reDefStmtInfos) { 113 let originalLine = valueStmt.getOriginPositionInfo().getLineNo(); 114 let redefLine = reDefStmtInfo.stmt.getOriginPositionInfo().getLineNo(); 115 if (redefLine >= originalLine) { 116 break; 117 } 118 nearReDefStmtInfo = reDefStmtInfo; 119 } 120 let stmt = nearReDefStmtInfo.stmt; 121 if (stmt instanceof ArkAssignStmt) { 122 let rightOp = stmt.getRightOp(); 123 return this.getStringByScope(arkFile, nearReDefStmtInfo, rightOp); 124 } 125 } 126 if (!hasFind && scope.parentScope !== null) { 127 let defStmtInfo = new VarInfo(valueStmt, scope.parentScope); 128 return this.getStringByScope(arkFile, defStmtInfo, value); 129 } 130 return ''; 131 } 132 133 private static getExprStringValue(arkFile: ArkFile, stmtInfo: VarInfo, value: AbstractExpr): string { 134 if (value instanceof ArkNormalBinopExpr) { 135 let stringOfOp1 = this.getStringByScope(arkFile, stmtInfo, value.getOp1()); 136 let stringOfOp2 = this.getStringByScope(arkFile, stmtInfo, value.getOp2()); 137 switch (value.getOperator()) { 138 case '+': 139 return stringOfOp1 + stringOfOp2; 140 } 141 } 142 return ''; 143 } 144 145 private static getStaticStringValue(arkFile: ArkFile, value: ArkStaticFieldRef): string { 146 let classSignature = value.getFieldSignature().getDeclaringSignature(); 147 if (!(classSignature instanceof ClassSignature)) { 148 return ''; 149 } 150 let fieldSignature = classSignature.getDeclaringFileSignature(); 151 let staticClassArkFile = arkFile.getScene().getFile(fieldSignature); 152 if (!staticClassArkFile) { 153 return ''; 154 } 155 let staticClass = staticClassArkFile.getClass(classSignature); 156 if (!staticClass) { 157 return ''; 158 } 159 let staticField = staticClass.getStaticFieldWithName(value.getFieldName()); 160 if (!staticField) { 161 return ''; 162 } 163 if (staticClass.getCategory() === ClassCategory.CLASS && !staticField.isReadonly()) { 164 return ''; 165 } 166 let stmts = staticField.getInitializer(); 167 if (stmts.length === 0) { 168 return ''; 169 } 170 let stmt = stmts[0]; 171 let varInfo = new VarInfo(stmt, (stmt as StmtExt).scope); 172 if (!(stmt instanceof ArkAssignStmt)) { 173 return ''; 174 } 175 let initValue = stmt.getRightOp(); 176 return this.getStringByScope(staticClassArkFile, varInfo, initValue); 177 } 178}