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 { backingField, expectName } from '../../common/arkts-utils'; 19import { PropertyTranslator } from './base'; 20import { GetterSetter, InitializerConstructor } from './types'; 21import { DecoratorNames, generateToRecord } from './utils'; 22 23function getLocalStorageLinkValueStr(node: arkts.AstNode): string | undefined { 24 if (!arkts.isClassProperty(node) || !node.value) return undefined; 25 return arkts.isStringLiteral(node.value) ? node.value.str : undefined; 26} 27 28function getLocalStorageLinkAnnotationValue(anno: arkts.AnnotationUsage): string | undefined { 29 const isStorageLinkAnnotation: boolean = 30 !!anno.expr && arkts.isIdentifier(anno.expr) && anno.expr.name === DecoratorNames.LOCAL_STORAGE_LINK; 31 32 if (isStorageLinkAnnotation && anno.properties.length === 1) { 33 return getLocalStorageLinkValueStr(anno.properties.at(0)!); 34 } 35 return undefined; 36} 37 38function getLocalStorageLinkValueInAnnotation(node: arkts.ClassProperty): string | undefined { 39 const annotations: readonly arkts.AnnotationUsage[] = node.annotations; 40 41 for (let i = 0; i < annotations.length; i++) { 42 const anno: arkts.AnnotationUsage = annotations[i]; 43 const str: string | undefined = getLocalStorageLinkAnnotationValue(anno); 44 if (!!str) { 45 return str; 46 } 47 } 48 49 return undefined; 50} 51 52export class LocalStorageLinkTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { 53 translateMember(): arkts.AstNode[] { 54 const originalName: string = expectName(this.property.key); 55 const newName: string = backingField(originalName); 56 57 this.cacheTranslatedInitializer(newName, originalName); // TODO: need to release cache after some point... 58 return this.translateWithoutInitializer(newName, originalName); 59 } 60 61 cacheTranslatedInitializer(newName: string, originalName: string): void { 62 const currentStructInfo: arkts.StructInfo = arkts.GlobalInfo.getInfoInstance().getStructInfo(this.structName); 63 const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName); 64 currentStructInfo.initializeBody.push(initializeStruct); 65 66 if (currentStructInfo.isReusable) { 67 const toRecord = generateToRecord(newName, originalName); 68 currentStructInfo.toRecordBody.push(toRecord); 69 } 70 71 arkts.GlobalInfo.getInfoInstance().setStructInfo(this.structName, currentStructInfo); 72 } 73 74 generateInitializeStruct(newName: string, originalName: string): arkts.AstNode { 75 const localStorageLinkValueStr: string | undefined = getLocalStorageLinkValueInAnnotation(this.property); 76 if (!localStorageLinkValueStr) { 77 throw new Error('LocalStorageLink required only one value!!'); // TODO: replace this with proper error message. 78 } 79 80 const call = arkts.factory.createCallExpression( 81 arkts.factory.createIdentifier('StorageLinkState'), 82 this.property.typeAnnotation ? [this.property.typeAnnotation] : [], 83 [ 84 arkts.factory.createMemberExpression( 85 arkts.factory.createThisExpression(), 86 arkts.factory.createIdentifier('_entry_local_storage_'), 87 arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, 88 false, 89 false 90 ), 91 arkts.factory.createStringLiteral(localStorageLinkValueStr), 92 this.property.value ?? arkts.factory.createUndefinedLiteral(), 93 ] 94 ); 95 96 return arkts.factory.createAssignmentExpression( 97 arkts.factory.createMemberExpression( 98 arkts.factory.createThisExpression(), 99 arkts.factory.createIdentifier(newName), 100 arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, 101 false, 102 false 103 ), 104 arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION, 105 call 106 ); 107 } 108} 109