* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {LOG_MODULE_TYPE} from 'arkanalyzer/lib/utils/logger';
import {Logger} from 'arkanalyzer';
import {Command, OptionValues} from 'commander';
import {FileUtils} from '../../utils/common/FileUtils';
import fs from 'fs';
import {ANALYSIS_MODE} from './utils';
const logger = Logger.getLogger(LOG_MODULE_TYPE.TOOL, 'DependencyAnalysisCliParser');
const SUPPORTED_EXTENSIONS: string[] = ['.ts', '.ets', '.js'];
export interface CommandLineArgs {
mode: string;
projectPath: string;
sdkPath: string;
cSdkPaths: string[];
outputDir: string;
sourceFiles: string[]
}
function getFileList(path: string): string[] {
let fileList: string[] = [];
try {
const jsonData = JSON.parse(fs.readFileSync(path, 'utf8'));
fileList.push(...((jsonData?.sourceFiles ?? []) as string[]));
} catch (error) {
logger.error(`Error occurred while reading file list from ${path}: ${error}`);
}
return fileList;
}
export function genArgsByConfig(configPath: string): CommandLineArgs {
let jsonData;
try {
jsonData = JSON.parse(fs.readFileSync(configPath, 'utf8'));
} catch (error) {
logger.error(`Error occurred while reading config from ${configPath}: ${error}`);
process.exit(1);
}
if (!jsonData.mode) {
jsonData.mode = 'all';
logger.warn(`Analysis mode is not set, bu default set to 'all'.`);
}
if (!ANALYSIS_MODE.has(jsonData.mode.toLowerCase())) {
logger.error(`Invalid mode set in config file: ${jsonData.mode}`);
process.exit(1);
}
if (!jsonData || !jsonData.projectPath || !jsonData.sdkPath) {
logger.error(`The configurations in ${configPath} is not valid, please check.`);
process.exit(1);
}
logger.info(`Parsed config file: ${JSON.stringify(jsonData)}`);
let files: string[];
if (jsonData.analysisFilesPath) {
files = getFileList(jsonData.analysisFilesPath);
} else {
const fileDir = jsonData.analysisDir ? jsonData.analysisDir : jsonData.projectPath;
files = FileUtils.getAllFiles(fileDir, SUPPORTED_EXTENSIONS);
}
return {
mode: jsonData.mode.toLowerCase(),
projectPath: jsonData.projectPath,
sdkPath: jsonData.sdkPath,
cSdkPaths: jsonData.cSdkPaths ?? [],
outputDir: jsonData.outputDir ?? './out',
sourceFiles: files
};
}
function getCliOptions(program: Command, args: string[]): OptionValues {
program
.option('--mode [mode]', 'run mode, by default analyze all')
.option('--configPath [configPath]', 'basic config path')
.option('--projectPath [projectPath]', 'project path')
.option('--sdkPath [sdkPath]', 'sdk path')
.option('--cSdkPaths [cSdkPaths...]', 'c sdk paths')
.option('--outputDir [outputDir]', 'output directory')
.option('--analysisFilesPath [analysisFilesPath]', 'path of source files to be analyzed')
.option('--analysisDir [analysisDir]', 'directory to be analyzed, by default use project root')
.parse(args);
return program.opts();
}
export function parseCliArgs(): CommandLineArgs {
logger.info('Parsing cli options...');
const program = new Command();
const options = getCliOptions(program, process.argv);
logger.info(`Parsed cli options: ${JSON.stringify(options)}`);
if (options.configPath) {
logger.info(`Parsing configuration from configFile: ${options.configPath}`);
return genArgsByConfig(options.configPath);
}
if (!options.projectPath || !options.sdkPath) {
logger.error(`Invalid command line options, projectPath and sdkPath are required when configPath is not set.`);
process.exit(1);
}
if (!options.mode) {
options.mode = 'all';
logger.warn(`Analysis mode is not set, bu default set to 'all'.`);
}
if (!ANALYSIS_MODE.has(options.mode.toLowerCase())) {
logger.error(`Invalid mode set in CLI options: ${options.mode}`);
process.exit(1);
}
let files: string[];
if (options.analysisFilesPath) {
files = getFileList(options.analysisFilesPath);
} else {
const fileDir = options.analysisDir ? options.analysisDir : options.projectPath;
files = FileUtils.getAllFiles(fileDir, SUPPORTED_EXTENSIONS);
}
return {
mode: options.mode.toLowerCase(),
projectPath: options.projectPath,
sdkPath: options.sdkPath,
cSdkPaths: options.cSdkPaths ?? [],
outputDir: options.outputDir ?? './out',
sourceFiles: files
};
}