• 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 {
16  ErrorTagFormat,
17  NameDictionaryType,
18  NameScenarioType,
19  ErrorMessage,
20} from '../../../typedef/checker/result_type';
21import { ApiInfo } from '../../../typedef/parser/ApiInfoDefination';
22import { Comment } from '../../../typedef/parser/Comment';
23import { CommonFunctions, punctuationMarkSet } from '../../../utils/checkUtils';
24import { WordsCheck } from './words_check';
25const nameDictionary = require('../config/name_dictionary.json');
26const nameScenarioScope = require('../config/name_scenario_scope.json');
27
28export class ApiNamingCheck {
29  /**
30   * Check if the Api name is correct.
31   * @param { Comment.JsDocInfo } apiJsdoc -api jsdoc all infomation
32   * @returns { boolean }
33   */
34  static namingCheck(singleApi: ApiInfo): ErrorTagFormat {
35    const tagNameCheckResult: ErrorTagFormat = {
36      state: true,
37      errorInfo: '',
38    };
39    const jsDocInfo: Comment.JsDocInfo[] = singleApi.getJsDocInfos();
40    const publishVersion: string = CommonFunctions.getSinceVersion(jsDocInfo[0].getSince());
41    const apiVersionToBeVerified: string = CommonFunctions.getCheckApiVersion();
42    const fileName: string = singleApi.getFilePath().toLowerCase();
43    const reg = /\s{2,}/g;
44    const regx = /(\/\*|\*\/|\*)|\n|\r/g;
45    let apiText: string = singleApi.getDefinedText().replace(regx, ' ');
46    punctuationMarkSet.forEach(punctuationMark => {
47      const punctuationMarkReg = new RegExp(punctuationMark, 'g');
48      if (punctuationMarkReg.test(apiText)) { apiText = apiText.replace(punctuationMarkReg, ' ').replace(reg, ' '); }
49    });
50    let apiWordsArr = apiText.split(/\s/g);
51    let basicWords: string[] = [];
52    apiWordsArr.forEach((apiWord) => { WordsCheck.splitComplexWords(apiWord, basicWords); });
53    basicWords.forEach((basicWord: string) => {
54      if (publishVersion === apiVersionToBeVerified) {
55        ApiNamingCheck.checkApiNamingWords(basicWord, tagNameCheckResult);
56        ApiNamingCheck.checkApiNamingScenario(fileName, tagNameCheckResult, singleApi);
57      }
58    });
59    return tagNameCheckResult;
60  }
61
62  /**
63   *
64   * @param { string } lowIdentifier
65   * @param { ErrorTagFormat } tagNameCheckResult
66   */
67  static checkApiNamingWords(lowIdentifier: string, tagNameCheckResult: ErrorTagFormat): void {
68    const lowercaseNamingMap: Map<string, NameDictionaryType> = ApiNamingCheck.getlowercaseNamingMap();
69    for (const [key, value] of lowercaseNamingMap) {
70      const prohibitedWordIndex: number = lowIdentifier.indexOf(key);
71      if (prohibitedWordIndex === -1) {
72        continue;
73      }
74      const lowercaseIgnoreWordArr: string[] = value.ignore.map((word: string) => word.toLowerCase());
75      const internalWord: string = lowIdentifier.substring(prohibitedWordIndex, prohibitedWordIndex + key.length);
76      if (lowercaseIgnoreWordArr.length === 0) {
77        tagNameCheckResult.state = false;
78        tagNameCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_NAMING, [
79          lowIdentifier,
80          internalWord,
81          value.suggestion,
82        ]);
83        break;
84      } else {
85        const isIgnoreWord: boolean = ApiNamingCheck.checkIgnoreWord(lowercaseIgnoreWordArr, lowIdentifier);
86        if (isIgnoreWord === false) {
87          tagNameCheckResult.state = false;
88          tagNameCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_NAMING, [
89            lowIdentifier,
90            internalWord,
91            value.suggestion,
92          ]);
93        }
94      }
95    }
96  }
97
98  /**
99   *
100   * @param {string} lowIdentifier
101   * @param {ErrorTagFormat} tagNameCheckResult
102   * @param {ApiInfo} singleApi
103   */
104  static checkApiNamingScenario(lowIdentifier: string, tagNameCheckResult: ErrorTagFormat, singleApi: ApiInfo): void {
105    const lowercaseNamingScenarioMap = ApiNamingCheck.getlowercaseNamingScenarioMap();
106    for (const [key, value] of lowercaseNamingScenarioMap) {
107      const prohibitedWordIndex: number = lowIdentifier.indexOf(key);
108      if (prohibitedWordIndex !== -1 && !ApiNamingCheck.isInAllowedFiles(value.files, singleApi.getFilePath())) {
109        tagNameCheckResult.state = false;
110        tagNameCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_SCENARIO, [
111          lowIdentifier,
112          key,
113          singleApi.getFilePath(),
114        ]);
115      }
116    }
117  }
118
119  /**
120   *
121   * @returns
122   */
123  static getlowercaseNamingMap(): Map<string, NameDictionaryType> {
124    const lowercaseNamingMap: Map<string, NameDictionaryType> = new Map();
125    for (const item of nameDictionary) {
126      const namingKey: string = item.badWord.toLowerCase();
127      const namingValue: NameDictionaryType = item;
128      lowercaseNamingMap.set(namingKey, namingValue);
129    }
130    return lowercaseNamingMap;
131  }
132
133  /**
134   *
135   * @param { string[] } lowercaseIgnoreWordArr
136   * @param { string }lowIdentifier
137   * @returns { boolean }
138   */
139  static checkIgnoreWord(lowercaseIgnoreWordArr: string[], lowIdentifier: string): boolean {
140    let isIgnoreWord: boolean = false;
141    for (let i = 0; i < lowercaseIgnoreWordArr.length; i++) {
142      if (lowercaseIgnoreWordArr[i] && lowIdentifier.indexOf(lowercaseIgnoreWordArr[i]) !== -1) {
143        isIgnoreWord = true;
144        break;
145      }
146    }
147    return isIgnoreWord;
148  }
149
150  /**
151   *
152   * @returns { Map<string, NameScenarioType> }
153   */
154  static getlowercaseNamingScenarioMap(): Map<string, NameScenarioType> {
155    const lowercaseNamingScenarioMap: Map<string, NameScenarioType> = new Map();
156    for (const item of nameScenarioScope) {
157      const scenarioKey = item.word.toLowerCase();
158      const scenarioValue: NameScenarioType = item;
159      lowercaseNamingScenarioMap.set(scenarioKey, scenarioValue);
160    }
161    return lowercaseNamingScenarioMap;
162  }
163
164  /**
165   *
166   * @param { string[] } files
167   * @param { string } fileName
168   * @returns { boolean }
169   */
170  static isInAllowedFiles(files: string[], fileName: string): boolean {
171    for (const item of files) {
172      const pattern: RegExp = new RegExp(item);
173      pattern.test(fileName);
174      if (pattern.test(fileName)) {
175        return true;
176      }
177    }
178    return false;
179  }
180}
181