• 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';
17
18import {
19    generateToRecord,
20    createGetter,
21    createSetter2,
22    generateThisBacking,
23    generateGetOrSetCall,
24    judgeIfAddWatchFunc,
25} from './utils';
26import { PropertyTranslator } from './base';
27import { GetterSetter, InitializerConstructor } from './types';
28import { backingField, expectName } from '../../common/arkts-utils';
29import { createOptionalClassProperty } from '../utils';
30import { factory } from './factory';
31
32export class StateTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter {
33    translateMember(): arkts.AstNode[] {
34        const originalName: string = expectName(this.property.key);
35        const newName: string = backingField(originalName);
36        this.cacheTranslatedInitializer(newName, originalName); // TODO: need to release cache after some point...
37        return this.translateWithoutInitializer(newName, originalName);
38    }
39
40    cacheTranslatedInitializer(newName: string, originalName: string): void {
41        const currentStructInfo: arkts.StructInfo = arkts.GlobalInfo.getInfoInstance().getStructInfo(this.structName);
42        const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName);
43        currentStructInfo.initializeBody.push(initializeStruct);
44        if (currentStructInfo.isReusable) {
45            const toRecord = generateToRecord(newName, originalName);
46            currentStructInfo.toRecordBody.push(toRecord);
47        }
48        arkts.GlobalInfo.getInfoInstance().setStructInfo(this.structName, currentStructInfo);
49    }
50
51    translateWithoutInitializer(newName: string, originalName: string): arkts.AstNode[] {
52        const field: arkts.ClassProperty = createOptionalClassProperty(
53            newName,
54            this.property,
55            'StateDecoratedVariable',
56            arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE
57        );
58        const thisValue: arkts.Expression = generateThisBacking(newName, false, true);
59        const thisGet: arkts.CallExpression = generateGetOrSetCall(thisValue, 'get');
60        const thisSet: arkts.ExpressionStatement = arkts.factory.createExpressionStatement(
61            generateGetOrSetCall(thisValue, 'set')
62        );
63        const getter: arkts.MethodDefinition = this.translateGetter(
64            originalName,
65            this.property.typeAnnotation,
66            thisGet
67        );
68        const setter: arkts.MethodDefinition = this.translateSetter(
69            originalName,
70            this.property.typeAnnotation,
71            thisSet
72        );
73
74        return [field, getter, setter];
75    }
76
77    translateGetter(
78        originalName: string,
79        typeAnnotation: arkts.TypeNode | undefined,
80        returnValue: arkts.Expression
81    ): arkts.MethodDefinition {
82        return createGetter(originalName, typeAnnotation, returnValue);
83    }
84
85    translateSetter(
86        originalName: string,
87        typeAnnotation: arkts.TypeNode | undefined,
88        statement: arkts.AstNode
89    ): arkts.MethodDefinition {
90        return createSetter2(originalName, typeAnnotation, statement);
91    }
92
93    generateInitializeStruct(newName: string, originalName: string): arkts.AstNode {
94        const binaryItem = arkts.factory.createBinaryExpression(
95            factory.createBlockStatementForOptionalExpression(
96                arkts.factory.createIdentifier('initializers'),
97                originalName
98            ),
99            this.property.value ?? arkts.factory.createUndefinedLiteral(),
100            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING
101        );
102        const args: arkts.Expression[] = [arkts.factory.create1StringLiteral(originalName), binaryItem];
103        judgeIfAddWatchFunc(args, this.property);
104        const right = arkts.factory.createETSNewClassInstanceExpression(
105            arkts.factory.createTypeReference(
106                arkts.factory.createTypeReferencePart(
107                    arkts.factory.createIdentifier('StateDecoratedVariable'),
108                    arkts.factory.createTSTypeParameterInstantiation(
109                        this.property.typeAnnotation ? [this.property.typeAnnotation] : []
110                    )
111                )
112            ),
113            args
114        );
115        const assign: arkts.AssignmentExpression = arkts.factory.createAssignmentExpression(
116            generateThisBacking(newName),
117            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION,
118            right
119        );
120        return arkts.factory.createExpressionStatement(assign);
121    }
122}
123