• 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 */
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}