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 */ 15 16const path = require('path'); 17const { ErrorLevel, LogType, hasAPINote, getApiInfo, requireTypescriptModule, ErrorType, getApiVersion, getCheckApiVersion } = require('./utils'); 18const { addAPICheckErrorLogs } = require('./compile_info'); 19const ts = requireTypescriptModule(); 20 21/** 22 * 大驼峰 23 * class、interface、枚举名 24 * 小驼峰 25 * 变量名、方法名、参数名、namespace 26 * 全大写 27 * 常量命名、枚举值 28 */ 29 30// 大驼峰检查 31function checkLargeHump(word) { 32 return /^([A-Z][a-z0-9]*)*$/g.test(word); 33} 34 35// 小驼峰检查 36function checkSmallHump(word) { 37 return /^[a-z]+[0-9]*([A-Z][a-z0-9]*)*$/g.test(word); 38} 39exports.checkSmallHump = checkSmallHump; 40 41// 全大写检查 42function checkAllUppercaseHump(word) { 43 return /^[A-Z]+[0-9]*([\_][A-Z0-9]+)*$/g.test(word); 44} 45 46function getName(node) { 47 let str = ''; 48 if (node.name.escapedText) { 49 str = node.name.escapedText.toString(); 50 } else if (node.name.text) { 51 str = node.name.text.toString(); 52 } 53 return str; 54} 55 56function isConstantDecorator(node, name) { 57 return hasAPINote(node) && getApiInfo(node).isConstant && !checkAllUppercaseHump(name); 58} 59 60function filterApiVersion(node, version) { 61 const apiVersion = getApiVersion(node); 62 return apiVersion === version; 63} 64 65function checkAPINameOfHump(node, sourcefile, fileName) { 66 let checkResult = ''; 67 const apiInfo = getApiInfo(node); 68 if (ts.isEnumMember(node) || (ts.isVariableDeclaration(node) && !(fileName.indexOf('component\\ets\\') >= 0 || 69 fileName.indexOf('component/ets/') >= 0))) { 70 const name = getName(node); 71 if (!checkAllUppercaseHump(name)) { 72 checkResult = `This name [${name}] should be named by all uppercase.`; 73 } 74 } else if (ts.isInterfaceDeclaration(node) || ts.isClassDeclaration(node) || ts.isTypeAliasDeclaration(node) || 75 ts.isEnumDeclaration(node)) { 76 const name = getName(node); 77 if (isConstantDecorator(node, name)) { 78 checkResult = `This name [${name}] should be named by all uppercase.`; 79 } else if (!apiInfo.isConstant && !checkLargeHump(name)) { 80 checkResult = `This name [${name}] should be named by large hump.`; 81 } 82 } else if (ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isMethodDeclaration(node) || 83 ts.isFunctionDeclaration(node) || ts.isParameter(node) || ts.isModuleDeclaration(node)) { 84 const name = getName(node); 85 if (isConstantDecorator(node, name)) { 86 checkResult = `This name [${name}] should be named by all uppercase.`; 87 } else if (!apiInfo.isConstant && !checkSmallHump(name)) { 88 checkResult = `This name [${name}] should be named by small hump.`; 89 } 90 } 91 92 if (checkResult !== '' && filterApiVersion(node, getCheckApiVersion()) && (!apiInfo.deprecated || apiInfo.deprecated === '')) { 93 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.NAMING_ERRORS, checkResult, LogType.LOG_API, 94 ErrorLevel.MIDDLE); 95 } 96} 97exports.checkAPINameOfHump = checkAPINameOfHump; 98 99function checkAPIFileName(sourcefile, fileName) { 100 if (fileName.indexOf('component\\ets\\') < 0 && fileName.indexOf('component/ets/') < 0) { 101 let moduleName = ''; 102 let exportAssignment = ''; 103 sourcefile.statements.forEach(statement => { 104 if (ts.isModuleDeclaration(statement) && statement.name && ts.isIdentifier(statement.name)) { 105 moduleName = statement.name.escapedText.toString(); 106 } 107 if (ts.isExportAssignment(statement) && statement.expression && ts.isIdentifier(statement.expression)) { 108 exportAssignment = statement.expression.escapedText.toString(); 109 } 110 }); 111 const basename = path.basename(fileName).replace(/\.d\.ts$/, ''); 112 const lastModuleName = basename.split('.').pop(); 113 let checkResult = ''; 114 115 if (moduleName !== '' && exportAssignment === moduleName && !checkSmallHump(lastModuleName)) { 116 checkResult = 'This API file should be named by small hump.'; 117 } else if (moduleName === '' && exportAssignment !== moduleName && !checkLargeHump(lastModuleName)) { 118 checkResult = 'This API file should be named by large hump.'; 119 } 120 if (checkResult !== '' && filterApiVersion(sourcefile, getCheckApiVersion())) { 121 addAPICheckErrorLogs(sourcefile, sourcefile, fileName, ErrorType.NAMING_ERRORS, checkResult, LogType.LOG_FILE, 122 ErrorLevel.MIDDLE); 123 } 124 } 125} 126exports.checkAPIFileName = checkAPIFileName; 127