diff --git a/arkui-plugins/interop-plugins/arkuiImportList.ts b/arkui-plugins/interop-plugins/arkuiImportList.ts index ddc19b2bd98bf3d005f43c654945be7fbc640c2f..417d788de15b9ae2b029b9368e30a771de2a8566 100644 --- a/arkui-plugins/interop-plugins/arkuiImportList.ts +++ b/arkui-plugins/interop-plugins/arkuiImportList.ts @@ -169,6 +169,7 @@ export const ARKUI_DECLARE_LIST: Set = new Set([ 'Reusable', 'Computed', 'Builder', + 'WrappedBuilder', 'LocalBuilder', 'Styles', 'Extend', diff --git a/arkui-plugins/interop-plugins/decl_transformer.ts b/arkui-plugins/interop-plugins/decl_transformer.ts index 32d6a610ed38b6c00179a12eb7fe035cec5f6988..09a450e452043cf4c9aff28510d77d83367fdcd2 100644 --- a/arkui-plugins/interop-plugins/decl_transformer.ts +++ b/arkui-plugins/interop-plugins/decl_transformer.ts @@ -71,6 +71,8 @@ export class DeclTransformer extends AbstractVisitor { return astNode; } else if (arkts.isClassProperty(astNode)) { astNode.setAnnotations([]); + } else if (arkts.isVariableDeclarator(astNode)) { + return this.transformWrappedBuilderVarDecl(astNode); } return node; } @@ -133,4 +135,27 @@ export class DeclTransformer extends AbstractVisitor { }); return astNode; } + + transformWrappedBuilderVarDecl(node: arkts.VariableDeclarator): arkts.VariableDeclarator { + const typeAnn = node?.name?.typeAnnotation; + if (!typeAnn || !arkts.isETSTypeReference(typeAnn)) return node; + const part = typeAnn.part; + if (!part?.name || !arkts.isIdentifier(part?.name) || part?.name.name !== 'WrappedBuilder') return node; + const fnType = part.typeParams?.params?.[0]; + if (!fnType || !arkts.isETSFunctionType(fnType)) return node; + const types: arkts.TypeNode[] = []; + for (const p of fnType.params) { + if (!arkts.isEtsParameterExpression(p) || !p.type || !arkts.isTypeNode(p.type)) { + return node; + } + types.push(p.type); + } + const tuple = arkts.ETSTuple.create2ETSTuple(types); + + const newTypeParams = arkts.factory.updateTSTypeParameterInstantiation(part.typeParams, [tuple]); + const newPart = arkts.factory.updateTypeReferencePart(part, part.name, newTypeParams, part.previous); + const newTypeRef = arkts.factory.updateTypeReference(typeAnn, newPart); + const newId = arkts.factory.updateIdentifier(node.name, node.name.name, newTypeRef); + return arkts.factory.updateVariableDeclarator(node, node.flag, newId, node.initializer); + } } diff --git a/compiler/src/interop/src/component_map.ts b/compiler/src/interop/src/component_map.ts index 3527b3e6df65aaabca5362831d3d361e9bf30ceb..158a0d5cda1b1a44c0f9f0ae42d0a0494f17609e 100644 --- a/compiler/src/interop/src/component_map.ts +++ b/compiler/src/interop/src/component_map.ts @@ -134,6 +134,9 @@ export const INTERFACE_NODE_SET: Set = new Set(); export const INNER_CUSTOM_BUILDER_METHOD: Set = new Set(); export const GLOBAL_CUSTOM_BUILDER_METHOD: Set = new Set(); +export const STATIC_WRAPPED_BUILDER: Set = new Set(); +export const STATIC_BUILDER: Set = new Set(); + export const JS_BIND_COMPONENTS: Set = new Set([ 'ForEach', 'LazyForEach', ...GESTURE_TYPE_NAMES, 'Gesture', 'PanGestureOption', 'CustomDialogController', 'Storage', 'Scroller', 'SwiperController', diff --git a/compiler/src/interop/src/process_component_build.ts b/compiler/src/interop/src/process_component_build.ts index 037efb0b8bacb4900450d2a806c195ec7691fe8a..6c93c416e2f9158150f926b8787acacc139d9546 100644 --- a/compiler/src/interop/src/process_component_build.ts +++ b/compiler/src/interop/src/process_component_build.ts @@ -161,7 +161,9 @@ import { STYLES_ATTRIBUTE, INNER_CUSTOM_LOCALBUILDER_METHOD, COMMON_ATTRS, - EXT_WHITE_LIST + EXT_WHITE_LIST, + STATIC_WRAPPED_BUILDER, + STATIC_BUILDER } from './component_map'; import { componentCollection, @@ -657,7 +659,11 @@ function builderCallNode(node: ts.CallExpression): ts.Expression { } else { newNode = ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( - node.expression, + isStaticBuilder(node) ? ts.factory.createCallExpression( + ts.factory.createIdentifier('transferCompatibleBuilder'), + undefined, + [node.expression] + ) : node.expression, ts.factory.createIdentifier(BUILDER_ATTR_BIND) ), undefined, @@ -667,6 +673,15 @@ function builderCallNode(node: ts.CallExpression): ts.Expression { return newNode; } +function isStaticBuilder(node: ts.CallExpression): boolean { + if (ts.isIdentifier(node.expression)) { + return STATIC_BUILDER.has(node.expression.escapedText.toString()); + } else if (node.expression && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression)) { + return STATIC_WRAPPED_BUILDER.has(node.expression.expression.escapedText.toString()); + } + return false; +} + function traverseBuilderParams(node: ts.ObjectLiteralExpression, isBuilder: boolean): ts.ObjectLiteralExpression { const properties: ts.ObjectLiteralElementLike[] = []; diff --git a/compiler/src/interop/src/process_import.ts b/compiler/src/interop/src/process_import.ts index 8ca3073c3a7d8118f3354f16524e75efa63cb733..7d73a9b2f2540bb33930e5c8200077648387fc67 100644 --- a/compiler/src/interop/src/process_import.ts +++ b/compiler/src/interop/src/process_import.ts @@ -28,7 +28,8 @@ import { COMPONENT_DECORATOR_ENTRY, COMPONENT_BUILDER_DECORATOR, DECORATOR_REUSEABLE, - DECORATOR_REUSABLE_V2 + DECORATOR_REUSABLE_V2, + WRAPPEDBUILDER_CLASS } from './pre_define'; import { propertyCollection, @@ -79,7 +80,9 @@ import { import { CUSTOM_BUILDER_METHOD, INNER_COMPONENT_NAMES, - GLOBAL_CUSTOM_BUILDER_METHOD + GLOBAL_CUSTOM_BUILDER_METHOD, + STATIC_WRAPPED_BUILDER, + STATIC_BUILDER } from './component_map'; import { type ResolveModuleInfo, @@ -887,8 +890,13 @@ function processImportNode(originNode: ts.Node, usedNode: ts.Identifier, importI } else if (ts.isFunctionDeclaration(originNode) && hasDecorator(originNode, COMPONENT_BUILDER_DECORATOR)) { CUSTOM_BUILDER_METHOD.add(name); GLOBAL_CUSTOM_BUILDER_METHOD.add(name); + if (isArkoala) { + STATIC_BUILDER.add(name); + } } else if (ts.isEnumDeclaration(originNode) && originNode.name) { enumCollection.add(name); + } else if (ts.isVariableDeclaration(originNode)) { + processStaticBuild(isArkoala, originNode.type, name); } else { needCollection = false; } @@ -1005,3 +1013,9 @@ function isReusableV2(node: ts.StructDeclaration): boolean { return name === DECORATOR_REUSABLE_V2; }); } + +function processStaticBuild(isArkoala: boolean, type: ts.TypeNode | undefined, name: string): void { + if (isArkoala && type && ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName) && type.typeName.escapedText === WRAPPEDBUILDER_CLASS) { + STATIC_WRAPPED_BUILDER.add(name); + } +}