• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 } from './ui-syntax-rule';
19
20const rule: UISyntaxRule = {
21  name: 'struct-missing-decorator',
22  messages: {
23    missingComponentDecorator: `struct '{{structName}}' is missing '@Component' or '@CustomDialog' decorators`,
24    misusedPreview: `struct '{{structName}}' misused '@Preview' decorator. it should be decorated by '@Component' or '@CustomDialog'`,
25    misusedObserved: `struct '{{structName}}' misused '@Observed' decorator. it should be decorated by '@Component' or '@CustomDialog'`,
26  },
27  setup(context) {
28    function hasDecorator(node: arkts.StructDeclaration, decorator: string): boolean {
29      return !!getAnnotationUsage(node, decorator);
30    }
31
32    return {
33      parsed: (node): void => {
34        if (!arkts.isStructDeclaration(node)) {
35          return;
36        }
37        // Check for the presence of specific decorators on the struct
38        const structName = node.definition.ident?.name ?? '';
39        const structNode = node.definition.ident;
40        const hasComponent = hasDecorator(node, PresetDecorators.COMPONENT_V1);
41        const hasComponentV2 = hasDecorator(node, PresetDecorators.COMPONENT_V2);
42        const hasCustomDialog = hasDecorator(node, PresetDecorators.CUSTOM_DIALOG);
43        const hasPreview = getAnnotationUsage(node, PresetDecorators.PREVIEW);
44        const hasObserved = getAnnotationUsage(node, PresetDecorators.OBSERVED_V1);
45        // If no valid component decorators (@Component or @CustomDialog) are found
46        if (!hasComponent && !hasComponentV2 && !hasCustomDialog && structNode) {
47          context.report({
48            node: structNode,
49            message: rule.messages.missingComponentDecorator,
50            data: { structName },
51          });
52        }
53        // If the @Preview decorator is used but the struct is not decorated with @Component or @CustomDialog
54        if (hasPreview && !hasComponent && !hasComponentV2 && !hasCustomDialog && structNode) {
55          context.report({
56            node: structNode,
57            message: rule.messages.misusedPreview,
58            data: { structName },
59          });
60        }
61        // If the @Observed decorator is used but the struct is not decorated with @Component or @CustomDialog
62        if (hasObserved && !hasComponent && !hasComponentV2 && !hasCustomDialog && structNode) {
63          context.report({
64            node: structNode,
65            message: rule.messages.misusedObserved,
66            data: { structName },
67          });
68        }
69      },
70    };
71  },
72};
73
74export default rule;
75