* Copyright (c) 2022-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 { AbstractVisitor } from '../../common/abstract-visitor';
import { initResourceInfo, loadBuildJson, LoaderJson, ProjectConfig, ResourceInfo } from '../../common/plugin-context';
import { collectCustomComponentScopeInfo, isCustomComponentClass } from '../utils';
import {
CustomComponentScopeInfo,
isResourceNode,
ScopeInfoCollection
} from './utils';
import { factory } from './factory';
import { isEntryWrapperClass } from '../entry-translators/utils';
import { factory as entryFactory } from '../entry-translators/factory';
import { ImportCollector } from '../../common/import-collector';
import { DeclarationCollector } from '../../common/declaration-collector';
import { PropertyCache } from '../property-translators/cache/propertyCache';
import { ComponentLifecycleCache } from '../property-translators/cache/componentLifecycleCache';
import { CustomComponentNames } from '../../common/predefines';
export class StructTransformer extends AbstractVisitor {
private scope: ScopeInfoCollection;
projectConfig: ProjectConfig | undefined;
aceBuildJson: Partial<LoaderJson>;
resourceInfo: ResourceInfo;
constructor(projectConfig: ProjectConfig | undefined, resourcePath: string | undefined) {
super();
this.projectConfig = projectConfig;
this.scope = { customComponents: [] };
this.aceBuildJson = loadBuildJson(this.projectConfig);
this.resourceInfo = initResourceInfo(this.projectConfig, this.aceBuildJson, resourcePath ?? '');
}
reset(): void {
super.reset();
this.scope = { customComponents: [] };
PropertyCache.getInstance().reset();
ComponentLifecycleCache.getInstance().reset();
ImportCollector.getInstance().reset();
DeclarationCollector.getInstance().reset();
}
enter(node: arkts.AstNode): void {
if (arkts.isClassDeclaration(node) && !!node.definition && node.definition.body.length > 0) {
const customComponentInfo = collectCustomComponentScopeInfo(node);
if (!!customComponentInfo) {
this.scope.customComponents.push(customComponentInfo);
}
}
if (arkts.isMethodDefinition(node) && this.scope.customComponents.length > 0) {
const name = node.id!.name;
const scopeInfo = this.scope.customComponents.pop()!;
scopeInfo.hasInitializeStruct ||= name === CustomComponentNames.COMPONENT_INITIALIZE_STRUCT;
scopeInfo.hasUpdateStruct ||= name === CustomComponentNames.COMPONENT_UPDATE_STRUCT;
this.scope.customComponents.push(scopeInfo);
}
}
exit(node: arkts.AstNode): void {
if (
arkts.isClassDeclaration(node) &&
this.scope.customComponents.length > 0 &&
isCustomComponentClass(node, this.scope.customComponents[this.scope.customComponents.length - 1])
) {
this.scope.customComponents.pop();
}
}
visitor(beforeChildren: arkts.AstNode): arkts.AstNode {
this.enter(beforeChildren);
const node = this.visitEachChild(beforeChildren);
if (
arkts.isClassDeclaration(node) &&
this.scope.customComponents.length > 0 &&
isCustomComponentClass(node, this.scope.customComponents[this.scope.customComponents.length - 1])
) {
const scope: CustomComponentScopeInfo = this.scope.customComponents[this.scope.customComponents.length - 1];
const newClass: arkts.ClassDeclaration = factory.tranformClassMembers(node, scope);
this.exit(beforeChildren);
return newClass;
} else if (isEntryWrapperClass(node)) {
entryFactory.addMemoToEntryWrapperClassMethods(node);
return node;
} else if (arkts.isClassDeclaration(node)) {
return factory.transformNormalClass(node);
} else if (arkts.isCallExpression(node) && isResourceNode(node)) {
return factory.transformResource(node, this.projectConfig, this.resourceInfo);
} else if (arkts.isTSInterfaceDeclaration(node)) {
return factory.tranformInterfaceMembers(node, this.externalSourceName);
}
if (arkts.isETSModule(node) && ImportCollector.getInstance().importInfos.length > 0) {
let imports = ImportCollector.getInstance().getImportStatements();
return arkts.factory.updateETSModule(node, [...imports, ...node.statements]);
}
return node;
}
}