1/* 2 * Copyright (c) 2021-2022 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 */ 15const path = require('path'); 16const { 17 ErrorType, 18 ErrorLevel, 19 FileType, 20 getApiVersion, 21 getCheckApiVersion, 22 requireTypescriptModule 23} = require('./utils'); 24const { addAPICheckErrorLogs, getParentkind } = require('./compile_info'); 25const ts = requireTypescriptModule(); 26const nameDictionary = require('./name_dictionary.json'); 27const nameScenarioScope = require('./name_scenario_scope.json'); 28 29function checkNaming(node, sourcefile, fileName) { 30 const apiVersionToBeVerified = getCheckApiVersion(); 31 const apiVersion = Number(getApiVersion(node)); 32 33 if (apiVersionToBeVerified.indexOf('^') === 0) { 34 const minCheckApiVersion = Number(apiVersionToBeVerified.substr(1)); 35 checkApiVerion(minCheckApiVersion); 36 if (apiVersion > minCheckApiVersion) { 37 checkApiNaming(node, sourcefile, fileName); 38 } 39 } else if (apiVersion === Number(apiVersionToBeVerified)) { 40 checkApiNaming(node, sourcefile, fileName); 41 } else { 42 checkApiVerion(apiVersionToBeVerified); 43 } 44} 45exports.checkNaming = checkNaming; 46 47function checkApiNaming(node, sourcefile, fileName) { 48 const lowIdentifier = node.getText().toLowerCase(); 49 const apiParentKind = []; 50 getParentkind(node, apiParentKind); 51 if (node.parent.kind === ts.SyntaxKind.TypeReference || apiParentKind.includes('JSDoc')) { 52 return; 53 } 54 checkApiNamingWords(node, sourcefile, fileName, lowIdentifier); 55 checkApiNamingScenario(node, sourcefile, fileName, lowIdentifier); 56} 57 58function checkApiNamingWords(node, sourcefile, fileName, lowIdentifier) { 59 const lowercaseNamingMap = getlowercaseNamingMap(); 60 for (const [key, value] of lowercaseNamingMap) { 61 const prohibitedWordIndex = lowIdentifier.indexOf(key); 62 if (prohibitedWordIndex === -1) { 63 continue; 64 } 65 const lowercaseIgnoreWordArr = value.ignore.map(word => word.toLowerCase()); 66 const internalWord = node.getText().substr(prohibitedWordIndex, key.length); 67 const errorInfo = `Prohibited word in [${node.getText()}]:{${internalWord}}.The word allowed is [${value.suggestion}]`; 68 if (lowercaseIgnoreWordArr.length === 0) { 69 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.NAMING_ERRORS, errorInfo, FileType.LOG_API, 70 ErrorLevel.MIDDLE 71 ); 72 break; 73 } else { 74 const isIgnoreWord = checkIgnoreWord(lowercaseIgnoreWordArr, lowIdentifier, value.badWord); 75 if (isIgnoreWord === false) { 76 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.NAMING_ERRORS, errorInfo, FileType.LOG_API, 77 ErrorLevel.MIDDLE 78 ); 79 } 80 } 81 } 82} 83 84function checkIgnoreWord(lowercaseIgnoreWordArr, lowIdentifier, badWord) { 85 let isIgnoreWord = false; 86 const isNamingFoot = lowIdentifier.substring(lowIdentifier.length - badWord.length, lowIdentifier.length) === badWord; 87 for (let i = 0; i < lowercaseIgnoreWordArr.length; i++) { 88 if (lowercaseIgnoreWordArr[i] && lowIdentifier.indexOf(lowercaseIgnoreWordArr[i]) !== -1) { 89 isIgnoreWord = true; 90 break; 91 } 92 } 93 if (!isNamingFoot) { 94 isIgnoreWord = true; 95 } 96 return isIgnoreWord; 97} 98 99function checkApiVerion(apiVersion) { 100 if (isNaN(parseInt(apiVersion))) { 101 throw 'Please configure the correct API version to be verified'; 102 } 103} 104 105function checkApiNamingScenario(node, sourcefile, fileName, lowIdentifier) { 106 const lowercaseNamingScenarioMap = getlowercaseNamingScenarioMap(); 107 for (const [key, value] of lowercaseNamingScenarioMap) { 108 const prohibitedWordIndex = lowIdentifier.indexOf(key); 109 if ( 110 prohibitedWordIndex !== -1 && 111 !isInAllowedFiles(value.files, path.basename(fileName)) 112 ) { 113 const internalWord = node.getText().substr(prohibitedWordIndex, key.length); 114 const errorInfo = `Prohibited word in [${node.getText()}]:{${internalWord}} in the [${path.basename(fileName)}] file`; 115 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.NAMING_ERRORS, errorInfo, FileType.LOG_API, 116 ErrorLevel.MIDDLE 117 ); 118 } 119 } 120} 121 122function getlowercaseNamingMap() { 123 const lowercaseNamingMap = new Map(); 124 for (const item of nameDictionary) { 125 const key = item.badWord.toLowerCase(); 126 const { badWord, suggestion, ignore } = item; 127 lowercaseNamingMap.set(key, { badWord, suggestion, ignore }); 128 } 129 return lowercaseNamingMap; 130} 131 132function getlowercaseNamingScenarioMap() { 133 const lowercaseNamingScenarioMap = new Map(); 134 for (const item of nameScenarioScope) { 135 const key = item.word.toLowerCase(); 136 const { word, files } = item; 137 lowercaseNamingScenarioMap.set(key, { word, files }); 138 } 139 return lowercaseNamingScenarioMap; 140} 141 142function isInAllowedFiles(files, fileName) { 143 for (const item of files) { 144 const pattern = new RegExp(item); 145 pattern.test(fileName); 146 if (pattern.test(fileName)) { 147 return true; 148 } 149 } 150 return false; 151} 152