• 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 { factory } from './factory';
30import { createOptionalClassProperty } from '../utils';
31
32export class LinkTranslator 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 initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName);
44        currentStructInfo.initializeBody.push(initializeStruct);
45        if (currentStructInfo.isReusable) {
46            const toRecord = generateToRecord(newName, originalName);
47            currentStructInfo.toRecordBody.push(toRecord);
48        }
49        arkts.GlobalInfo.getInfoInstance().setStructInfo(this.structName, currentStructInfo);
50    }
51
52    generateInitializeStruct(newName: string, originalName: string) {
53        const test = factory.createBlockStatementForOptionalExpression(
54            arkts.factory.createIdentifier('initializers'),
55            newName
56        );
57
58        const args: arkts.Expression[] = [
59            arkts.factory.create1StringLiteral(originalName),
60            arkts.factory.createTSNonNullExpression(
61                factory.createNonNullOrOptionalMemberExpression('initializers', newName, false, true)
62            ),
63        ];
64        judgeIfAddWatchFunc(args, this.property);
65        const consequent = arkts.BlockStatement.createBlockStatement([
66            arkts.factory.createExpressionStatement(
67                arkts.factory.createAssignmentExpression(
68                    generateThisBacking(newName, false, false),
69                    arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION,
70                    factory.createNewDecoratedInstantiate('LinkDecoratedVariable', this.property.typeAnnotation, args)
71                )
72            ),
73        ]);
74
75        return arkts.factory.createExpressionStatement(arkts.factory.createIfStatement(test, consequent));
76    }
77
78    translateWithoutInitializer(newName: string, originalName: string): arkts.AstNode[] {
79        const field: arkts.ClassProperty = createOptionalClassProperty(
80            newName,
81            this.property,
82            'LinkDecoratedVariable',
83            arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE
84        );
85        const thisValue: arkts.Expression = generateThisBacking(newName, false, true);
86        const thisGet: arkts.CallExpression = generateGetOrSetCall(thisValue, 'get');
87        const thisSet: arkts.ExpressionStatement = arkts.factory.createExpressionStatement(
88            generateGetOrSetCall(thisValue, 'set')
89        );
90        const getter: arkts.MethodDefinition = this.translateGetter(
91            originalName,
92            this.property.typeAnnotation,
93            thisGet
94        );
95        const setter: arkts.MethodDefinition = this.translateSetter(
96            originalName,
97            this.property.typeAnnotation,
98            thisSet
99        );
100
101        return [field, getter, setter];
102    }
103
104    translateGetter(
105        originalName: string,
106        typeAnnotation: arkts.TypeNode | undefined,
107        returnValue: arkts.Expression
108    ): arkts.MethodDefinition {
109        return createGetter(originalName, typeAnnotation, returnValue);
110    }
111
112    translateSetter(
113        originalName: string,
114        typeAnnotation: arkts.TypeNode | undefined,
115        statement: arkts.AstNode
116    ): arkts.MethodDefinition {
117        return createSetter2(originalName, typeAnnotation, statement);
118    }
119}
120