• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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