* Copyright (c) 2026 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 { DecoratorNames } from '../../common/predefines';
import {
BaseMethodTranslator,
MethodCacheTranslator,
MethodCacheTranslatorOptions,
MethodTranslator,
MethodTranslatorOptions
} from './base';
import { hasDecorator } from './utils';
import {
ComponentLifecycleCache,
LifecycleMethodType,
LifecycleMethodInfo
} from './cache/componentLifecycleCache';
import { ActiveInactiveCache } from './cache/activeInactiveCache';
import { StructMethodInfo } from '../../collectors/ui-collectors/records';
* Maps lifecycle decorators to their corresponding lifecycle method types.
*/
const LIFECYCLE_DECORATOR_TYPE = new Map<DecoratorNames, LifecycleMethodType>([
[DecoratorNames.COMPONENT_INIT, LifecycleMethodType.ABOUT_TO_APPEAR],
[DecoratorNames.COMPONENT_APPEAR, LifecycleMethodType.ABOUT_TO_APPEAR],
[DecoratorNames.COMPONENT_BUILT, LifecycleMethodType.ON_DID_BUILD],
[DecoratorNames.COMPONENT_DISAPPEAR, LifecycleMethodType.ABOUT_TO_DISAPPEAR],
[DecoratorNames.COMPONENT_REUSE, LifecycleMethodType.ABOUT_TO_REUSE],
[DecoratorNames.COMPONENT_RECYCLE, LifecycleMethodType.ABOUT_TO_RECYCLE],
]);
function collectLifecycleMethods(
this: BaseMethodTranslator,
structName: string,
methodName: string,
matchedDecorators: Map<DecoratorNames, LifecycleMethodType>
): void {
if (matchedDecorators.has(DecoratorNames.COMPONENT_INIT)) {
ComponentLifecycleCache.getInstance().collectInitMethod(structName, methodName);
}
if (hasDecorator(this.method, DecoratorNames.COMPONENT_ACTIVE)) {
ActiveInactiveCache.getInstance().collectActiveMethod(structName, methodName);
}
if (hasDecorator(this.method, DecoratorNames.COMPONENT_INACTIVE)) {
ActiveInactiveCache.getInstance().collectInactiveMethod(structName, methodName);
}
for (const [decorator, lifecycleType] of matchedDecorators) {
if (decorator !== DecoratorNames.COMPONENT_INIT && methodName !== lifecycleType) {
collectLifecycleMethod.bind(this)(structName, methodName, lifecycleType);
}
}
}
function collectLifecycleMethod(
this: BaseMethodTranslator,
structName: string,
methodName: string,
lifecycleType: LifecycleMethodType
): void {
const params = this.method.function.params as arkts.ETSParameterExpression[];
const hasReuseParam =
lifecycleType === LifecycleMethodType.ABOUT_TO_REUSE && params.length > 0;
const methodInfo: LifecycleMethodInfo = {
methodName,
methodType: lifecycleType,
hasReuseParam,
reuseParams: hasReuseParam ? params : undefined,
};
ComponentLifecycleCache.getInstance().collectLifecycleMethod(structName, methodInfo);
}
* @deprecated
*/
export class ComponentLifecycleTranslator extends MethodTranslator {
constructor(options: MethodTranslatorOptions) {
super(options);
}
translateMember(): arkts.AstNode[] {
if (this.isDecl) {
return [this.method];
}
const methodName: string = this.method.id!.name;
if (this.classInfo.isFromStruct) {
const structName: string = this.classInfo.className;
const matchedDecorators = this.findMatchingLifecycleDecorators();
collectLifecycleMethods.bind(this)(structName, methodName, matchedDecorators);
}
return [this.method];
}
protected findMatchingLifecycleDecorators(): Map<DecoratorNames, LifecycleMethodType> {
const matched = new Map<DecoratorNames, LifecycleMethodType>();
for (const [decorator, lifecycleType] of LIFECYCLE_DECORATOR_TYPE) {
if (hasDecorator(this.method, decorator)) {
matched.set(decorator, lifecycleType);
}
}
return matched;
}
}
export interface ComponentLifecycleCacheTranslatorOptions extends MethodCacheTranslatorOptions {
methodInfo: StructMethodInfo
}
export class ComponentLifecycleCacheTranslator extends MethodCacheTranslator {
protected methodInfo: StructMethodInfo = {};
constructor(options: ComponentLifecycleCacheTranslatorOptions) {
super(options);
this.methodInfo = options.methodInfo;
}
translateMember(): arkts.AstNode[] {
if (this.isDecl) {
return [this.method];
}
const methodName: string | undefined = this.methodInfo.name;
if (methodName !== undefined && !!this.methodInfo.structInfo?.name) {
const structName: string = this.methodInfo.structInfo.name;
const matchedDecorators = this.findMatchingLifecycleDecorators(this.methodInfo);
collectLifecycleMethods.bind(this)(structName, methodName, matchedDecorators);
}
return [this.method];
}
protected findMatchingLifecycleDecorators(
methodInfo: StructMethodInfo
): Map<DecoratorNames, LifecycleMethodType> {
const matched = new Map<DecoratorNames, LifecycleMethodType>();
if (methodInfo.annotationInfo === undefined) {
return matched;
}
for (const [decorator, lifecycleType] of LIFECYCLE_DECORATOR_TYPE) {
if (methodInfo.annotationInfo[`has${decorator}`]) {
matched.set(decorator, lifecycleType);
}
}
return matched;
}
}