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 { getAnnotationUsage, PresetDecorators } from '../utils'; 18import { UISyntaxRule, UISyntaxRuleContext } from './ui-syntax-rule'; 19 20const MAX_PREVIEW_DECORATOR_COUNT = 10; 21 22function checkDuplicatePreview(node: arkts.AstNode, context: UISyntaxRuleContext): void { 23 if (arkts.nodeType(node) !== arkts.Es2pandaAstNodeType.AST_NODE_TYPE_ETS_MODULE) { 24 return; 25 } 26 let previewDecoratorUsages: arkts.AnnotationUsage[] = []; 27 node.getChildren().forEach((child) => { 28 if (!arkts.isStructDeclaration(child)) { 29 return; 30 } 31 const previewDecoratorUsage = getAnnotationUsage( 32 child, 33 PresetDecorators.PREVIEW, 34 ); 35 if (previewDecoratorUsage) { 36 previewDecoratorUsages.push(previewDecoratorUsage); 37 } 38 }); 39 // If the number of preview decorators is greater than 10, an error is reported 40 if (previewDecoratorUsages.length <= MAX_PREVIEW_DECORATOR_COUNT) { 41 return; 42 } 43 previewDecoratorUsages.forEach((previewDecoratorUsage) => { 44 context.report({ 45 node: previewDecoratorUsage, 46 message: rule.messages.duplicateEntry, 47 fix: (previewDecoratorUsage) => { 48 const startPosition = arkts.getStartPosition(previewDecoratorUsage); 49 const endPosition = arkts.getEndPosition(previewDecoratorUsage); 50 return { 51 range: [startPosition, endPosition], 52 code: '', 53 }; 54 } 55 }); 56 }); 57} 58 59const rule: UISyntaxRule = { 60 name: 'no-duplicate-preview', 61 messages: { 62 duplicateEntry: `An ArkTS file con contain at most 10 '@Preview' decorators.`, 63 }, 64 setup(context) { 65 return { 66 parsed: (node): void => { 67 checkDuplicatePreview(node, context); 68 }, 69 }; 70 }, 71}; 72 73export default rule;