From 3964f37e30abbd2abde0df18534053c319337f9e Mon Sep 17 00:00:00 2001 From: houhaoyu Date: Sat, 9 Jul 2022 20:51:04 +0800 Subject: [PATCH 1/2] houhaoyu@huawei.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复多级自定义组件传递@Builder this绑定错误 Signed-off-by: houhaoyu Change-Id: I4d0b12c80fba96991a849e2f346078de5fa73e0f --- compiler/src/process_component_build.ts | 29 ++++++++++++++++++++---- compiler/src/process_component_class.ts | 14 ++++++++++-- compiler/src/process_custom_component.ts | 16 ++++++------- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/compiler/src/process_component_build.ts b/compiler/src/process_component_build.ts index 91738cf..76686d1 100644 --- a/compiler/src/process_component_build.ts +++ b/compiler/src/process_component_build.ts @@ -94,6 +94,7 @@ import { import { projectConfig } from '../main'; import { transformLog, contextGlobal } from './process_ui_syntax'; import { props } from './compile_info'; +import { INNER_CUSTOM_BUILDER_METHOD } from './process_component_class'; export function processComponentBuild(node: ts.MethodDeclaration, log: LogInfo[]): ts.MethodDeclaration { @@ -113,9 +114,9 @@ export function processComponentBuild(node: ts.MethodDeclaration, } export function processComponentBlock(node: ts.Block, isLazy: boolean, log: LogInfo[], - isTransition: boolean = false): ts.Block { + isTransition: boolean = false, isInnerBuilder: boolean = false): ts.Block { const newStatements: ts.Statement[] = []; - processComponentChild(node, newStatements, log); + processComponentChild(node, newStatements, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder); if (isLazy) { newStatements.unshift(createRenderingInProgress(true)); } @@ -221,7 +222,7 @@ function validateEtsComponentNode(node: ts.CallExpression | ts.EtsComponentExpre let sourceNode: ts.SourceFile; export function processComponentChild(node: ts.Block | ts.SourceFile, newStatements: ts.Statement[], log: LogInfo[], - supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}): void { + supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder: boolean = false): void { if (supplement.isAcceleratePreview) { newsupplement = supplement; const compilerOptions = ts.readConfigFile( @@ -253,7 +254,7 @@ export function processComponentChild(node: ts.Block | ts.SourceFile, newStateme item = expressionResult; } } - processCustomComponent(item as ts.ExpressionStatement, newStatements, log, name); + processCustomComponent(item as ts.ExpressionStatement, newStatements, log, name, isInnerBuilder); lastName = name; lastExpression = item; } @@ -264,8 +265,16 @@ export function processComponentChild(node: ts.Block | ts.SourceFile, newStateme lastExpression = item; break; case ComponentType.customBuilderMethod: + if (INNER_CUSTOM_BUILDER_METHOD.has(name)) { + newStatements.push(addInnerBuilderParameter(item)); + } else { + newStatements.push(item); + } + lastName = name; + lastExpression = item; + break; case ComponentType.builderParamMethod: - newStatements.push(item); + newStatements.push(addInnerBuilderParameter(item)); lastName = name; lastExpression = item; break; @@ -299,6 +308,16 @@ export function processComponentChild(node: ts.Block | ts.SourceFile, newStateme }; } +function addInnerBuilderParameter(node: ts.ExpressionStatement): ts.ExpressionStatement { + if (node.expression && ts.isCallExpression(node.expression) && node.expression.arguments) { + node.expression.arguments.push(ts.factory.createThis()); + return ts.factory.createExpressionStatement(ts.factory.updateCallExpression(node.expression, + node.expression.expression, node.expression.typeArguments, node.expression.arguments)); + } else { + return node; + } +} + function processMixBuilder(lastName: string, name: string, index: number, lastExpression: ts.Statement, log: LogInfo[], newStatements: ts.Statement[], item: ts.Statement, type: ComponentType): void { let isMixExtend: boolean; diff --git a/compiler/src/process_component_class.ts b/compiler/src/process_component_class.ts index f1b6087..5993be5 100644 --- a/compiler/src/process_component_class.ts +++ b/compiler/src/process_component_class.ts @@ -276,7 +276,7 @@ function createLocalStroageCallExpression(node: ts.PropertyDeclaration, name: st ] ); } - +export const INNER_CUSTOM_BUILDER_METHOD: Set = new Set(); function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: ts.Identifier, context: ts.TransformationContext, log: LogInfo[], buildCount: BuildCount): ts.MethodDeclaration { let updateItem: ts.MethodDeclaration = node; @@ -300,9 +300,19 @@ function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: node.type, processComponentBlock(node.body, false, log, true)); } else if (hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) { CUSTOM_BUILDER_METHOD.add(name); + INNER_CUSTOM_BUILDER_METHOD.add(name) + node.parameters.push(ts.factory.createParameterDeclaration( + undefined, + undefined, + undefined, + ts.factory.createIdentifier("parent"), + undefined, + undefined, + undefined + )) const builderNode: ts.MethodDeclaration = ts.factory.updateMethodDeclaration(node, undefined, node.modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, - node.type, processComponentBlock(node.body, false, log)); + node.type, processComponentBlock(node.body, false, log, false, true)); updateItem = processBuildMember(builderNode, context, log); } else if (hasDecorator(node, COMPONENT_STYLES_DECORATOR)) { if (node.parameters && node.parameters.length === 0) { diff --git a/compiler/src/process_custom_component.ts b/compiler/src/process_custom_component.ts index 40d05ee..a77771c 100644 --- a/compiler/src/process_custom_component.ts +++ b/compiler/src/process_custom_component.ts @@ -75,7 +75,7 @@ const decoractorMap: Map>> = new Map( [COMPONENT_OBJECT_LINK_DECORATOR, objectLinkCollection]]); export function processCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Statement[], - log: LogInfo[], name: string): void { + log: LogInfo[], name: string, isInnerBuilder: boolean = false): void { const componentNode: ts.CallExpression = getCustomComponentNode(node); if (componentNode) { const hasChainCall: boolean = componentNode.parent && @@ -109,7 +109,7 @@ export function processCustomComponent(node: ts.ExpressionStatement, newStatemen ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), null))); bindComponentAttr(node, ts.factory.createIdentifier(COMPONENT_COMMON), newStatements, log); } - addCustomComponent(node, newStatements, customComponentNewExpression, log, name, componentNode); + addCustomComponent(node, newStatements, customComponentNewExpression, log, name, componentNode, isInnerBuilder); if (hasChainCall) { newStatements.push(ts.factory.createExpressionStatement( createFunction(ts.factory.createIdentifier(COMPONENT_COMMON), @@ -140,18 +140,18 @@ function changeNodeFromCallToArrow(node: ts.CallExpression): ts.ArrowFunction { } function addCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Statement[], - newNode: ts.NewExpression, log: LogInfo[], name: string, componentNode: ts.CallExpression): void { + newNode: ts.NewExpression, log: LogInfo[], name: string, componentNode: ts.CallExpression, isInnerBuilder: boolean = false): void { if (ts.isNewExpression(newNode)) { const propertyArray: ts.ObjectLiteralElementLike[] = []; validateCustomComponentPrams(componentNode, name, propertyArray, log); - addCustomComponentStatements(node, newStatements, newNode, name, propertyArray); + addCustomComponentStatements(node, newStatements, newNode, name, propertyArray, isInnerBuilder); } } function addCustomComponentStatements(node: ts.ExpressionStatement, newStatements: ts.Statement[], - newNode: ts.NewExpression, name: string, props: ts.ObjectLiteralElementLike[]): void { + newNode: ts.NewExpression, name: string, props: ts.ObjectLiteralElementLike[], isInnerBuilder: boolean = false): void { const id: string = componentInfo.id.toString(); - newStatements.push(createFindChildById(id, name), createCustomComponentIfStatement(id, + newStatements.push(createFindChildById(id, name, isInnerBuilder), createCustomComponentIfStatement(id, ts.factory.updateExpressionStatement(node, createViewCreate(newNode)), ts.factory.createObjectLiteralExpression(props, true), name)); } @@ -355,12 +355,12 @@ function getPropertyDecoratorKind(propertyName: string, customComponentName: str } } -function createFindChildById(id: string, name: string): ts.VariableStatement { +function createFindChildById(id: string, name: string, isInnerBuilder: boolean = false): ts.VariableStatement { return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( [ts.factory.createVariableDeclaration(ts.factory.createIdentifier( `${CUSTOM_COMPONENT_EARLIER_CREATE_CHILD}${id}`), undefined, ts.factory.createTypeReferenceNode( ts.factory.createIdentifier(name)), ts.factory.createAsExpression(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier( + ts.factory.createPropertyAccessExpression(isInnerBuilder ? ts.factory.createIdentifier('parent') : ts.factory.createThis(), ts.factory.createIdentifier( `${CUSTOM_COMPONENT_FUNCTION_FIND_CHILD_BY_ID}`)), undefined, [ts.factory.createStringLiteral(id)]), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(name))))], ts.NodeFlags.Let)); } From af2ce8d080daa9f419fcb446014cf35c87090a30 Mon Sep 17 00:00:00 2001 From: houhaoyu Date: Tue, 19 Jul 2022 15:46:41 +0800 Subject: [PATCH 2/2] houhaoyu@huawei.com Signed-off-by: houhaoyu Change-Id: I6458c63b6d5b5b10fee1383862d66a776653cebb --- compiler/src/component_map.ts | 2 ++ compiler/src/process_component_build.ts | 12 +++++++----- compiler/src/process_component_class.ts | 25 ++++++++++-------------- compiler/src/process_component_member.ts | 11 +++++++++-- compiler/src/process_custom_component.ts | 21 +++++++++++++++----- 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/compiler/src/component_map.ts b/compiler/src/component_map.ts index fe9f600..1ec4f56 100644 --- a/compiler/src/component_map.ts +++ b/compiler/src/component_map.ts @@ -80,6 +80,8 @@ export const STYLES_ATTRIBUTE: Set = new Set(); export const INTERFACE_NODE_SET: Set = new Set(); +export const INNER_CUSTOM_BUILDER_METHOD: 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/process_component_build.ts b/compiler/src/process_component_build.ts index 0af9a5d..3da05ce 100644 --- a/compiler/src/process_component_build.ts +++ b/compiler/src/process_component_build.ts @@ -74,7 +74,8 @@ import { INNER_STYLE_FUNCTION, GLOBAL_STYLE_FUNCTION, COMMON_ATTRS, - CUSTOM_BUILDER_PROPERTIES + CUSTOM_BUILDER_PROPERTIES, + INNER_CUSTOM_BUILDER_METHOD } from './component_map'; import { componentCollection, @@ -91,7 +92,6 @@ import { import { projectConfig } from '../main'; import { transformLog, contextGlobal } from './process_ui_syntax'; import { props } from './compile_info'; -import { INNER_CUSTOM_BUILDER_METHOD } from './process_component_class'; export function processComponentBuild(node: ts.MethodDeclaration, log: LogInfo[]): ts.MethodDeclaration { @@ -113,7 +113,8 @@ export function processComponentBuild(node: ts.MethodDeclaration, export function processComponentBlock(node: ts.Block, isLazy: boolean, log: LogInfo[], isTransition: boolean = false, isInnerBuilder: boolean = false): ts.Block { const newStatements: ts.Statement[] = []; - processComponentChild(node, newStatements, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder); + processComponentChild(node, newStatements, log, + {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder); if (isLazy) { newStatements.unshift(createRenderingInProgress(true)); } @@ -209,8 +210,9 @@ function validateEtsComponentNode(node: ts.CallExpression | ts.EtsComponentExpre let sourceNode: ts.SourceFile; -export function processComponentChild(node: ts.Block | ts.SourceFile, newStatements: ts.Statement[], log: LogInfo[], - supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder: boolean = false): void { +export function processComponentChild(node: ts.Block | ts.SourceFile, newStatements: ts.Statement[], + log: LogInfo[], supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, + isInnerBuilder: boolean = false): void { if (supplement.isAcceleratePreview) { newsupplement = supplement; const compilerOptions = ts.readConfigFile( diff --git a/compiler/src/process_component_class.ts b/compiler/src/process_component_class.ts index 5993be5..3dd3441 100644 --- a/compiler/src/process_component_class.ts +++ b/compiler/src/process_component_class.ts @@ -55,14 +55,16 @@ import { COMPONENT_SET_AND_LINK, COMPONENT_SET_AND_PROP, COMPONENT_CONSTRUCTOR_UNDEFINED, - CUSTOM_COMPONENT + CUSTOM_COMPONENT, + COMPONENT_CONSTRUCTOR_PARENT } from './pre_define'; import { BUILDIN_STYLE_NAMES, CUSTOM_BUILDER_METHOD, INNER_STYLE_FUNCTION, INTERFACE_NODE_SET, - STYLES_ATTRIBUTE + STYLES_ATTRIBUTE, + INNER_CUSTOM_BUILDER_METHOD } from './component_map'; import { componentCollection, @@ -276,7 +278,7 @@ function createLocalStroageCallExpression(node: ts.PropertyDeclaration, name: st ] ); } -export const INNER_CUSTOM_BUILDER_METHOD: Set = new Set(); + function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: ts.Identifier, context: ts.TransformationContext, log: LogInfo[], buildCount: BuildCount): ts.MethodDeclaration { let updateItem: ts.MethodDeclaration = node; @@ -301,18 +303,11 @@ function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: } else if (hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) { CUSTOM_BUILDER_METHOD.add(name); INNER_CUSTOM_BUILDER_METHOD.add(name) - node.parameters.push(ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - ts.factory.createIdentifier("parent"), - undefined, - undefined, - undefined - )) - const builderNode: ts.MethodDeclaration = ts.factory.updateMethodDeclaration(node, undefined, node.modifiers, - node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, - node.type, processComponentBlock(node.body, false, log, false, true)); + node.parameters.push(ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), undefined, undefined, ts.factory.createIdentifier("undefined"))); + const builderNode: ts.MethodDeclaration = ts.factory.updateMethodDeclaration(node, undefined, + node.modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, + node.parameters, node.type, processComponentBlock(node.body, false, log, false, true)); updateItem = processBuildMember(builderNode, context, log); } else if (hasDecorator(node, COMPONENT_STYLES_DECORATOR)) { if (node.parameters && node.parameters.length === 0) { diff --git a/compiler/src/process_component_member.ts b/compiler/src/process_component_member.ts index 7d371e3..b59aa84 100644 --- a/compiler/src/process_component_member.ts +++ b/compiler/src/process_component_member.ts @@ -52,7 +52,8 @@ import { COMPONENT_CREATE_FUNCTION, COMPONENT_BUILDERPARAM_DECORATOR, COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, - COMPONENT_LOCAL_STORAGE_PROP_DECORATOR + COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, + COMPONENT_CONSTRUCTOR_PARENT } from './pre_define'; import { forbiddenUseStateType, @@ -593,7 +594,13 @@ function addCustomComponentId(node: ts.NewExpression, componentName: string, isI argumentsArray = [ts.factory.createObjectLiteralExpression([], true)]; } argumentsArray.unshift(ts.factory.createStringLiteral((++componentInfo.id).toString()), - isInnerBuilder ? ts.factory.createIdentifier('parent') : ts.factory.createThis()); + isInnerBuilder ? ts.factory.createConditionalExpression( + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.ColonToken), + ts.factory.createThis() + ) : ts.factory.createThis()); node = ts.factory.updateNewExpression(node, node.expression, node.typeArguments, argumentsArray); } else if (argumentsArray) { diff --git a/compiler/src/process_custom_component.ts b/compiler/src/process_custom_component.ts index caf4e5e..be467a4 100644 --- a/compiler/src/process_custom_component.ts +++ b/compiler/src/process_custom_component.ts @@ -32,7 +32,8 @@ import { COMPONENT_CONSTRUCTOR_UNDEFINED, CUSTOM_COMPONENT_NEEDS_UPDATE_FUNCTION, CUSTOM_COMPONENT_MARK_STATIC_FUNCTION, - COMPONENT_COMMON + COMPONENT_COMMON, + COMPONENT_CONSTRUCTOR_PARENT } from './pre_define'; import { propertyCollection, @@ -109,7 +110,8 @@ export function processCustomComponent(node: ts.ExpressionStatement, newStatemen ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), null))); bindComponentAttr(node, ts.factory.createIdentifier(COMPONENT_COMMON), newStatements, log); } - addCustomComponent(node, newStatements, customComponentNewExpression, log, name, componentNode, isInnerBuilder); + addCustomComponent(node, newStatements, customComponentNewExpression, log, name, componentNode, + isInnerBuilder); if (hasChainCall) { newStatements.push(ts.factory.createExpressionStatement( createFunction(ts.factory.createIdentifier(COMPONENT_COMMON), @@ -140,7 +142,8 @@ function changeNodeFromCallToArrow(node: ts.CallExpression): ts.ArrowFunction { } function addCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Statement[], - newNode: ts.NewExpression, log: LogInfo[], name: string, componentNode: ts.CallExpression, isInnerBuilder: boolean = false): void { + newNode: ts.NewExpression, log: LogInfo[], name: string, componentNode: ts.CallExpression, + isInnerBuilder: boolean = false): void { if (ts.isNewExpression(newNode)) { const propertyArray: ts.ObjectLiteralElementLike[] = []; validateCustomComponentPrams(componentNode, name, propertyArray, log); @@ -149,7 +152,8 @@ function addCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Stat } function addCustomComponentStatements(node: ts.ExpressionStatement, newStatements: ts.Statement[], - newNode: ts.NewExpression, name: string, props: ts.ObjectLiteralElementLike[], isInnerBuilder: boolean = false): void { + newNode: ts.NewExpression, name: string, props: ts.ObjectLiteralElementLike[], + isInnerBuilder: boolean = false): void { const id: string = componentInfo.id.toString(); newStatements.push(createFindChildById(id, name, isInnerBuilder), createCustomComponentIfStatement(id, ts.factory.updateExpressionStatement(node, createViewCreate(newNode)), @@ -360,7 +364,14 @@ function createFindChildById(id: string, name: string, isInnerBuilder: boolean = [ts.factory.createVariableDeclaration(ts.factory.createIdentifier( `${CUSTOM_COMPONENT_EARLIER_CREATE_CHILD}${id}`), undefined, ts.factory.createTypeReferenceNode( ts.factory.createIdentifier(name)), ts.factory.createAsExpression(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(isInnerBuilder ? ts.factory.createIdentifier('parent') : ts.factory.createThis(), ts.factory.createIdentifier( + ts.factory.createPropertyAccessExpression(isInnerBuilder ? + ts.factory.createParenthesizedExpression(ts.factory.createConditionalExpression( + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.ColonToken), + ts.factory.createThis() + )) : ts.factory.createThis(), ts.factory.createIdentifier( `${CUSTOM_COMPONENT_FUNCTION_FIND_CHILD_BY_ID}`)), undefined, [ts.factory.createStringLiteral(id)]), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(name))))], ts.NodeFlags.Let)); }