1/* 2 * Copyright (c) 2025 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 * as arkts from '@koalaui/libarkts'; 17import { UISyntaxRule, UISyntaxRuleContext } from './ui-syntax-rule'; 18import { getIdentifierName } from '../utils'; 19 20function isInsideStructAndBuild(node: arkts.AstNode): boolean { 21 let parentNode = node.parent; 22 let isInStruct = false; 23 let isInBuild = false; 24 while (arkts.nodeType(parentNode) !== arkts.Es2pandaAstNodeType.AST_NODE_TYPE_ETS_MODULE) { 25 if (arkts.isStructDeclaration(parentNode)) { 26 isInStruct = true; 27 } 28 if (arkts.isScriptFunction(parentNode) && parentNode.id?.name === 'build') { 29 isInBuild = true; 30 } 31 parentNode = parentNode.parent; 32 } 33 return isInStruct && isInBuild; 34} 35 36function reportNoChildInButtonError(parentNode: arkts.AstNode, context: UISyntaxRuleContext): void { 37 const siblings = parentNode.getChildren(); 38 if (!Array.isArray(siblings) || siblings.length < 3) { 39 return; 40 } 41 if (arkts.isStringLiteral(siblings[1]) && arkts.isBlockStatement(siblings[2])) { 42 context.report({ 43 node: parentNode, 44 message: rule.messages.noChildInButton, 45 fix: (parentNode) => { 46 const startPosition = arkts.getStartPosition(siblings[2]); 47 const endPosition = arkts.getEndPosition(siblings[2]); 48 return { 49 range: [startPosition, endPosition], 50 code: '', 51 }; 52 }, 53 }); 54 } 55} 56 57const rule: UISyntaxRule = { 58 name: 'no-child-in-button', 59 messages: { 60 noChildInButton: `The Button component with a label parameter can not have any child.`, 61 }, 62 setup(context: UISyntaxRuleContext) { 63 return { 64 parsed: (node): void => { 65 // Check if the current node is an identifier 66 if (!arkts.isIdentifier(node)) { 67 return; 68 } 69 const componentName = getIdentifierName(node); 70 // If the current node is 'Button' 71 if (componentName !== 'Button') { 72 return; 73 } 74 if (!isInsideStructAndBuild(node)) { 75 return; 76 } 77 // Obtain the information of the parent node of the current node 78 let parentNode = node.parent; 79 if (!arkts.isCallExpression(parentNode)) { 80 return; 81 }; 82 // Gets and traverses all the children of the parent node 83 reportNoChildInButtonError(parentNode, context); 84 } 85 }; 86 }, 87}; 88 89export default rule;