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