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