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 { AbstractVisitor } from '../common/abstract-visitor'; 19import { ARKUI_DECLARE_LIST } from './arkuiImportList'; 20import { debugLog } from '../common/debug'; 21 22export class DeclTransformer extends AbstractVisitor { 23 constructor(private options?: interop.DeclTransformerOptions) { 24 super(); 25 } 26 27 processComponent(node: arkts.StructDeclaration): arkts.ClassDeclaration { 28 const className = node.definition?.ident?.name; 29 if (!className) { 30 throw 'Non Empty className expected for Component'; 31 } 32 33 let newDec: arkts.ClassDeclaration = arkts.factory.createClassDeclaration(node.definition); 34 35 const newDefinition = arkts.factory.updateClassDefinition( 36 newDec.definition!, 37 newDec.definition?.ident, 38 undefined, 39 undefined, 40 newDec.definition?.implements!, 41 undefined, 42 undefined, 43 node.definition?.body, 44 newDec.definition?.modifiers!, 45 arkts.classDefinitionFlags(newDec.definition!) | arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE 46 ); 47 48 arkts.factory.updateClassDeclaration(newDec, newDefinition); 49 newDec.modifiers = node.modifiers; 50 return newDec; 51 } 52 53 visitor(beforeChildren: arkts.AstNode): arkts.AstNode { 54 let astNode: arkts.AstNode = beforeChildren; 55 if (arkts.isEtsScript(astNode)) { 56 astNode = this.transformImportDecl(astNode); 57 } 58 const node = this.visitEachChild(astNode); 59 if (arkts.isStructDeclaration(node)) { 60 debugLog(`DeclTransformer:before:flag:${arkts.classDefinitionIsFromStructConst(node.definition!)}`); 61 arkts.classDefinitionSetFromStructModifier(node.definition!); 62 let newnode = this.processComponent(node); 63 debugLog(`DeclTransformer:after:flag:${arkts.classDefinitionIsFromStructConst(newnode.definition!)}`); 64 return newnode; 65 } else if (arkts.isETSImportDeclaration(astNode)) { 66 return this.updateImportDeclaration(astNode); 67 } else if (arkts.isMethodDefinition(astNode)) { 68 if (astNode.name?.name === 'build' ) { 69 return this.transformMethodDefinition(astNode); 70 } 71 return astNode; 72 } 73 return node; 74 } 75 76 transformImportDecl(astNode: arkts.AstNode):arkts.AstNode { 77 if (!arkts.isEtsScript(astNode)) { 78 return astNode; 79 } 80 let statements = astNode.statements.filter(node => this.isImportDeclarationNeedFilter(node)); 81 return arkts.factory.updateEtsScript(astNode, statements); 82 } 83 84 transformMethodDefinition(node: arkts.MethodDefinition): arkts.AstNode { 85 const func: arkts.ScriptFunction = node.scriptFunction; 86 const isFunctionCall: boolean = false; 87 const typeNode: arkts.TypeNode | undefined = node.scriptFunction?.returnTypeAnnotation; 88 const updateFunc = arkts.factory.updateScriptFunction( 89 func, 90 !!func.body && arkts.isBlockStatement(func.body) 91 ? arkts.factory.updateBlock( 92 func.body, 93 func.body.statements.filter((st) => false) 94 ) 95 : undefined, 96 arkts.FunctionSignature.createFunctionSignature(func.typeParams, func.params, func.returnTypeAnnotation, false), 97 func?.flags, 98 func?.modifiers 99 ); 100 101 return arkts.factory.updateMethodDefinition( 102 node, 103 node.kind, 104 arkts.factory.updateIdentifier( 105 node.name, 106 node.name?.name 107 ), 108 updateFunc, 109 node.modifiers, 110 false 111 ); 112 } 113 114 isImportDeclarationNeedFilter(astNode: arkts.AstNode):boolean { 115 if (!arkts.isETSImportDeclaration(astNode)) { 116 return true; 117 } 118 return astNode?.source?.str !== '@global.arkui'; 119 } 120 121 updateImportDeclaration(astNode: arkts.AstNode):arkts.AstNode { 122 if (!arkts.isETSImportDeclaration(astNode) || astNode?.source?.str !== '@ohos.arkui.component') { 123 return astNode; 124 } 125 astNode.specifiers.forEach((element) => { 126 if (arkts.isImportSpecifier(element)) { 127 if (ARKUI_DECLARE_LIST.has(element.imported?.name as string)) { 128 arkts.ImportSpecifierSetRemovable(element); 129 } 130 } 131 }); 132 return astNode; 133 } 134} 135