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 if (node.name.escapedText) { 48 return node.name.escapedText.toString(); 49 } else if (node.name.text) { 50 return node.name.text.toString(); 51 } 52 return; 53} 54 55function isConstantDecorator(node, name) { 56 return hasAPINote(node) && getApiInfo(node).isConstant && !checkAllUppercaseHump(name); 57} 58 59function filterApiVersion(node, version) { 60 const apiVersion = getApiVersion(node); 61 return apiVersion === version; 62} 63 64function checkAPINameOfHump(node, sourcefile, fileName) { 65 let checkResult = ''; 66 const apiInfo = getApiInfo(node); 67 if (ts.isEnumMember(node) || (ts.isVariableDeclaration(node) && !(fileName.indexOf('component\\ets\\') >= 0 || 68 fileName.indexOf('component/ets/') >= 0))) { 69 const name = getName(node); 70 if (!checkAllUppercaseHump(name)) { 71 checkResult = `This name [${name}] should be named by all uppercase.`; 72 } 73 } else if (ts.isInterfaceDeclaration(node) || ts.isClassDeclaration(node) || ts.isTypeAliasDeclaration(node) || 74 ts.isEnumDeclaration(node)) { 75 const name = getName(node); 76 if (isConstantDecorator(node, name)) { 77 checkResult = `This name [${name}] should be named by all uppercase.`; 78 } else if (!apiInfo.isConstant && !checkLargeHump(name)) { 79 checkResult = `This name [${name}] should be named by large hump.`; 80 } 81 } else if (ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isMethodDeclaration(node) || 82 ts.isFunctionDeclaration(node) || ts.isParameter(node) || ts.isModuleDeclaration(node)) { 83 const name = getName(node); 84 if (isConstantDecorator(node, name)) { 85 checkResult = `This name [${name}] should be named by all uppercase.`; 86 } else if (!apiInfo.isConstant && !checkSmallHump(name)) { 87 checkResult = `This name [${name}] should be named by small hump.`; 88 } 89 } 90 91 if (checkResult !== '' && filterApiVersion(node, getCheckApiVersion()) && (!apiInfo.deprecated || apiInfo.deprecated === '')) { 92 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.NAMING_ERRORS, checkResult, LogType.LOG_API, 93 ErrorLevel.MIDDLE); 94 } 95} 96exports.checkAPINameOfHump = checkAPINameOfHump; 97 98function checkAPIFileName(sourcefile, fileName) { 99 if (fileName.indexOf('component\\ets\\') < 0 && fileName.indexOf('component/ets/') < 0) { 100 let moduleName = ''; 101 let exportAssignment = ''; 102 sourcefile.statements.forEach(statement => { 103 if (ts.isModuleDeclaration(statement) && statement.name && ts.isIdentifier(statement.name)) { 104 moduleName = statement.name.escapedText.toString(); 105 } 106 if (ts.isExportAssignment(statement) && statement.expression && ts.isIdentifier(statement.expression)) { 107 exportAssignment = statement.expression.escapedText.toString(); 108 } 109 }); 110 const basename = path.basename(fileName).replace(/\.d\.ts$/, ''); 111 const lastModuleName = basename.split('.').pop(); 112 let checkResult = ''; 113 114 if (moduleName !== '' && exportAssignment === moduleName && !checkSmallHump(lastModuleName)) { 115 checkResult = 'This API file should be named by small hump.'; 116 } else if (moduleName === '' && exportAssignment !== moduleName && !checkLargeHump(lastModuleName)) { 117 checkResult = 'This API file should be named by large hump.'; 118 } 119 if (checkResult !== '' && filterApiVersion(sourcefile, getCheckApiVersion())) { 120 addAPICheckErrorLogs(sourcefile, sourcefile, fileName, ErrorType.NAMING_ERRORS, checkResult, LogType.LOG_FILE, 121 ErrorLevel.MIDDLE); 122 } 123 } 124} 125exports.checkAPIFileName = checkAPIFileName; 126