1/* 2 * Copyright (c) 2023 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 */ 15import { ApiResultSimpleInfo, ApiResultMessage, ApiBaseInfo, checkEntryType } from '../../typedef/checker/result_type'; 16import { Check } from './src/api_check_plugin'; 17import { LogUtil } from '../../utils/logUtil'; 18import { GenerateFile } from '../../utils/checkUtils'; 19import { compositiveResult, compositiveLocalResult, apiCheckResult, hierarchicalRelationsSet } from '../../utils/checkUtils'; 20import { DOC, DEFINE, CHANEGE } from './config/api_check_config.json'; 21import { ApiChangeCheck } from './src/check_api_diff'; 22 23/** 24 * local entrance 25 */ 26export class LocalEntry { 27 28 static checkEntryLocal(checkParam: checkEntryType): ApiResultMessage[] { 29 let allResult: ApiResultMessage[] = apiCheckResult; 30 try { 31 Check.scanEntry(checkParam.filePathArr, checkParam.prId); 32 const incrementResult: ApiResultSimpleInfo[] = LocalEntry.filterIncrementResult(compositiveResult, checkParam.isIncrement); 33 LocalEntry.maskAlarm(incrementResult, checkParam.fileRuleArr); 34 } catch (error) { 35 LogUtil.e('API_CHECK_ERROR', error); 36 } finally { 37 GenerateFile.writeFile(apiCheckResult, checkParam.output, {}); 38 if (checkParam.isOutExcel === 'true') { 39 GenerateFile.writeExcelFile(apiCheckResult); 40 } 41 } 42 return allResult; 43 } 44 45 /** 46 * 过滤增量检查结果 47 * 48 * @param {ApiResultSimpleInfo[]} allResultInfo 所有apicheck结果 49 * @param {boolean} isIncrement 是否为命令配置的增量检查,默认为true 50 * @return {*} {ApiResultSimpleInfo[]} 51 * @memberof LocalEntry 52 */ 53 static filterIncrementResult(allResultInfo: ApiResultSimpleInfo[], isIncrement: boolean): ApiResultSimpleInfo[] { 54 // 不需要增量检查或者diff数据为空 55 if (!isIncrement || hierarchicalRelationsSet.size === 0) { 56 return allResultInfo; 57 } 58 return allResultInfo.filter((resultItem: ApiResultSimpleInfo) => { 59 return !Boolean(process.env.IS_INCREMENT_CHECK) || LocalEntry.hasHierarchicalRelations(resultItem); 60 }); 61 } 62 63 static hasHierarchicalRelations(resultItem: ApiResultSimpleInfo): boolean { 64 if (process.env.NODE_ENV === 'development') { 65 return hierarchicalRelationsSet.has(resultItem.hierarchicalRelations); 66 } else if (process.env.NODE_ENV === 'production') { 67 return hierarchicalRelationsSet.has(resultItem.hierarchicalRelations); 68 } 69 return hierarchicalRelationsSet.has(resultItem.hierarchicalRelations); 70 } 71 72 static maskAlarm(allResultInfo: ApiResultSimpleInfo[], fileRuleArr: string[]): void { 73 const localScan: boolean = (fileRuleArr.length === 1 && fileRuleArr[0] === 'all') ? true : false; 74 const apiCheckInfos: Map<string, string> = new Map(Object.entries({ ...DOC, ...DEFINE, ...CHANEGE })); 75 let apiCheckAdmissiveSet: Set<string> = new Set(); 76 if (localScan) { 77 apiCheckAdmissiveSet = new Set([...apiCheckInfos.values()]); 78 } else { 79 fileRuleArr.forEach((apiCheckItem: string) => { 80 const apiCheckItemMessage: string | undefined = apiCheckInfos.get(apiCheckItem); 81 if (apiCheckItemMessage) { 82 apiCheckAdmissiveSet.add(apiCheckItemMessage); 83 } 84 }); 85 } 86 let allResultInfoSet: Set<ApiResultSimpleInfo> = new Set(allResultInfo); 87 const maskResult: ApiResultSimpleInfo[] = LocalEntry.filterAllResultInfo(allResultInfo, 88 apiCheckInfos, apiCheckAdmissiveSet); 89 maskResult.forEach(resultItem => { 90 const apiBaseInfos: ApiBaseInfo = new ApiBaseInfo(); 91 apiBaseInfos 92 .setApiName(resultItem.apiName) 93 .setApiType(resultItem.apiType) 94 .setHierarchicalRelations(resultItem.hierarchicalRelations) 95 .setParentModuleName(resultItem.parentModuleName); 96 97 const apiChecktErrorLog: ApiResultMessage = new ApiResultMessage(); 98 apiChecktErrorLog 99 .setFilePath(resultItem.filePath) 100 .setLocation(resultItem.location) 101 .setLevel(resultItem.level) 102 .setType(resultItem.type) 103 .setMessage(resultItem.message) 104 .setMainBuggyCode(resultItem.apiText) 105 .setMainBuggyLine(resultItem.location) 106 .setExtendInfo(apiBaseInfos); 107 apiCheckResult.push(apiChecktErrorLog); 108 }); 109 } 110 111 static filterAllResultInfo(allResultInfo: ApiResultSimpleInfo[], apiCheckInfos: Map<string, string>, 112 apiCheckAdmissiveSet: Set<string>): ApiResultSimpleInfo[] { 113 return allResultInfo.filter((resultItem: ApiResultSimpleInfo) => { 114 let resultItemInfo: string = resultItem.message.replace(/API check error of \[.*\]: /g, ''); 115 const regex1 = /Prohibited word in \[.*\]:{option}.The word allowed is \[.*\]\./g; 116 const regex2 = /Prohibited word in \[.*\]:{ability} in the \[.*\] file\./g; 117 const regex3 = /please confirm whether it needs to be corrected to a common word./g; 118 const regex4 = /tag does not exist. Please use a valid JSDoc tag./g; 119 const regex5 = /The event name should be named by small hump./g; 120 if (/\d/g.test(resultItemInfo)) { 121 resultItemInfo = resultItemInfo.replace(/\d+/g, '1'); 122 } 123 if (regex1.test(resultItemInfo)) { 124 resultItemInfo = JSON.stringify(apiCheckInfos.get('API_DEFINE_NAME_01')).replace(/\"/g, ''); 125 } 126 if (regex2.test(resultItemInfo)) { 127 resultItemInfo = JSON.stringify(apiCheckInfos.get('API_DEFINE_NAME_02')).replace(/\"/g, ''); 128 } 129 if (regex3.test(resultItemInfo)) { 130 resultItemInfo = resultItemInfo.replace(/\{.*\}/g, '{XXXX}'); 131 } 132 if (regex4.test(resultItemInfo)) { 133 resultItemInfo = resultItemInfo.replace(/\[.*\]/g, '[XXXX]'); 134 } 135 if (regex5.test(resultItemInfo)) { 136 resultItemInfo = resultItemInfo.replace(/\[.*\]/g, '[XXXX]'); 137 } 138 if (/This name \[.*\] should be named by/g.test(resultItemInfo)) { 139 resultItemInfo = resultItemInfo.replace(/\[.*\]/g, '[XXXX]'); 140 } 141 if (apiCheckAdmissiveSet.has(resultItemInfo)) { 142 const key: string = LocalEntry.filterApiCheckInfos(apiCheckInfos, resultItemInfo); 143 if (key !== '') { 144 resultItem.setType(key); 145 } 146 } 147 return apiCheckAdmissiveSet.has(resultItemInfo); 148 }); 149 } 150 151 static filterApiCheckInfos(apiCheckInfos: Map<string, string>, resultItemInfo: string): string { 152 for (let [key, value] of apiCheckInfos.entries()) { 153 if (value === resultItemInfo) { 154 return key; 155 } 156 } 157 return ''; 158 } 159 160 static apiChangeCheckEntryLocal(checkParam: checkEntryType): ApiResultMessage[] { 161 let apiChangeCheckResult: ApiResultMessage[] = apiCheckResult; 162 try { 163 ApiChangeCheck.checkApiChange(checkParam.prId); 164 LocalEntry.maskAlarm(compositiveResult, checkParam.fileRuleArr); 165 } catch (error) { 166 LogUtil.e('API_CHECK_ERROR', error); 167 } finally { 168 GenerateFile.writeFile(apiCheckResult, checkParam.output, {}); 169 if (checkParam.isOutExcel === 'true') { 170 GenerateFile.writeExcelFile(apiCheckResult); 171 } 172 } 173 return apiChangeCheckResult; 174 } 175} 176