• 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 fs from 'fs';
17import path from 'path';
18import ts from 'ohos-typescript';
19import { ArkFile, Language } from '../ArkFile';
20import { ArkNamespace } from '../ArkNamespace';
21import Logger, { LOG_MODULE_TYPE } from '../../../utils/logger';
22import { buildDefaultArkClassFromArkFile, buildNormalArkClassFromArkFile } from './ArkClassBuilder';
23import { buildArkMethodFromArkClass } from './ArkMethodBuilder';
24import { buildImportInfo } from './ArkImportBuilder';
25import {
26    buildExportAssignment,
27    buildExportDeclaration,
28    buildExportInfo,
29    buildExportTypeAliasDeclaration,
30    buildExportVariableStatement,
31    isExported,
32} from './ArkExportBuilder';
33import { buildArkNamespace, mergeNameSpaces } from './ArkNamespaceBuilder';
34import { ArkClass } from '../ArkClass';
35import { ArkMethod } from '../ArkMethod';
36import { LineColPosition } from '../../base/Position';
37import { ETS_COMPILER_OPTIONS } from '../../common/EtsConst';
38import { FileSignature } from '../ArkSignature';
39import { ARKTS_STATIC_MARK } from '../../common/Const';
40
41const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'ArkFileBuilder');
42
43export const notStmtOrExprKind = [
44    'ModuleDeclaration',
45    'ClassDeclaration',
46    'InterfaceDeclaration',
47    'EnumDeclaration',
48    'ExportDeclaration',
49    'ExportAssignment',
50    'MethodDeclaration',
51    'Constructor',
52    'FunctionDeclaration',
53    'GetAccessor',
54    'SetAccessor',
55    'ArrowFunction',
56    'FunctionExpression',
57    'MethodSignature',
58    'ConstructSignature',
59    'CallSignature',
60];
61
62/**
63 * Entry of building ArkFile instance
64 *
65 * @param arkFile
66 * @returns
67 */
68export function buildArkFileFromFile(absoluteFilePath: string, projectDir: string, arkFile: ArkFile, projectName: string): void {
69    arkFile.setFilePath(absoluteFilePath);
70    arkFile.setProjectDir(projectDir);
71
72    const fileSignature = new FileSignature(projectName, path.relative(projectDir, absoluteFilePath));
73    arkFile.setFileSignature(fileSignature);
74
75    arkFile.setCode(fs.readFileSync(arkFile.getFilePath(), 'utf8'));
76    const sourceFile = ts.createSourceFile(arkFile.getName(), arkFile.getCode(), ts.ScriptTarget.Latest, true, undefined, ETS_COMPILER_OPTIONS);
77    genDefaultArkClass(arkFile, sourceFile);
78    buildArkFile(arkFile, sourceFile);
79}
80
81/**
82 * Building ArkFile instance
83 *
84 * @param arkFile
85 * @param astRoot
86 * @returns
87 */
88function buildArkFile(arkFile: ArkFile, astRoot: ts.SourceFile): void {
89    const statements = astRoot.statements;
90    const namespaces: ArkNamespace[] = [];
91    statements.forEach(child => {
92        if (ts.isModuleDeclaration(child)) {
93            let ns: ArkNamespace = new ArkNamespace();
94            ns.setDeclaringArkFile(arkFile);
95
96            buildArkNamespace(child, arkFile, ns, astRoot);
97            namespaces.push(ns);
98            if (ns.isExported()) {
99                arkFile.addExportInfo(buildExportInfo(ns, arkFile, LineColPosition.buildFromNode(child, astRoot)));
100            }
101        } else if (ts.isClassDeclaration(child) || ts.isInterfaceDeclaration(child) || ts.isEnumDeclaration(child) || ts.isStructDeclaration(child)) {
102            let cls: ArkClass = new ArkClass();
103
104            buildNormalArkClassFromArkFile(child, arkFile, cls, astRoot);
105            arkFile.addArkClass(cls);
106
107            if (cls.isExported()) {
108                arkFile.addExportInfo(buildExportInfo(cls, arkFile, LineColPosition.buildFromNode(child, astRoot)));
109            }
110        }
111        // TODO: Check
112        else if (ts.isMethodDeclaration(child)) {
113            logger.trace('This is a MethodDeclaration in ArkFile.');
114            let mthd: ArkMethod = new ArkMethod();
115
116            buildArkMethodFromArkClass(child, arkFile.getDefaultClass(), mthd, astRoot);
117
118            if (mthd.isExported()) {
119                arkFile.addExportInfo(buildExportInfo(mthd, arkFile, LineColPosition.buildFromNode(child, astRoot)));
120            }
121        } else if (ts.isFunctionDeclaration(child)) {
122            let mthd: ArkMethod = new ArkMethod();
123
124            buildArkMethodFromArkClass(child, arkFile.getDefaultClass(), mthd, astRoot);
125
126            if (mthd.isExported()) {
127                arkFile.addExportInfo(buildExportInfo(mthd, arkFile, LineColPosition.buildFromNode(child, astRoot)));
128            }
129        } else if (ts.isImportEqualsDeclaration(child) || ts.isImportDeclaration(child)) {
130            let importInfos = buildImportInfo(child, astRoot, arkFile);
131            importInfos?.forEach(element => {
132                element.setDeclaringArkFile(arkFile);
133                arkFile.addImportInfo(element);
134            });
135        } else if (ts.isExportDeclaration(child)) {
136            buildExportDeclaration(child, astRoot, arkFile).forEach(item => arkFile.addExportInfo(item));
137        } else if (ts.isExportAssignment(child)) {
138            buildExportAssignment(child, astRoot, arkFile).forEach(item => arkFile.addExportInfo(item));
139        } else if (ts.isVariableStatement(child) && isExported(child.modifiers)) {
140            buildExportVariableStatement(child, astRoot, arkFile).forEach(item => arkFile.addExportInfo(item));
141        } else if (ts.isTypeAliasDeclaration(child) && isExported(child.modifiers)) {
142            buildExportTypeAliasDeclaration(child, astRoot, arkFile).forEach(item => arkFile.addExportInfo(item));
143        } else if (ts.isExpressionStatement(child) && ts.isStringLiteral(child.expression)) {
144            child.expression.text.trim() === ARKTS_STATIC_MARK && arkFile.setLanguage(Language.ARKTS1_2);
145        } else {
146            logger.trace('Child joined default method of arkFile: ', ts.SyntaxKind[child.kind]);
147        }
148    });
149
150    const mergedNameSpaces = mergeNameSpaces(namespaces);
151    mergedNameSpaces.forEach(mergedNameSpace => {
152        arkFile.addNamespace(mergedNameSpace);
153        if (mergedNameSpace.isExport()) {
154            const linCol = new LineColPosition(mergedNameSpace.getLine(), mergedNameSpace.getColumn());
155            arkFile.addExportInfo(buildExportInfo(mergedNameSpace, arkFile, linCol));
156        }
157    });
158}
159
160function genDefaultArkClass(arkFile: ArkFile, astRoot: ts.SourceFile): void {
161    let defaultClass = new ArkClass();
162
163    buildDefaultArkClassFromArkFile(arkFile, defaultClass, astRoot);
164    arkFile.setDefaultClass(defaultClass);
165    arkFile.addArkClass(defaultClass);
166}
167