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 */ 15import { ArkAssignStmt, ArkInvokeStmt, Stmt } from 'arkanalyzer/lib/core/base/Stmt'; 16import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; 17import { AbstractInvokeExpr, ArkAwaitExpr } from 'arkanalyzer/lib/core/base/Expr'; 18import { Local } from 'arkanalyzer/lib/core/base/Local'; 19import path from 'path'; 20import { ArkClass, ArkFile, ArkInstanceFieldRef, FileSignature, Scene, Value } from 'arkanalyzer'; 21import { ScopeType, TempLocation } from '../../model/Scope'; 22 23const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'CheckUtils'); 24 25export class CheckerUtils { 26 /** 27 * 从给定的语句中获取调用表达式 28 * @param stmt - 要处理的语句 29 * @returns 如果找到调用表达式,则返回 AbstractInvokeExpr,否则返回 null 30 */ 31 public static getInvokeExprFromStmt(stmt: Stmt): AbstractInvokeExpr | null { 32 if (stmt instanceof ArkInvokeStmt) { 33 return stmt.getInvokeExpr(); 34 } else if (stmt instanceof ArkAssignStmt) { 35 const rightOp = stmt.getRightOp(); 36 if (rightOp instanceof AbstractInvokeExpr) { 37 return rightOp; 38 } 39 } 40 return null; 41 } 42 43 /** 44 * 从给定的语句中获取调用表达式(Await) 45 * @param stmt - 要处理的语句 46 * @returns 如果找到调用表达式,则返回 AbstractInvokeExpr,否则返回 null 47 */ 48 public static getInvokeExprFromAwaitStmt(stmt: Stmt): AbstractInvokeExpr | null { 49 if (stmt instanceof ArkInvokeStmt) { 50 return stmt.getInvokeExpr(); 51 } else if (stmt instanceof ArkAssignStmt) { 52 let rightOp = stmt.getRightOp(); 53 if (rightOp instanceof AbstractInvokeExpr) { 54 return rightOp; 55 } else if (rightOp instanceof ArkAwaitExpr) { 56 let promise = rightOp.getPromise(); 57 if (!(promise instanceof Local)) { 58 return null; 59 } 60 let declaringStmt = promise.getDeclaringStmt(); 61 if (!(declaringStmt instanceof ArkAssignStmt)) { 62 return null; 63 } 64 rightOp = declaringStmt.getRightOp(); 65 if (rightOp instanceof AbstractInvokeExpr) { 66 return rightOp; 67 } 68 } 69 } 70 return null; 71 } 72 73 /** 74 * 获取语句的Scope类型 75 * @param stmt 语句对象 76 * @returns Scope类型 77 */ 78 public static getScopeType(stmt: Stmt): ScopeType { 79 const text = stmt.getOriginalText() ?? ''; 80 if (!text) { 81 return ScopeType.UNKNOWN_TYPE; 82 } 83 if (text.startsWith('for (') || text.startsWith('for(')) { 84 return ScopeType.FOR_CONDITION_TYPE; 85 } else if (text.startsWith('while (') || text.startsWith('while(')) { 86 return ScopeType.WHILE_TYPE; 87 } else if (text.startsWith('if (') || text.startsWith('if(')) { 88 return ScopeType.IF_TYPE; 89 } 90 return ScopeType.UNKNOWN_TYPE; 91 } 92 93 /** 94 * 判断给定的语句是否是声明语句 95 * @param defName - 要检查的变量名 96 * @param stmt - 要检查的语句 97 * @returns 如果语句是声明语句,则返回true,否则返回false 98 */ 99 public static isDeclaringStmt(defName: string, stmt: Stmt): boolean { 100 const text = stmt.getOriginalText() ?? ''; 101 if (text) { 102 if (text.includes('let ' + defName) || text.includes('const ' + defName) || 103 text.includes('var ' + defName)) { 104 const c = text[text.indexOf(' ' + defName) + defName.length + 1]; 105 if (c === ' ' || c === ':' || c === '=') { 106 return true; 107 } 108 } 109 } 110 return false; 111 } 112 113 /** 114 * 获取语句中临时变量的位置 115 * @param stmt 语句 116 * @returns 临时变量的位置 117 */ 118 public static wherIsTemp(stmt: Stmt): TempLocation { 119 let def = stmt.getDef(); 120 if (def instanceof Local) { 121 if (def.getName().includes('%')) { 122 return TempLocation.LEFT; 123 } 124 } 125 if (stmt instanceof ArkAssignStmt) { 126 let right = stmt.getRightOp(); 127 if (right instanceof Local) { 128 if (right.getName().includes('%')) { 129 return TempLocation.RIGHT; 130 } 131 } 132 } 133 return TempLocation.NOFOUND; 134 } 135 136 /** 137 * 根据文件路径获取ArkFile对象 138 * @param scene Scene 139 * @param absolutePath 文件的绝对路径 140 * @returns 返回对应的ArkFile对象,如果未找到则返回null 141 */ 142 public static getArkFileByFilePath(scene: Scene, absolutePath: string): ArkFile | null { 143 const relativePath = path.relative(scene.getRealProjectDir(), absolutePath); 144 const fileSign = new FileSignature(scene.getProjectName(), relativePath); 145 return scene.getFile(fileSign); 146 } 147 148 /** 149 * 获取参数的右值 150 * @param arg - 参数 151 * @param arkClass - ArkClass对象 152 * @returns Value | null - 返回参数的右值,如果不存在则返回null 153 */ 154 public static getArgRight(arg: Value, arkClass: ArkClass): Value | null { 155 if (!(arg instanceof Local)) { 156 return arg; 157 } 158 let decStmt = arg.getDeclaringStmt(); 159 if (!(decStmt instanceof ArkAssignStmt)) { 160 return null; 161 } 162 let rightOp = decStmt.getRightOp(); 163 if (!(rightOp instanceof ArkInstanceFieldRef)) { 164 return rightOp; 165 } 166 let field = arkClass.getField(rightOp.getFieldSignature()); 167 if (!field) { 168 return null; 169 } 170 for (let initializer of field.getInitializer()) { 171 if (!(initializer instanceof ArkAssignStmt)) { 172 continue; 173 } 174 return initializer.getRightOp(); 175 } 176 return null; 177 } 178}