• 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 {ArkFile, Scene, SceneConfig} from 'arkanalyzer';
17import Logger, {LOG_MODULE_TYPE} from 'arkanalyzer/lib/utils/logger';
18import {buildModuleChains} from './BuildModuleChains';
19import {ProjectConfig} from '../model/ProjectConfig';
20import {FileUtils, WriteFileMode} from '../utils/common/FileUtils';
21import {Utils} from '../utils/common/Utils';
22import {buildFileDepGraph, buildModuleDepGraph} from './depGraph/builder';
23import {OptionValues} from 'commander';
24import {ConfigUtils} from '../Index';
25import path from 'path';
26import fs from 'fs';
27
28const logger = Logger.getLogger(LOG_MODULE_TYPE.TOOL, 'runTool');
29
30export function runTool(tool: Tools, argvObj: OptionValues): void {
31    const startTime = new Date().getTime();
32    const projectConfig = new ProjectConfig(ConfigUtils.getConfig(argvObj.projectConfigPath));
33    let depGraphOutputDir = argvObj.depGraphOutputDir;
34
35    try {
36        // 配置日志文件路径
37        const logPath = projectConfig.logPath;
38        Utils.setLogPath(logPath.length ? logPath : './HomeCheckTools.log');
39        logger.info('start to run tool...');
40        const scene = buildScene(projectConfig);
41        if (!scene) {
42            return;
43        }
44        // 运行对应工具模块
45        switch (tool) {
46            case Tools.ImportChains:
47                logger.info('start to buildModuleChains...');
48                buildModuleChains(scene, [], projectConfig.reportDir);
49                logger.info('buildModuleChains completed.');
50                break;
51            case Tools.DepGraph:
52                if (!depGraphOutputDir) {
53                    logger.warn('The output directory of dependency graph is not set, by default it will be set to current directory.');
54                    depGraphOutputDir = './';
55                }
56                if (!fs.existsSync(depGraphOutputDir)) {
57                    logger.error(`The given depGraphOutputDir: ${depGraphOutputDir} is not exist.`);
58                    process.exit(-1);
59                }
60                genFileDepGraph(depGraphOutputDir, scene.getFiles());
61                genModuleDepGraph(depGraphOutputDir, scene);
62                break;
63            default:
64                logger.error(`Unknown tool: ${tool}`);
65                break;
66        }
67    } catch (error) {
68        logger.error(`Error occurred: ${(error as Error).message}`);
69        return;
70    }
71    const endTime = new Date().getTime();
72    logger.info(`HomeCheck tools took: ${(endTime - startTime) / 1000}s`);
73}
74
75function buildScene(projectConfig: ProjectConfig): Scene | null {
76    try {
77        // 构建SceneConfig
78        const config: SceneConfig = new SceneConfig();
79        const fileList = FileUtils.getAllFiles(projectConfig.projectPath, ['.ts', '.ets']);
80        config.buildFromProjectFiles(projectConfig.projectName, projectConfig.projectPath, fileList, FileUtils.genSdks(projectConfig));
81        logger.info('Build sceneConfig completed.');
82        // 构建Scene
83        const scene = new Scene();
84        scene.buildSceneFromFiles(config);
85        logger.info('Build scene completed.');
86        scene.inferTypes();
87        logger.info('Infer types completed.');
88        return scene;
89    } catch (error) {
90        logger.error(`Build scene or infer types error: ${(error as Error).message}`);
91        return null;
92    }
93}
94
95function genFileDepGraph(outputPath: string, arkFiles: ArkFile[]): void {
96    const fileDepGraphJson = path.join(outputPath, './fileDepGraph.json');
97    const fileDepGraphDot = path.join(outputPath, './fileDepGraph.dot');
98
99    logger.info('Started to build file dependency graph...');
100
101    const depGraph = buildFileDepGraph(arkFiles);
102
103    const jsonRes = JSON.stringify(depGraph.toJson());
104    FileUtils.writeToFile(fileDepGraphJson, jsonRes, WriteFileMode.OVERWRITE);
105    logger.info('Building dependency graph in json format has completed.');
106
107    const dotRes = depGraph.dump();
108    FileUtils.writeToFile(fileDepGraphDot, dotRes, WriteFileMode.OVERWRITE);
109    logger.info('Building dependency graph in dot format has completed.');
110
111    logger.info('Building file dependency graph completed.');
112}
113
114function genModuleDepGraph(outputPath: string, scene: Scene): void {
115    const moduleDepGraphJson = path.join(outputPath, './moduleDepGraph.json');
116    const moduleDepGraphDot = path.join(outputPath, './moduleDepGraph.dot');
117
118    logger.info('Started to build module dependency graph...');
119
120    const depGraph = buildModuleDepGraph(scene);
121
122    const jsonRes = JSON.stringify(depGraph.toJson());
123    FileUtils.writeToFile(moduleDepGraphJson, jsonRes, WriteFileMode.OVERWRITE);
124    logger.info('Building module graph in json format has completed.');
125
126    const dotRes = depGraph.dump();
127    FileUtils.writeToFile(moduleDepGraphDot, dotRes, WriteFileMode.OVERWRITE);
128    logger.info('Building module graph in dot format has completed.');
129
130    logger.info('Building file module graph completed.');
131}
132
133export enum Tools {
134    ImportChains = 0,
135    DepGraph = 1,
136}