* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as arkts from '@koalaui/libarkts';
import {
collectStateManagementTypeImport,
createGetter,
createSetter,
createSetter2,
findCachedMemoMetadata,
generateGetOrSetCall,
generateThisBacking,
hasDecoratorName,
removeDecorator,
findPropertyAccessModifierFlags,
InitializeValueOptions,
} from './utils';
import { CustomComponentInfo, ClassInfo } from '../utils';
import {
CustomComponentNames,
DecoratorNames,
GetSetTypes,
NodeCacheNames,
ObservedNames,
StateManagementTypes,
} from '../../common/predefines';
import { ClassScopeInfo } from '../struct-translators/utils';
import {
CustomComponentInnerClassPropertyInfo,
NormalClassMethodInfo,
NormalClassPropertyInfo,
StructMethodInfo,
StructPropertyInfo,
} from '../../collectors/ui-collectors/records';
import { factory } from './factory';
import { PropertyCache } from './cache/propertyCache';
import { annotation, backingField, expectName, flatVisitMethodWithOverloads } from '../../common/arkts-utils';
import { factory as UIFactory } from '../ui-factory';
import { CustomDialogControllerPropertyCache } from './cache/customDialogControllerPropertyCache';
import { PropertyFactoryCallTypeCache, PropertyValueCache, PropertyValueInfo } from '../memo-collect-cache';
import { AstNodeCacheValueMetadata, NodeCacheFactory } from '../../common/node-cache';
import { MetaDataCollector } from '../../common/metadata-collector';
export interface BasePropertyTranslatorOptions {
property: arkts.ClassProperty;
}
export abstract class BasePropertyTranslator {
protected stateManagementType: StateManagementTypes | undefined;
protected property: arkts.ClassProperty;
protected propertyType: arkts.TypeNode | undefined;
protected isMemoCached?: boolean;
protected isMemoShouldUpdate?: boolean;
protected makeType?: StateManagementTypes;
protected hasResetOnReuse?: boolean;
protected hasInitializeStruct?: boolean;
protected hasUpdateStruct?: boolean;
protected hasToRecord?: boolean;
protected hasField?: boolean;
protected hasGetter?: boolean;
protected hasSetter?: boolean;
protected shouldWrapPropertyType?: boolean;
protected initializeOptions?: InitializeValueOptions;
constructor(options: BasePropertyTranslatorOptions) {
this.property = options.property;
this.propertyType = options.property.typeAnnotation?.clone();
this.isMemoCached = NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).has(options.property);
this.isMemoShouldUpdate = NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).shouldUpdateByPeer(options.property.peer);
}
abstract translateMember(): arkts.AstNode[];
protected cacheTranslatedInitializer(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): void {}
protected translateWithoutInitializer(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): arkts.AstNode[] {
const nodes: arkts.AstNode[] = [];
if (this.hasField) {
nodes.push(this.field(newName, originalName, metadata));
}
if (this.hasGetter) {
nodes.push(this.getter(newName, originalName, metadata));
}
if (this.hasSetter) {
nodes.push(this.setter(newName, originalName, metadata));
}
return nodes;
}
field(newName: string, originalName?: string, metadata?: AstNodeCacheValueMetadata): arkts.ClassProperty {
const stateMgmtCallDefaultType = this.property.typeAnnotation;
const stateMgmtCallType = factory.createStateManagementFactoryGenericType(
this.property.value,
stateMgmtCallDefaultType,
this.initializeOptions
);
const field: arkts.ClassProperty = factory.createOptionalClassProperty({
name: newName,
propertyType: stateMgmtCallType,
modifiers: arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE,
stateManagementType: this.stateManagementType
});
field.startPosition = this.property.startPosition;
field.endPosition = this.property.endPosition;
if (this.isMemoCached) {
NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).collect(field, metadata);
}
return field;
}
getter(newName: string, originalName: string, metadata?: arkts.AstNodeCacheValueMetadata): arkts.MethodDefinition {
let thisValue: arkts.Expression = generateThisBacking(newName, false, true);
if (this.initializeOptions?.isRequired && !arkts.isTSNonNullExpression(thisValue)) {
thisValue = arkts.factory.createTSNonNullExpression(thisValue);
}
const thisGetCall: arkts.CallExpression = generateGetOrSetCall(thisValue, GetSetTypes.GET);
let thisGet: arkts.Expression = thisGetCall;
if (this.initializeOptions?.canDefinitelyBeNonNull) {
thisGet = arkts.factory.createTSNonNullExpression(thisGet);
}
const getter: arkts.MethodDefinition = createGetter(
originalName,
this.propertyType,
thisGet,
this.isMemoCached,
false,
metadata
);
thisGet.startPosition = this.property.startPosition;
thisGet.endPosition = this.property.endPosition;
if (this.isMemoCached) {
NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).collect(getter, metadata);
}
return getter;
}
setter(newName: string, originalName: string, metadata?: AstNodeCacheValueMetadata): arkts.MethodDefinition {
const thisValue: arkts.Expression = generateThisBacking(newName, false, true);
const thisSet: arkts.ExpressionStatement = arkts.factory.createExpressionStatement(
generateGetOrSetCall(thisValue, GetSetTypes.SET)
);
const setter: arkts.MethodDefinition = createSetter2(originalName, this.propertyType, thisSet);
thisSet.startPosition = this.property.startPosition;
thisSet.endPosition = this.property.endPosition;
if (this.isMemoCached) {
NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).collect(setter, metadata);
}
return setter;
}
initializeStruct(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): arkts.Statement | undefined {
if (!this.stateManagementType || !this.makeType) {
return undefined;
}
const initializePropertyValue = this.property.value;
const initializePropertyType = this.propertyType?.clone();
const args: arkts.Expression[] = [
arkts.factory.createStringLiteral(originalName),
factory.generateInitializeValue(
initializePropertyValue,
initializePropertyType,
originalName,
this.initializeOptions,
this.isMemoCached,
metadata
),
];
if (this.initializeOptions?.isWatched) {
factory.addWatchFunc(args, this.property);
}
collectStateManagementTypeImport(this.stateManagementType);
const stateMgmtCallDefaultType = this.propertyType?.clone();
const stateMgmtCallType = factory.createStateManagementFactoryGenericType(
initializePropertyValue,
stateMgmtCallDefaultType,
this.initializeOptions
);
const assign: arkts.AssignmentExpression = arkts.factory.createAssignmentExpression(
generateThisBacking(newName),
factory.generateStateMgmtFactoryCall(this.makeType, stateMgmtCallType, args, true, metadata),
arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION
);
if (this.isMemoShouldUpdate) {
if (!!initializePropertyValue) {
PropertyValueCache.getInstance().collect({ value: initializePropertyValue });
}
if (!!initializePropertyType) {
PropertyValueCache.getInstance().collect({ value: initializePropertyType });
}
if (!!stateMgmtCallDefaultType) {
PropertyValueCache.getInstance().collect({ value: stateMgmtCallDefaultType });
}
}
return arkts.factory.createExpressionStatement(assign);
}
updateStruct(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): arkts.Statement | undefined {
if (!this.propertyType) {
return undefined;
}
const mutableThis: arkts.Expression = generateThisBacking(newName);
const member: arkts.MemberExpression = arkts.factory.createMemberExpression(
arkts.factory.createTSNonNullExpression(mutableThis),
arkts.factory.createIdentifier(StateManagementTypes.UPDATE),
arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
false,
false
);
const propertyType = this.propertyType.clone();
const asExpression = arkts.factory.createTSAsExpression(
factory.createNonNullOrOptionalMemberExpression(
CustomComponentNames.COMPONENT_INITIALIZERS_NAME,
originalName,
false,
true
),
propertyType,
false
);
if (this.isMemoCached) {
PropertyFactoryCallTypeCache.getInstance().collect({ node: propertyType, metadata });
} else if (this.isMemoShouldUpdate) {
PropertyValueCache.getInstance().collect({ value: propertyType });
}
return factory.createIfInUpdateStruct(originalName, member, [asExpression]);
}
toRecord(originalName: string): arkts.Property {
return arkts.factory.createProperty(
arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
arkts.factory.createStringLiteral(originalName),
arkts.factory.createBinaryExpression(
arkts.factory.createMemberExpression(
arkts.factory.createIdentifier('paramsCasted'),
arkts.factory.createIdentifier(originalName),
arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
false,
false
),
arkts.ETSNewClassInstanceExpression.createETSNewClassInstanceExpression(
arkts.factory.createETSTypeReference(
arkts.factory.createETSTypeReferencePart(arkts.factory.createIdentifier('Object'))
),
[]
),
arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING
),
false,
false
);
}
resetOnReuse(
newName: string,
originalName?: string,
metadata?: arkts.AstNodeCacheValueMetadata
): arkts.ExpressionStatement {
const propertyValue = this.property.value?.clone();
const arg = !!propertyValue ? propertyValue : arkts.factory.createUndefinedLiteral();
if (this.isMemoShouldUpdate && !!propertyValue) {
const isFunctionValue = arkts.isArrowFunctionExpression(propertyValue);
PropertyValueCache.getInstance().collect({ value: propertyValue, shouldCache: this.isMemoCached && isFunctionValue, metadata });
}
return factory.createResetOnReuseStmt(newName, arg);
}
}
export interface PropertyTranslatorOptions extends BasePropertyTranslatorOptions {
structInfo: CustomComponentInfo;
}
export abstract class PropertyTranslator extends BasePropertyTranslator {
protected structInfo: CustomComponentInfo;
constructor(options: PropertyTranslatorOptions) {
super(options);
this.structInfo = options.structInfo;
}
translateMember(): arkts.AstNode[] {
const originalName: string = expectName(this.property.key);
const newName: string = backingField(originalName);
const shouldWrapPropertyType =
this.shouldWrapPropertyType || (!!this.propertyType && arkts.isETSTypeReference(this.propertyType));
const metadata = this.isMemoCached ? findCachedMemoMetadata(this.property, shouldWrapPropertyType) : undefined;
this.cacheTranslatedInitializer(newName, originalName, metadata);
const rewriteMembers = this.translateWithoutInitializer(newName, originalName, metadata);
if (this.isMemoShouldUpdate) {
PropertyValueCache.getInstance().updateAll().reset();
}
return rewriteMembers;
}
protected cacheTranslatedInitializer(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): void {
const structName: string = this.structInfo.name;
if (this.hasInitializeStruct) {
const initializeStruct = this.initializeStruct(newName, originalName, metadata);
if (initializeStruct) {
initializeStruct.startPosition = this.property.startPosition;
initializeStruct.endPosition = this.property.endPosition;
PropertyCache.getInstance().collectInitializeStruct(structName, [initializeStruct]);
PropertyCache.getInstance().setShouldMemoUpdateInitializeStruct(structName, !!this.isMemoShouldUpdate);
}
}
if (this.hasUpdateStruct) {
const updateStruct = this.updateStruct(newName, originalName, metadata);
if (updateStruct) {
PropertyCache.getInstance().collectUpdateStruct(structName, [updateStruct]);
}
}
if (this.hasToRecord && !!this.structInfo.annotations?.reusable) {
const toRecord = this.toRecord(originalName);
PropertyCache.getInstance().collectToRecord(structName, [toRecord]);
}
if (this.hasResetOnReuse) {
const resetStateVars: arkts.Statement = this.resetOnReuse(newName, originalName, metadata);
PropertyCache.getInstance().collectResetStateVars(this.structInfo.name, [resetStateVars]);
PropertyCache.getInstance().setShouldMemoUpdateResetOnReuse(structName, !!this.isMemoShouldUpdate);
}
}
}
export interface PropertyCachedTranslatorOptions extends BasePropertyTranslatorOptions {
propertyInfo: StructPropertyInfo;
}
export abstract class PropertyCachedTranslator extends BasePropertyTranslator {
protected propertyInfo: StructPropertyInfo;
constructor(options: PropertyCachedTranslatorOptions) {
super(options);
this.propertyInfo = options.propertyInfo;
this.collectCustomDialogControllerProperty();
}
collectCustomDialogControllerProperty(): void {
if (!this.propertyInfo.structInfo?.annotationInfo?.hasCustomDialog || !this.propertyInfo.structInfo?.name) {
return;
}
if (!this.propertyType) {
return;
}
CustomDialogControllerPropertyCache.getInstance().collect(
this.property,
this.propertyType,
this.propertyInfo.structInfo.name
);
}
translateMember(): arkts.AstNode[] {
if (!this.propertyInfo || !this.propertyInfo.structInfo || !this.propertyInfo.name) {
return [];
}
const originalName = this.propertyInfo.name;
const newName: string = backingField(originalName);
const shouldWrapPropertyType =
this.shouldWrapPropertyType || (!!this.propertyType && arkts.isETSTypeReference(this.propertyType));
const metadata = this.isMemoCached ? findCachedMemoMetadata(this.property, shouldWrapPropertyType) : undefined;
this.cacheTranslatedInitializer(newName, originalName, metadata);
const rewriteMembers = this.translateWithoutInitializer(newName, originalName, metadata);
if (this.isMemoShouldUpdate) {
PropertyValueCache.getInstance().updateAll().reset();
}
return rewriteMembers;
}
protected cacheTranslatedInitializer(
newName: string,
originalName: string,
metadata?: AstNodeCacheValueMetadata
): void {
if (!this.propertyInfo?.structInfo?.name) {
return;
}
const structName: string = this.propertyInfo.structInfo.name;
if (this.hasInitializeStruct) {
const initializeStruct = this.initializeStruct(newName, originalName, metadata);
if (initializeStruct) {
initializeStruct.startPosition = this.property.startPosition;
initializeStruct.endPosition = this.property.endPosition;
PropertyCache.getInstance().collectInitializeStruct(structName, [initializeStruct]);
PropertyCache.getInstance().setShouldMemoUpdateInitializeStruct(structName, !!this.isMemoShouldUpdate);
}
}
if (this.hasUpdateStruct) {
const updateStruct = this.updateStruct(newName, originalName, metadata);
if (updateStruct) {
PropertyCache.getInstance().collectUpdateStruct(structName, [updateStruct]);
}
}
if (this.hasToRecord && !!this.propertyInfo.structInfo.annotationInfo?.hasReusable) {
const toRecord = this.toRecord(originalName);
PropertyCache.getInstance().collectToRecord(structName, [toRecord]);
}
if (this.hasResetOnReuse) {
const resetStateVars: arkts.Statement = this.resetOnReuse(newName, originalName, metadata);
PropertyCache.getInstance().collectResetStateVars(structName, [resetStateVars]);
PropertyCache.getInstance().setShouldMemoUpdateResetOnReuse(structName, !!this.isMemoShouldUpdate);
}
}
}
export interface BaseMethodTranslatorOptions {
method: arkts.MethodDefinition;
}
export abstract class BaseMethodTranslator {
protected method: arkts.MethodDefinition;
protected returnType: arkts.TypeNode | undefined;
protected isDecl?: boolean;
constructor(options: BaseMethodTranslatorOptions) {
this.method = options.method;
this.returnType = this.method.function.returnTypeAnnotation?.clone();
}
abstract translateMember(): arkts.AstNode[];
}
export interface MethodTranslatorOptions extends BaseMethodTranslatorOptions {
classInfo: ClassInfo;
}
export abstract class MethodTranslator extends BaseMethodTranslator {
protected classInfo: ClassInfo;
constructor(options: MethodTranslatorOptions) {
super(options);
this.classInfo = options.classInfo;
this.isDecl = arkts.hasModifierFlag(this.method, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE);
}
}
export interface MethodCacheTranslatorOptions extends BaseMethodTranslatorOptions {
methodInfo: StructMethodInfo | NormalClassMethodInfo;
}
export abstract class MethodCacheTranslator extends BaseMethodTranslator {
protected methodInfo: StructMethodInfo | NormalClassMethodInfo;
constructor(options: MethodCacheTranslatorOptions) {
super(options);
this.methodInfo = options.methodInfo;
this.isDecl = MetaDataCollector.getInstance().isDeclaration || this.methodInfo.isDecl;
}
}
export interface BaseObservedPropertyTranslatorOptions {
property: arkts.ClassProperty;
}
export interface IBaseObservedPropertyTranslator {
traceDecorator?: DecoratorNames.TRACE | DecoratorNames.TRACK;
property?: arkts.ClassProperty;
propertyType?: arkts.TypeNode | undefined;
propertyModifier?: arkts.Es2pandaModifierFlags;
}
export abstract class BaseObservedPropertyTranslator implements IBaseObservedPropertyTranslator {
property: arkts.ClassProperty;
propertyType: arkts.TypeNode | undefined;
traceDecorator?: DecoratorNames.TRACE | DecoratorNames.TRACK;
propertyModifier?: arkts.Es2pandaModifierFlags;
protected hasImplement?: boolean;
protected hasBackingField?: boolean;
protected hasMetaField?: boolean;
protected hasGetterSetter?: boolean;
protected isTraced?: boolean;
protected isTracked?: boolean;
protected isStatic?: boolean;
protected isDecl?: boolean;
constructor(options: BaseObservedPropertyTranslatorOptions) {
this.property = options.property;
this.propertyType = options.property.typeAnnotation;
}
abstract translateMember(): arkts.AstNode[];
* @ignore-declaration cannot enter in declaration mode
*/
backingField(originalName: string, newName: string): arkts.ClassProperty {
const backingField = arkts.factory.createClassProperty(
arkts.factory.createIdentifier(newName),
this.property.value,
this.propertyType,
this.isStatic
? arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC
: findPropertyAccessModifierFlags(this.property),
false
);
if (!this.property.value) {
backingField.modifierFlags |= arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_OPTIONAL;
}
const annotations: arkts.AnnotationUsage[] = [...this.property.annotations];
if (
!hasDecoratorName(this.property, DecoratorNames.JSONSTRINGIFYIGNORE) &&
!hasDecoratorName(this.property, DecoratorNames.JSONRENAME)
) {
annotations.push(
annotation(DecoratorNames.JSONRENAME).addProperty(
arkts.factory.createClassProperty(
arkts.factory.createIdentifier(ObservedNames.NEW_NAME),
arkts.factory.createStringLiteral(originalName),
undefined,
arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE,
false
)
)
);
}
backingField.setAnnotations(annotations);
removeDecorator(backingField, this.traceDecorator!);
if (!this.isTracked && !this.isStatic) {
return backingField;
}
backingField.startPosition = this.property.startPosition;
backingField.endPosition = this.property.endPosition;
return backingField;
}
* @ignore-declaration connot enter in declaration mode
*/
metaField(originalName: string, newName: string): arkts.ClassProperty {
collectStateManagementTypeImport(StateManagementTypes.MUTABLE_STATE_META);
const metaName = this.isTracked
? `${StateManagementTypes.META}_${originalName}`
: `${StateManagementTypes.META}V2_${originalName}`;
const args = this.isStatic
? [arkts.factory.createUndefinedLiteral(), arkts.factory.createStringLiteral(metaName)]
: [arkts.factory.createStringLiteral(metaName)];
return arkts.factory.createClassProperty(
arkts.factory.createIdentifier(`${StateManagementTypes.META}_${originalName}`),
factory.generateStateMgmtFactoryCall(
StateManagementTypes.MAKE_MUTABLESTATE_META,
undefined,
args,
!this.isStatic
),
UIFactory.createTypeReferenceFromString(StateManagementTypes.MUTABLE_STATE_META),
this.isStatic
? arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC
: arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE,
false
);
}
abstract getter(originalName: string, newName: string): arkts.MethodDefinition;
abstract setter(originalName: string, newName: string): arkts.MethodDefinition;
}
export interface ObservedPropertyTranslatorOptions extends BaseObservedPropertyTranslatorOptions {
classScopeInfo: ClassScopeInfo;
}
export abstract class ObservedPropertyTranslator extends BaseObservedPropertyTranslator {
protected classScopeInfo: ClassScopeInfo;
constructor(options: ObservedPropertyTranslatorOptions) {
super(options);
this.classScopeInfo = options.classScopeInfo;
this.hasImplement = arkts.hasModifierFlag(this.property, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_SETTER);
this.isDecl = MetaDataCollector.getInstance().isDeclaration ||
arkts.hasModifierFlag(this.property, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE);
}
translateMember(): arkts.AstNode[] {
const originalName: string = expectName(this.property.key);
const newName: string = backingField(originalName);
const fields: arkts.AstNode[] = [];
if (this.hasBackingField) {
fields.push(this.backingField(originalName, newName));
}
if (this.hasMetaField && !this.isDecl) {
fields.push(this.metaField(originalName, newName));
}
if (this.hasGetterSetter) {
this.cacheGetterSetter(originalName, newName);
}
return fields;
}
protected cacheGetterSetter(originalName: string, newName: string): void {
const newGetter = this.getter(originalName, newName);
const newSetter = this.setter(originalName, newName);
if (this.hasImplement) {
{
const idx: number = this.classScopeInfo.getters.findIndex(
(getter) => getter.id!.name === originalName
);
const originGetter: arkts.MethodDefinition = this.classScopeInfo.getters[idx];
const originSetter: arkts.MethodDefinition = originGetter.overloads[0];
const updateGetter: arkts.MethodDefinition = arkts.factory.updateMethodDefinition(
originGetter,
originGetter.kind,
newGetter.key,
arkts.factory.createFunctionExpression(
originGetter.id?.clone(),
newGetter.function.addFlag(arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_METHOD),
),
originGetter.modifierFlags,
false
);
arkts.factory.updateMethodDefinition(
originSetter,
originSetter.kind,
newSetter.key,
arkts.factory.createFunctionExpression(
originSetter.id?.clone(),
newSetter.function
.addFlag(arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_OVERLOAD)
.addFlag(arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_METHOD),
),
originSetter.modifierFlags,
false
);
this.classScopeInfo.getters[idx] = updateGetter;
}
} else {
this.classScopeInfo.getters.push(...[newGetter, newSetter]);
}
}
}
export interface ObservedPropertyCachedTranslatorOptions extends BaseObservedPropertyTranslatorOptions {
propertyInfo: NormalClassPropertyInfo;
}
export abstract class ObservedPropertyCachedTranslator extends BaseObservedPropertyTranslator {
protected propertyInfo: NormalClassPropertyInfo;
constructor(options: ObservedPropertyCachedTranslatorOptions) {
super(options);
this.propertyInfo = options.propertyInfo;
if (!!this.propertyInfo.modifiers) {
this.hasImplement = (this.propertyInfo.modifiers & arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_SETTER) === arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_SETTER;
}
}
translateMember(): arkts.AstNode[] {
if (!this.propertyInfo) {
return [this.property];
}
const fields: arkts.AstNode[] = [];
const name: string = this.propertyInfo.name!;
const originalName: string = name;
const newName: string = backingField(originalName);
if (this.hasBackingField) {
fields.push(this.backingField(originalName, newName));
}
if (this.hasMetaField && !this.isDecl) {
fields.push(this.metaField(originalName, newName));
}
if (!this.hasImplement) {
fields.push(this.getter(originalName, newName), this.setter(originalName, newName));
}
return fields;
}
}
export type InnerClassPropertyTypes = arkts.MethodDefinition | arkts.ClassProperty;
export interface InnerClassPropertyTranslatorOptions<T extends InnerClassPropertyTypes> {
property: T;
}
export abstract class InnerClassPropertyTranslator<T extends InnerClassPropertyTypes = InnerClassPropertyTypes>
implements InnerClassPropertyTranslatorOptions<T>
{
protected decorator: DecoratorNames | undefined;
property: T;
modified: boolean;
constructor(options: InnerClassPropertyTranslatorOptions<T>) {
this.property = options.property;
this.modified = false;
}
translateProperty(): T {
if (arkts.isMethodDefinition(this.property)) {
this.modified = true;
const method = flatVisitMethodWithOverloads(
this.property,
this.updateStateMethodInInnerClass.bind(this)
) as T;
return method;
} else if (arkts.isClassProperty(this.property)) {
this.modified = true;
return this.updateStatePropertyInInnerClass(this.property) as T;
}
return this.property;
}
* Wrap getter's return type and setter's param type (expecting an union type with `T` and `undefined`)
* to `StateManagementType<T> | undefined`.
*
* @param method expecting getter with decorator.
*/
protected updateStateMethodInInnerClass(method: arkts.MethodDefinition): arkts.MethodDefinition {
if (!this.decorator) {
throw new Error('interface property does not have any decorator.');
}
const metadata = findCachedMemoMetadata(method);
return factory.wrapStateManagementTypeToMethodInInnerClass(method, this.decorator, metadata);
}
* Wrap to the type of the property (expecting an union type with `T` and `undefined`)
* to `StateManagementType<T> | undefined`.
*
* @param property expecting property with decorator.
*/
protected updateStatePropertyInInnerClass(property: arkts.ClassProperty): arkts.ClassProperty {
if (!this.decorator) {
throw new Error('interface property does not have any decorator.');
}
return factory.wrapStateManagementTypeToPropertyInInnerClass(property, this.decorator);
}
static canBeTranslated(node: arkts.AstNode): node is InnerClassPropertyTypes {
return false;
}
}
export interface InnerClassPropertyCachedTranslatorOptions<T extends InnerClassPropertyTypes>
extends InnerClassPropertyTranslatorOptions<T> {
propertyInfo?: CustomComponentInnerClassPropertyInfo;
}
export abstract class InnerClassPropertyCachedTranslator<T extends InnerClassPropertyTypes = InnerClassPropertyTypes>
extends InnerClassPropertyTranslator<T>
implements InnerClassPropertyCachedTranslatorOptions<T>
{
propertyInfo?: CustomComponentInnerClassPropertyInfo;
constructor(options: InnerClassPropertyCachedTranslatorOptions<T>) {
super(options);
this.propertyInfo = options.propertyInfo;
}
static canBeTranslated(
node: arkts.AstNode,
metadata?: CustomComponentInnerClassPropertyInfo
): node is InnerClassPropertyTypes {
return false;
}
}