• 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    generateGetOrSetCall,
23    generateThisBacking,
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 PropTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter {
33    translateMember(): arkts.AstNode[] {
34        const originalName: string = expectName(this.property.key);
35        const newName: string = backingField(originalName);
36
37        this.cacheTranslatedInitializer(newName, originalName); // TODO: need to release cache after some point...
38        return this.translateWithoutInitializer(newName, originalName);
39    }
40
41    cacheTranslatedInitializer(newName: string, originalName: string): void {
42        const currentStructInfo: arkts.StructInfo = arkts.GlobalInfo.getInfoInstance().getStructInfo(this.structName);
43        const mutableThis: arkts.Expression = generateThisBacking(newName);
44        const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName);
45        const updateStruct: arkts.AstNode = this.generateUpdateStruct(mutableThis, originalName);
46        currentStructInfo.initializeBody.push(initializeStruct);
47        currentStructInfo.updateBody.push(updateStruct);
48        if (currentStructInfo.isReusable) {
49            const toRecord = generateToRecord(newName, originalName);
50            currentStructInfo.toRecordBody.push(toRecord);
51        }
52        arkts.GlobalInfo.getInfoInstance().setStructInfo(this.structName, currentStructInfo);
53    }
54
55    translateWithoutInitializer(newName: string, originalName: string): arkts.AstNode[] {
56        const field: arkts.ClassProperty = createOptionalClassProperty(
57            newName,
58            this.property,
59            'PropDecoratedVariable',
60            arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE
61        );
62        const thisValue: arkts.Expression = generateThisBacking(newName, false, true);
63        const thisGet: arkts.CallExpression = generateGetOrSetCall(thisValue, 'get');
64        const thisSet: arkts.ExpressionStatement = arkts.factory.createExpressionStatement(
65            generateGetOrSetCall(thisValue, 'set')
66        );
67        const getter: arkts.MethodDefinition = this.translateGetter(
68            originalName,
69            this.property.typeAnnotation,
70            thisGet
71        );
72        const setter: arkts.MethodDefinition = this.translateSetter(
73            originalName,
74            this.property.typeAnnotation,
75            thisSet
76        );
77
78        return [field, getter, setter];
79    }
80
81    translateGetter(
82        originalName: string,
83        typeAnnotation: arkts.TypeNode | undefined,
84        returnValue: arkts.Expression
85    ): arkts.MethodDefinition {
86        return createGetter(originalName, typeAnnotation, returnValue);
87    }
88
89    translateSetter(
90        originalName: string,
91        typeAnnotation: arkts.TypeNode | undefined,
92        statement: arkts.AstNode
93    ): arkts.MethodDefinition {
94        return createSetter2(originalName, typeAnnotation, statement);
95    }
96
97    generateInitializeStruct(newName: string, originalName: string): arkts.AstNode {
98        const binaryItem = arkts.factory.createBinaryExpression(
99            factory.createBlockStatementForOptionalExpression(
100                arkts.factory.createIdentifier('initializers'),
101                originalName
102            ),
103            this.property.value ?? arkts.factory.createUndefinedLiteral(),
104            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING
105        );
106        const args: arkts.Expression[] = [
107            arkts.factory.create1StringLiteral(originalName),
108            this.property.value
109                ? binaryItem
110                : arkts.factory.createTSAsExpression(
111                      factory.createNonNullOrOptionalMemberExpression('initializers', originalName, false, true),
112                      this.property.typeAnnotation ? this.property.typeAnnotation.clone() : undefined,
113                      false
114                  ),
115        ];
116        judgeIfAddWatchFunc(args, this.property);
117        const right = arkts.factory.createETSNewClassInstanceExpression(
118            arkts.factory.createTypeReference(
119                arkts.factory.createTypeReferencePart(
120                    arkts.factory.createIdentifier('PropDecoratedVariable'),
121                    arkts.factory.createTSTypeParameterInstantiation(
122                        this.property.typeAnnotation ? [this.property.typeAnnotation] : []
123                    )
124                )
125            ),
126            args
127        );
128        const assign: arkts.AssignmentExpression = arkts.factory.createAssignmentExpression(
129            generateThisBacking(newName),
130            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION,
131            right
132        );
133        return arkts.factory.createExpressionStatement(assign);
134    }
135
136    generateUpdateStruct(mutableThis: arkts.Expression, originalName: string): arkts.AstNode {
137        const binaryItem = arkts.factory.createBinaryExpression(
138            factory.createBlockStatementForOptionalExpression(
139                arkts.factory.createIdentifier('initializers'),
140                originalName
141            ),
142            arkts.factory.createUndefinedLiteral(),
143            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NOT_STRICT_EQUAL
144        );
145        const member: arkts.MemberExpression = arkts.factory.createMemberExpression(
146            arkts.factory.createTSNonNullExpression(mutableThis),
147            arkts.factory.createIdentifier('update'),
148            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
149            false,
150            false
151        );
152        return arkts.factory.createIfStatement(
153            binaryItem,
154            arkts.factory.createBlock([
155                arkts.factory.createExpressionStatement(
156                    arkts.factory.createCallExpression(member, undefined, [
157                        arkts.factory.createTSAsExpression(
158                            factory.createNonNullOrOptionalMemberExpression('initializers', originalName, false, true),
159                            this.property.typeAnnotation ? this.property.typeAnnotation.clone() : undefined,
160                            false
161                        ),
162                    ])
163                ),
164            ])
165        );
166    }
167}
168