/* * Copyright (c) 2025 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 * as path from 'path'; import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; import { FileReports } from '../../model/Defects'; import { FileUtils, WriteFileMode } from './FileUtils'; const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'GeneratingJsonFile'); const severitys: string[] = ['OFF', 'WARN', 'ERROR', 'SUGGESTION']; const FILE_NAMING_RULE = '@hw-stylistic/file-naming-convention'; export class GeneratingJsonFile { public static generatingJsonFile(filePath: string, fileReports: FileReports[]): void { const fileDefectInfos = this.format(fileReports); let results: Map = new Map(); for (let fileDefectInfo of fileDefectInfos) { this.addResult(fileDefectInfo, results); } const jsonString = this.format2(results); try { FileUtils.writeToFile(filePath, jsonString, WriteFileMode.OVERWRITE); } catch (error) { logger.error(`write file ${filePath} failed, error: ${error}`); } } /** * 过滤掉部分不需要的defect属性 * * @param fileReports 原始文件缺陷信息数组 * @returns 过滤后的文件缺陷信息数组 */ private static format(fileReports: FileReports[]): FileDefectInfo[] { const fileDefectInfos: FileDefectInfo[] = []; for (const fileReport of fileReports) { const fileDefectInfo: FileDefectInfo = { filePath: fileReport.filePath, defects: [] }; for (const defect of fileReport.defects) { const defectInfo: DefectInfo = { reportLine: defect.reportLine, reportColumn: defect.reportColumn, ruleId: defect.ruleId, severity: severitys[defect.severity], mergeKey: defect.mergeKey, description: defect.description, ruleDocPath: defect.ruleDocPath }; fileDefectInfo.defects.push(defectInfo); } fileDefectInfos.push(fileDefectInfo); } return fileDefectInfos; } private static addResult(defect: FileDefectInfo, results: Map): void { const normalizedPath = path.normalize(defect.filePath).toLocaleLowerCase(); if (!results.has(normalizedPath)) { results.set(normalizedPath, defect); } else { results.get(normalizedPath)?.defects.push(...defect.defects); } const defectInfo = results.get(normalizedPath); defectInfo?.defects.sort((defectA, defectB) => { if (defectA.ruleId === FILE_NAMING_RULE) { return -1; } if (defectB.ruleId === FILE_NAMING_RULE) { return 1; } if (defectA.reportLine === defectB.reportLine) { if (defectA.reportColumn === defectB.reportColumn) { return defectA.mergeKey.localeCompare(defectB.mergeKey); } return defectA.reportColumn - defectB.reportColumn; } return defectA.reportLine - defectB.reportLine; }); } private static format2(results: Map): string { const jsonResults: JsonResult[] = []; for (let result of results) { const oneResult: JsonResult = { filePath: '', messages: [] }; oneResult.filePath = result[1].filePath; let defects = result[1].defects; for (let defect of defects) { const oneDefect: SimpleDefect = { line: 0, column: 0, severity: '', message: '', rule: '', }; oneDefect.line = defect.reportLine; oneDefect.column = defect.reportColumn; oneDefect.severity = defect.severity; oneDefect.message = defect.description; oneDefect.rule = defect.ruleId; oneResult.messages.push(oneDefect); } jsonResults.push(oneResult); } return JSON.stringify(jsonResults, null, 2); } } interface JsonResult { filePath: string; messages: SimpleDefect[]; } interface SimpleDefect { line: number; column: number; severity: string; message: string; rule: string | null; } interface FileDefectInfo { filePath: string; defects: DefectInfo[]; } interface DefectInfo { severity: string; description: string; mergeKey: string; reportLine: number; reportColumn: number; ruleId: string | null; ruleDocPath: string | null; }