• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}