1/* 2 * Copyright (c) 2022-2024 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 * as fs from 'fs'; 17 18const ARK_TS_ISSUES_PREFIX = 'ArkTS'; 19const ARK_TS_ISSUES_ERROR_CATEGORY = 'ArkTS Migration Errors'; 20 21interface DefectInfo { 22 // warn: 1; error: 2; 23 severity: number; 24 description: string; 25 mergeKey: string; 26 reportLine: number; 27 reportColumn: number; 28 ruleId: string | null; 29 ruleDocPath: string | null; 30 category: string | null; 31 fixable: boolean; 32 fixKey: string; 33} 34 35interface FileDefectInfo { 36 defects: DefectInfo[]; 37 output: string | undefined; 38 filePath: string; 39} 40 41type ReportJson = FileDefectInfo[]; 42 43interface ArkTsIssueType { 44 description: string; 45 type: string; 46 count: number; 47} 48 49interface Statistics { 50 totalErrors: number; 51 totalWarnings: number; 52 linesWithErrors: number; 53 linesWithWarnings: number; 54 issues: Map<number, ArkTsIssueType>; 55} 56 57function isError(defectInfo: DefectInfo): boolean { 58 return defectInfo.category === ARK_TS_ISSUES_ERROR_CATEGORY; 59} 60 61function fillIssueInfo(statistics: Statistics, defectInfo: DefectInfo): void { 62 const recipeNo = parseInt( 63 defectInfo.ruleDocPath.substring('docs/recipe'.length, defectInfo.ruleDocPath.length - '.md'.length) 64 ); 65 const issueInfo = statistics.issues.get(recipeNo); 66 if (!issueInfo) { 67 statistics.issues.set(recipeNo, { 68 description: defectInfo.description, 69 type: isError(defectInfo) ? 'error' : 'warn', 70 count: 1 71 }); 72 } else { 73 issueInfo.count += 1; 74 } 75} 76 77function parse(reportJson: ReportJson): Statistics { 78 const statistics: Statistics = { 79 totalErrors: 0, 80 totalWarnings: 0, 81 linesWithErrors: 0, 82 linesWithWarnings: 0, 83 issues: new Map() 84 }; 85 86 for (const fileInfo of reportJson) { 87 const linesWithErrors: Set<number> = new Set(); 88 const linesWithWarnings: Set<number> = new Set(); 89 90 for (const defectInfo of fileInfo.defects) { 91 // count only issues from ArkTS Linter 92 if (!defectInfo.category.startsWith(ARK_TS_ISSUES_PREFIX)) { 93 continue; 94 } 95 96 fillIssueInfo(statistics, defectInfo); 97 98 if (isError(defectInfo)) { 99 statistics.totalErrors += 1; 100 linesWithErrors.add(defectInfo.reportLine); 101 } else { 102 statistics.totalWarnings += 1; 103 linesWithWarnings.add(defectInfo.reportLine); 104 } 105 } 106 statistics.linesWithErrors += linesWithErrors.size; 107 statistics.linesWithWarnings += linesWithWarnings.size; 108 } 109 110 return statistics; 111} 112 113function read(filePath: string): ReportJson { 114 return JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8', flag: 'r' })); 115} 116 117function main(): void { 118 if (process.argv.length < 3) { 119 console.error('Path to input json was not provided, exiting'); 120 process.exit(1); 121 } 122 console.log(parse(read(process.argv[2]))); 123} 124 125/* 126 * file is stored in project's directory under the following path: 127 * <PROJECT_ROOT_DIR>/.idea/code-linter/eslintAgent/output.json 128 */ 129main(); 130