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 */ 15 16import { ApiType, ExportImportValue, ImportInfo } from '../../../typedef/parser/ApiInfoDefination'; 17import { 18 ErrorType, 19 ErrorID, 20 LogType, 21 ErrorLevel, 22 ErrorTagFormat, 23 ErrorMessage, 24 ApiCheckInfo, 25 ErrorBaseInfo, 26} from '../../../typedef/checker/result_type'; 27import { BasicApiInfo } from '../../../typedef/parser/ApiInfoDefination'; 28import { tagsArrayOfOrder, officialTagArr, CommonFunctions } from '../../../utils/checkUtils'; 29import { AddErrorLogs } from './compile_info'; 30import { compositiveResult, compositiveLocalResult, punctuationMarkSet } from '../../../utils/checkUtils'; 31import { Set } from 'typescript'; 32import { dictionariesArr } from '../config/dictionaries.json'; 33import { dictionariesSupplementaryArr } from '../config/dictionaries_supplementary.json'; 34const dictionariesSet: Set<string> = new Set([ 35 ...dictionariesArr, 36 ...dictionariesSupplementaryArr, 37 ...tagsArrayOfOrder, 38 ...officialTagArr, 39]); 40 41export class WordsCheck { 42 /** 43 * words spell check 44 * @param { BasicApiInfo[] } baseInfos 45 */ 46 static wordCheckResultsProcessing(baseInfos: BasicApiInfo[]): void { 47 baseInfos.forEach((baseInfo) => { 48 if (baseInfo.getApiType() === ApiType.SOURCE_FILE) { 49 return; 50 } 51 let apiText: string = baseInfo.getJsDocText() + baseInfo.getDefinedText(); 52 if (baseInfo.getApiType() === ApiType.IMPORT) { 53 const importText: Array<ExportImportValue> = (baseInfo as ImportInfo).getImportValues(); 54 const importValueArr: string[] = []; 55 importText.forEach(importValue => { 56 importValueArr.push(importValue.key); 57 }); 58 apiText = importValueArr.join('|'); 59 } 60 WordsCheck.wordsCheck(apiText, baseInfo); 61 }); 62 } 63 64 /** 65 * Break the obtained api information into single words. 66 * @param { string } apiText 67 * @param { BasicApiInfo } baseInfo 68 */ 69 static wordsCheck(apiText: string, baseInfo: BasicApiInfo): void { 70 const reg = /\s{2,}/g; 71 const regx = /(\/\*|\*\/|\*)|\n|\r/g; 72 let fullText: string = apiText.replace(regx, ' '); 73 punctuationMarkSet.forEach(punctuationMark => { 74 const punctuationMarkReg = new RegExp(punctuationMark, 'g'); 75 if (punctuationMarkReg.test(fullText)) { 76 fullText = fullText.replace(punctuationMarkReg, ' ').replace(reg, ' '); 77 } 78 }); 79 let apiWordsArr = fullText.split(/\s/g); 80 const errorWords: string[] = []; 81 apiWordsArr.forEach((apiWord) => { 82 const basicWords: string[] = []; 83 WordsCheck.splitComplexWords(apiWord, basicWords); 84 basicWords.forEach((basicWord) => { 85 if (!WordsCheck.checkBaseWord(basicWord.toLowerCase())) { 86 errorWords.push(basicWord); 87 const wordsCheckFormat: ErrorTagFormat = { 88 state: false, 89 errorInfo: CommonFunctions.createErrorInfo(ErrorMessage.ERROR_WORD, [apiWord, basicWord]), 90 }; 91 const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo(); 92 errorBaseInfo 93 .setErrorID(ErrorID.MISSPELL_WORDS_ID) 94 .setErrorLevel(ErrorLevel.MIDDLE) 95 .setErrorType(ErrorType.MISSPELL_WORDS) 96 .setLogType(LogType.LOG_JSDOC) 97 .setErrorInfo(wordsCheckFormat.errorInfo); 98 const apiInfoSpell: ApiCheckInfo = CommonFunctions.getErrorInfo(baseInfo, undefined, baseInfo.getFileAbsolutePath(), errorBaseInfo); 99 AddErrorLogs.addAPICheckErrorLogs(apiInfoSpell, compositiveResult, compositiveLocalResult); 100 } 101 }); 102 }); 103 } 104 105 /** 106 * Whether compound words are underlined 107 * @param { string } word 108 * @returns { boolean } 109 */ 110 static hasUnderline(word: string): boolean { 111 return /(?<!^)\_/g.test(word); 112 } 113 114 /** 115 * split complex words 116 * @param { string } complexWord 117 * @returns { string[] } 118 */ 119 static splitComplexWords(complexWord: string, basicWords: string[]): void { 120 let baseWords: string[] = []; 121 // splite underlineWord 122 if (WordsCheck.hasUnderline(complexWord)) { 123 baseWords = complexWord.split(/(?<!^)\_/g); 124 } else { 125 // splite complexWord 126 if (!/(?<!^)(?=[A-Z])/g.test(complexWord)) { 127 baseWords.push(complexWord); 128 } else { 129 baseWords = complexWord.split(/(?<!^)(?=[A-Z])/g); 130 } 131 } 132 baseWords.forEach((word) => { 133 if (/[0-9]/g.test(word)) { 134 basicWords.concat(word.split(/0-9/g)); 135 } else { 136 basicWords.push(word); 137 } 138 }); 139 } 140 141 /** 142 * check base word 143 * @param { string } word 144 * @returns { boolean } 145 */ 146 static checkBaseWord(word: string): boolean { 147 if (/^[a-z][0-9]+$/g.test(word)) { 148 return false; 149 } else if (/^[A-Za-z]+/g.test(word) && !dictionariesSet.has(word.toLowerCase())) { 150 return false; 151 } 152 return true; 153 } 154} 155