From f6dc406b3300a1b0ee10ad1bab95160bc5d08eae Mon Sep 17 00:00:00 2001 From: Yuxin Feng Date: Tue, 2 Sep 2025 22:35:07 +0800 Subject: [PATCH] transform interop 1.1->1.2 builder Signed-off-by: Yuxin Feng Change-Id: I5361bfa8d6adf9d1771171946cec285a8d42c852 --- .../interop-plugins/arkuiImportList.ts | 1 + .../interop-plugins/decl_transformer.ts | 25 +++++++++++++++++++ compiler/src/interop/src/component_map.ts | 3 +++ .../interop/src/process_component_build.ts | 19 ++++++++++++-- compiler/src/interop/src/process_import.ts | 18 +++++++++++-- 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/arkui-plugins/interop-plugins/arkuiImportList.ts b/arkui-plugins/interop-plugins/arkuiImportList.ts index ddc19b2bd..417d788de 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 32d6a610e..09a450e45 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 3527b3e6d..158a0d5cd 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 037efb0b8..6c93c416e 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 8ca3073c3..7d73a9b2f 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); + } +} -- Gitee