• 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 Logger, { LOG_MODULE_TYPE } from './logger';
19import { transfer2UnixPath } from './pathTransfer';
20import { OH_PACKAGE_JSON5 } from '../core/common/EtsConst';
21import { Language } from '../core/model/ArkFile';
22
23const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'FileUtils');
24
25export class FileUtils {
26    public static readonly FILE_FILTER = {
27        ignores: ['.git', '.preview', '.hvigor', '.idea', 'test', 'ohosTest'],
28        include: /(?<!\.d)\.(ets|ts|json5)$/,
29    };
30
31    public static getIndexFileName(srcPath: string): string {
32        for (const fileInDir of fs.readdirSync(srcPath, { withFileTypes: true })) {
33            if (fileInDir.isFile() && /^index(\.d)?\.e?ts$/i.test(fileInDir.name)) {
34                return fileInDir.name;
35            }
36        }
37        return '';
38    }
39
40    public static isDirectory(srcPath: string): boolean {
41        try {
42            return fs.statSync(srcPath).isDirectory();
43        } catch (e) {}
44        return false;
45    }
46
47    public static isAbsolutePath(path: string): boolean {
48        return /^(\/|\\|[A-Z]:\\)/.test(path);
49    }
50
51    public static generateModuleMap(ohPkgContentMap: Map<string, { [k: string]: unknown }>): Map<string, ModulePath> {
52        const moduleMap: Map<string, ModulePath> = new Map();
53        ohPkgContentMap.forEach((content, filePath) => {
54            const moduleName = content.name as string;
55            if (moduleName && moduleName.startsWith('@')) {
56                const modulePath = path.dirname(filePath);
57                moduleMap.set(moduleName, new ModulePath(modulePath, content.main ? path.resolve(modulePath, content.main as string) : ''));
58            }
59        });
60        ohPkgContentMap.forEach((content, filePath) => {
61            if (!content.dependencies) {
62                return;
63            }
64            Object.entries(content.dependencies).forEach(([name, value]) => {
65                if (moduleMap.get(name)) {
66                    return;
67                }
68                const modulePath = path.resolve(path.dirname(filePath), value.replace('file:', ''));
69                const key = path.resolve(modulePath, OH_PACKAGE_JSON5);
70                const target = ohPkgContentMap.get(key);
71                if (target) {
72                    moduleMap.set(name, new ModulePath(modulePath, target.main ? path.resolve(modulePath, target.main as string) : ''));
73                }
74            });
75        });
76        return moduleMap;
77    }
78
79    public static getFileLanguage(file: string, fileTags?: Map<string, Language>): Language {
80        if (fileTags && fileTags.has(file)) {
81            return fileTags.get(file) as Language;
82        }
83        const extension = path.extname(file).toLowerCase();
84        switch (extension) {
85            case '.ts':
86                return Language.TYPESCRIPT;
87            case '.ets':
88                return Language.ARKTS1_1;
89            case '.js':
90                return Language.JAVASCRIPT;
91            default:
92                return Language.UNKNOWN;
93        }
94    }
95}
96
97export class ModulePath {
98    path: string;
99    main: string;
100
101    constructor(path: string, main: string) {
102        this.path = transfer2UnixPath(path);
103        this.main = transfer2UnixPath(main);
104    }
105}
106
107export function getFileRecursively(srcDir: string, fileName: string, visited: Set<string> = new Set<string>()): string {
108    let res = '';
109    if (!fs.existsSync(srcDir) || !fs.statSync(srcDir).isDirectory()) {
110        logger.warn(`Input directory ${srcDir} is not exist`);
111        return res;
112    }
113
114    const filesUnderThisDir = fs.readdirSync(srcDir, { withFileTypes: true });
115    const realSrc = fs.realpathSync(srcDir);
116    if (visited.has(realSrc)) {
117        return res;
118    }
119    visited.add(realSrc);
120
121    filesUnderThisDir.forEach(file => {
122        if (res !== '') {
123            return res;
124        }
125        if (file.name === fileName) {
126            res = path.resolve(srcDir, file.name);
127            return res;
128        }
129        const tmpDir = path.resolve(srcDir, '../');
130        res = getFileRecursively(tmpDir, fileName, visited);
131        return res;
132    });
133    return res;
134}
135