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