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 fs from 'fs'; 16import path from 'path'; 17import { Parser, FilesMap } from '../../parser/parser'; 18import { ApiInfo, BasicApiInfo, notJsDocApiTypes } from '../../../typedef/parser/ApiInfoDefination'; 19import { 20 ErrorType, 21 ErrorID, 22 LogType, 23 ErrorLevel, 24 ErrorTagFormat, 25 ErrorMessage, 26 ApiCheckInfo, 27 ErrorBaseInfo, 28} from '../../../typedef/checker/result_type'; 29import { ClassInfo } from '../../../typedef/parser/ApiInfoDefination'; 30import { Comment } from '../../../typedef/parser/Comment'; 31import { compositiveResult, compositiveLocalResult, CommonFunctions, cleanApiCheckResult } from '../../../utils/checkUtils'; 32import { OrderCheck } from './tag_order_check'; 33import { TagNameCheck } from './tag_name_check'; 34import { LegalityCheck } from './tag_legality_check'; 35import { TagRepeatCheck } from './tag_repeat_check'; 36import { AddErrorLogs } from './compile_info'; 37import { TagValueCheck } from './tag_value_check'; 38import { WordsCheck } from './words_check'; 39import { ForbiddenWordsCheck } from './forbidden_words_check'; 40import { ApiNamingCheck } from './naming_check'; 41import { CheckHump } from './check_hump'; 42import { EventMethodChecker } from './event_method_check'; 43import { EventMethodData } from '../../../typedef/checker/event_method_check_interface'; 44import { ApiChangeCheck } from './check_api_diff'; 45import { TagInheritCheck } from './tag_inherit_check'; 46import { ChineseCheck } from './check_chinese'; 47import { AnonymousFunctionCheck } from './check_anonymous_function'; 48import { CheckErrorCode } from './check_error_code'; 49 50export let currentFilePath: string = ''; 51 52export class Check { 53 /** 54 * checker tool main entrance 55 * @param { string[] } files -File path for storing file information. 56 */ 57 static scanEntry(files: string[], prId: string): void { 58 cleanApiCheckResult(); 59 ApiChangeCheck.checkApiChange(prId); 60 files.forEach((filePath: string, index: number) => { 61 currentFilePath = filePath; 62 if (process.env.NODE_ENV !== 'development' && filePath.indexOf('build-tools') !== -1) { 63 return; 64 } 65 console.log(`scaning file in no ${++index}!`); 66 const fileParseResult: FilesMap = Check.parseAPICodeStyle(filePath); 67 const baseInfos: BasicApiInfo[] = Parser.getAllBasicApi(fileParseResult); 68 Check.checkNodeInfos(baseInfos as ClassInfo[]); 69 const currFileInfo = fileParseResult.get(path.basename(filePath)); 70 if (currFileInfo) { 71 CheckHump.checkAPIFileName(currFileInfo); 72 } 73 CheckHump.checkAllAPINameOfHump(baseInfos); 74 //words check 75 WordsCheck.wordCheckResultsProcessing(baseInfos); 76 // event check 77 const eventMethodChecker: EventMethodChecker = new EventMethodChecker(fileParseResult); 78 const eventMethodDataMap: Map<string, EventMethodData> = eventMethodChecker.getAllEventMethod(); 79 eventMethodChecker.checkEventMethod(eventMethodDataMap); 80 }); 81 } 82 83 /** 84 * Obtain the path of the file to be checked. 85 * @param { string } url -File path for storing file information. 86 * @returns { Array<string> } -file path array 87 */ 88 static getMdFiles(url: string): Array<string> { 89 const content: string = fs.readFileSync(url, 'utf-8'); 90 const mdFiles: Array<string> = content.split(/[(\r\n)\r\n]+/); 91 return mdFiles; 92 } 93 94 /** 95 * Based on a single file path,parse it using the Parser method. 96 * @param { string } filePath -single file path to be checked 97 * @returns { FilesMap } 98 */ 99 static parseAPICodeStyle(filePath: string): FilesMap { 100 const parseResult: FilesMap = Parser.parseFile(path.resolve(filePath, '..'), filePath); 101 return parseResult; 102 } 103 104 /** 105 * Obtain all API information and check api jsdoc 106 * @param { ClassInfo[] } baseInfos 107 */ 108 static checkNodeInfos(baseInfos: ClassInfo[]): void { 109 let allNodeInfos: ApiInfo[] = []; 110 Check.getHasJsdocApiInfos(baseInfos, allNodeInfos); 111 // for all nodes of the current file 112 allNodeInfos.forEach((singleApi: ApiInfo) => { 113 const apiJsdoc: Comment.JsDocInfo | undefined = singleApi.getLastJsDocInfo(); 114 const apiJsdocTextLength: number = singleApi.getJsDocText().length; 115 if (singleApi.getApiType() === 'Method' && singleApi.getParentApi()?.apiType === 'Struct') { 116 return; 117 } 118 if (apiJsdoc === undefined || apiJsdocTextLength === 0) { 119 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 120 errorBaseInfo 121 .setErrorID(ErrorID.NO_JSDOC_ID) 122 .setErrorLevel(ErrorLevel.MIDDLE) 123 .setErrorType(ErrorType.NO_JSDOC) 124 .setLogType(LogType.LOG_JSDOC) 125 .setErrorInfo(ErrorMessage.ERROR_NO_JSDOC); 126 const apiInfoNojsdoc: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 127 errorBaseInfo); 128 AddErrorLogs.addAPICheckErrorLogs(apiInfoNojsdoc, compositiveResult, compositiveLocalResult); 129 } else { 130 if (apiJsdoc.getKit() === 'NA') { 131 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 132 errorBaseInfo 133 .setErrorID(ErrorID.WRONG_SCENE_ID) 134 .setErrorLevel(ErrorLevel.MIDDLE) 135 .setErrorType(ErrorType.WRONG_SCENE) 136 .setLogType(LogType.LOG_JSDOC) 137 .setErrorInfo(CommonFunctions.createErrorInfo(ErrorMessage.ERROR_LOST_LABEL, ['kit'])); 138 const apiInfoNoKit: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 139 errorBaseInfo); 140 AddErrorLogs.addAPICheckErrorLogs(apiInfoNoKit, compositiveResult, compositiveLocalResult); 141 } 142 if (!apiJsdoc.getFileTagContent()) { 143 const apiInfo: ApiCheckInfo = new ApiCheckInfo(); 144 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 145 errorBaseInfo 146 .setErrorID(ErrorID.WRONG_SCENE_ID) 147 .setErrorLevel(ErrorLevel.MIDDLE) 148 .setErrorType(ErrorType.WRONG_SCENE) 149 .setLogType(LogType.LOG_JSDOC) 150 .setErrorInfo(CommonFunctions.createErrorInfo(ErrorMessage.ERROR_LOST_LABEL, ['file'])); 151 const apiInfoNoFile: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 152 errorBaseInfo); 153 AddErrorLogs.addAPICheckErrorLogs(apiInfoNoFile, compositiveResult, compositiveLocalResult); 154 } 155 // legality check 156 const tagLegalityCheckResult: ErrorTagFormat[] = LegalityCheck.apiLegalityCheck(singleApi, apiJsdoc); 157 // order check 158 const orderCheckResult: ErrorTagFormat = OrderCheck.orderCheck(singleApi, apiJsdoc); 159 // api naming check 160 const namingCheckResult: ErrorTagFormat = ApiNamingCheck.namingCheck(singleApi); 161 // check jsdoc chinese 162 const chineseCheckResult: ErrorTagFormat = ChineseCheck.checkChinese(apiJsdoc); 163 // check error code 164 const errorCodeResult: ErrorTagFormat = CheckErrorCode.checkErrorCode(apiJsdoc); 165 // tags name check 166 const tagNameCheckResult: ErrorTagFormat = TagNameCheck.tagNameCheck(apiJsdoc); 167 // tags inherit check 168 const tagInheritCheckResult: ErrorTagFormat[] = TagInheritCheck.tagInheritCheck(singleApi); 169 // tags value check 170 const tagValueCheckResult: ErrorTagFormat[] = TagValueCheck.tagValueCheck(singleApi, apiJsdoc); 171 // tags repeat check 172 const tagRepeatCheckResult: ErrorTagFormat[] = TagRepeatCheck.tagRepeatCheck(apiJsdoc); 173 // api forbidden wors check 174 const forbiddenWordsCheckResult: ErrorTagFormat = ForbiddenWordsCheck.forbiddenWordsCheck(singleApi as ClassInfo); 175 176 const anonymousFunction: ErrorTagFormat = AnonymousFunctionCheck.checkAnonymousFunction(singleApi); 177 178 if (!orderCheckResult.state) { 179 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 180 errorBaseInfo 181 .setErrorID(ErrorID.WRONG_ORDER_ID) 182 .setErrorLevel(ErrorLevel.MIDDLE) 183 .setErrorType(ErrorType.WRONG_ORDER) 184 .setLogType(LogType.LOG_JSDOC) 185 .setErrorInfo(orderCheckResult.errorInfo); 186 const apiInfoOrder: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 187 errorBaseInfo); 188 AddErrorLogs.addAPICheckErrorLogs(apiInfoOrder, compositiveResult, compositiveLocalResult); 189 } 190 if (!tagNameCheckResult.state) { 191 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 192 errorBaseInfo 193 .setErrorID(ErrorID.UNKNOW_DECORATOR_ID) 194 .setErrorLevel(ErrorLevel.MIDDLE) 195 .setErrorType(ErrorType.UNKNOW_DECORATOR) 196 .setLogType(LogType.LOG_JSDOC) 197 .setErrorInfo(tagNameCheckResult.errorInfo); 198 const apiInfoName: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 199 errorBaseInfo); 200 AddErrorLogs.addAPICheckErrorLogs(apiInfoName, compositiveResult, compositiveLocalResult); 201 } 202 if (!forbiddenWordsCheckResult.state) { 203 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 204 errorBaseInfo 205 .setErrorID(ErrorID.FORBIDDEN_WORDS_ID) 206 .setErrorLevel(ErrorLevel.MIDDLE) 207 .setErrorType(ErrorType.FORBIDDEN_WORDS) 208 .setLogType(LogType.LOG_JSDOC) 209 .setErrorInfo(forbiddenWordsCheckResult.errorInfo); 210 const apiInfoForbiddenWords: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 211 errorBaseInfo); 212 AddErrorLogs.addAPICheckErrorLogs(apiInfoForbiddenWords, compositiveResult, compositiveLocalResult); 213 } 214 if (!namingCheckResult.state) { 215 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 216 errorBaseInfo 217 .setErrorID(ErrorID.NAMING_ERRORS_ID) 218 .setErrorLevel(ErrorLevel.MIDDLE) 219 .setErrorType(ErrorType.NAMING_ERRORS) 220 .setLogType(LogType.LOG_JSDOC) 221 .setErrorInfo(namingCheckResult.errorInfo); 222 const apiInfoNaming: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 223 errorBaseInfo); 224 AddErrorLogs.addAPICheckErrorLogs(apiInfoNaming, compositiveResult, compositiveLocalResult); 225 } 226 if (!chineseCheckResult.state) { 227 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 228 errorBaseInfo 229 .setErrorID(ErrorID.JSDOC_HAS_CHINESE) 230 .setErrorLevel(ErrorLevel.MIDDLE) 231 .setErrorType(ErrorType.JSDOC_HAS_CHINESE) 232 .setLogType(LogType.LOG_JSDOC) 233 .setErrorInfo(chineseCheckResult.errorInfo); 234 const apiInfoChineseCheck: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 235 errorBaseInfo); 236 AddErrorLogs.addAPICheckErrorLogs(apiInfoChineseCheck, compositiveResult, compositiveLocalResult); 237 } 238 if (!errorCodeResult.state) { 239 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 240 errorBaseInfo 241 .setErrorID(ErrorID.ERROR_ERROR_CODE) 242 .setErrorLevel(ErrorLevel.MIDDLE) 243 .setErrorType(ErrorType.ERROR_ERROR_CODE) 244 .setLogType(LogType.LOG_JSDOC) 245 .setErrorInfo(errorCodeResult.errorInfo); 246 const apiInfoErrorCode: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 247 errorBaseInfo); 248 AddErrorLogs.addAPICheckErrorLogs(apiInfoErrorCode, compositiveResult, compositiveLocalResult); 249 } 250 tagInheritCheckResult.forEach((inheritCheckResult: ErrorTagFormat) => { 251 if (!inheritCheckResult.state) { 252 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 253 errorBaseInfo 254 .setErrorID(ErrorID.WRONG_SCENE_ID) 255 .setErrorLevel(ErrorLevel.MIDDLE) 256 .setErrorType(ErrorType.WRONG_SCENE) 257 .setLogType(LogType.LOG_JSDOC) 258 .setErrorInfo(inheritCheckResult.errorInfo); 259 const apiInfoInherit: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 260 errorBaseInfo); 261 AddErrorLogs.addAPICheckErrorLogs(apiInfoInherit, compositiveResult, compositiveLocalResult); 262 } 263 }); 264 tagLegalityCheckResult.forEach((legalityResult) => { 265 if (legalityResult.state === false) { 266 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 267 errorBaseInfo 268 .setErrorID(ErrorID.WRONG_SCENE_ID) 269 .setErrorLevel(ErrorLevel.MIDDLE) 270 .setErrorType(ErrorType.WRONG_SCENE) 271 .setLogType(LogType.LOG_JSDOC) 272 .setErrorInfo(legalityResult.errorInfo); 273 const apiInfoInherit: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 274 errorBaseInfo); 275 AddErrorLogs.addAPICheckErrorLogs(apiInfoInherit, compositiveResult, compositiveLocalResult); 276 } 277 }); 278 tagValueCheckResult.forEach((valueResult) => { 279 if (valueResult.state === false) { 280 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 281 errorBaseInfo 282 .setErrorID(ErrorID.WRONG_VALUE_ID) 283 .setErrorLevel(ErrorLevel.MIDDLE) 284 .setErrorType(ErrorType.WRONG_VALUE) 285 .setLogType(LogType.LOG_JSDOC) 286 .setErrorInfo(valueResult.errorInfo); 287 const apiInfoValue: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 288 errorBaseInfo); 289 AddErrorLogs.addAPICheckErrorLogs(apiInfoValue, compositiveResult, compositiveLocalResult); 290 } 291 }); 292 tagRepeatCheckResult.forEach((repeatResult) => { 293 if (repeatResult.state === false) { 294 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 295 errorBaseInfo 296 .setErrorID(ErrorID.WRONG_SCENE_ID) 297 .setErrorLevel(ErrorLevel.MIDDLE) 298 .setErrorType(ErrorType.WRONG_SCENE) 299 .setLogType(LogType.LOG_JSDOC) 300 .setErrorInfo(repeatResult.errorInfo); 301 const apiInfoRepeat: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 302 errorBaseInfo); 303 AddErrorLogs.addAPICheckErrorLogs(apiInfoRepeat, compositiveResult, compositiveLocalResult); 304 } 305 }); 306 if (!anonymousFunction.state) { 307 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 308 errorBaseInfo 309 .setErrorID(ErrorID.WRONG_SCENE_ID) 310 .setErrorLevel(ErrorLevel.MIDDLE) 311 .setErrorType(ErrorType.WRONG_SCENE) 312 .setLogType(LogType.LOG_JSDOC) 313 .setErrorInfo(anonymousFunction.errorInfo); 314 const apiInfoAnonymous: ApiCheckInfo = CommonFunctions.getErrorInfo(singleApi, apiJsdoc, currentFilePath, 315 errorBaseInfo); 316 AddErrorLogs.addAPICheckErrorLogs(apiInfoAnonymous, compositiveResult, compositiveLocalResult); 317 } 318 } 319 }); 320 } 321 /** 322 * Filter out all nodes with comments. 323 * @param { BasicApiInfo[] } childNodeApis -original data. 324 * @param { ApiInfo[] } childNodeInfos -processed data. 325 */ 326 static getHasJsdocApiInfos(childNodeApis: BasicApiInfo[], childNodeInfos: ApiInfo[]): void { 327 childNodeApis.forEach((childNodeApi) => { 328 if (!notJsDocApiTypes.has(childNodeApi.getApiType())) { 329 childNodeInfos.push(childNodeApi as ApiInfo); 330 } 331 }); 332 return; 333 } 334} 335