From f567bce9ff9133543bcf41f79bdacfc1acb87176 Mon Sep 17 00:00:00 2001 From: Cuecuexiaoyu Date: Tue, 24 Jun 2025 21:47:30 +0800 Subject: [PATCH] modify optional builderparam Signed-off-by: Cuecuexiaoyu Change-Id: Ia4e0acc50d84134eed398291e7f5029d83db5468 --- .../builder-param/optional-builder-param.ets | 49 ++++++ .../optional-builder-param.test.ts | 143 ++++++++++++++++++ .../property-translators/builderParam.ts | 5 +- 3 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 arkui-plugins/test/demo/mock/decorators/builder-param/optional-builder-param.ets create mode 100644 arkui-plugins/test/ut/ui-plugins/decorators/builder-param/optional-builder-param.test.ts diff --git a/arkui-plugins/test/demo/mock/decorators/builder-param/optional-builder-param.ets b/arkui-plugins/test/demo/mock/decorators/builder-param/optional-builder-param.ets new file mode 100644 index 000000000..5585aba6b --- /dev/null +++ b/arkui-plugins/test/demo/mock/decorators/builder-param/optional-builder-param.ets @@ -0,0 +1,49 @@ +/* + * Copyright (C) 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 { Component, Entry, Builder, BuilderParam, Column, Text, Row } from "@kit.ArkUI" + +@Builder +function showTextBuilder() { + Text('Hello World') +} + +@Component +struct Child { + @BuilderParam customBuilderParam2?: () => void; + @BuilderParam customBuilderParam1: () => void = showTextBuilder; + + build() { + Row() { + if (this.customBuilderParam2) { + (this.customBuilderParam2 as () => void)() + } + this.customBuilderParam1() + } + } +} + +@Component +struct Parent { + @Builder componentBuilder() { + Text('Parent builder') + } + + build() { + Column() { + Child() + } + } +} \ No newline at end of file diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/builder-param/optional-builder-param.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/builder-param/optional-builder-param.test.ts new file mode 100644 index 000000000..11cc65e40 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/decorators/builder-param/optional-builder-param.test.ts @@ -0,0 +1,143 @@ +/* + * Copyright (c) 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 path from 'path'; +import { PluginTester } from '../../../../utils/plugin-tester'; +import { mockBuildConfig } from '../../../../utils/artkts-config'; +import { getRootPath, MOCK_ENTRY_DIR_PATH } from '../../../../utils/path-config'; +import { parseDumpSrc } from '../../../../utils/parse-string'; +import { recheck, uiNoRecheck } from '../../../../utils/plugins'; +import { BuildConfig, PluginTestContext } from '../../../../utils/shared-types'; +import { uiTransform } from '../../../../../ui-plugins'; +import { Plugins } from '../../../../../common/plugin-context'; + +const FUNCTION_DIR_PATH: string = 'decorators/builder-param'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, FUNCTION_DIR_PATH, 'optional-builder-param.ets'), +]; + +const pluginTester = new PluginTester('test optional builder param', buildConfig); + +const parsedTransform: Plugins = { + name: 'optional-builder-param', + parsed: uiTransform().parsed +}; + +const expectedScript: string = ` +import { memo as memo } from "arkui.stateManagement.runtime"; +import { LayoutCallback as LayoutCallback } from "arkui.component.customComponent"; +import { CustomComponentV2 as CustomComponentV2 } from "arkui.component.customComponent"; +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; +import { Component as Component, Entry as Entry, Builder as Builder, BuilderParam as BuilderParam, Column as Column, Text as Text, Row as Row } from "@kit.ArkUI"; + +function main() {} + + +@memo() function showTextBuilder() { + Text(undefined, "Hello World"); +} + + +@Component() final struct Child extends CustomComponent { + public __initializeStruct(initializers: __Options_Child | undefined, @memo() content: (()=> void) | undefined): void { + this.__backing_customBuilderParam2 = ((((({let gensym___103851375 = initializers; + (((gensym___103851375) == (null)) ? undefined : gensym___103851375.customBuilderParam2)})) ?? (content))) ?? (undefined)) + this.__backing_customBuilderParam1 = ((((({let gensym___20169645 = initializers; + (((gensym___20169645) == (null)) ? undefined : gensym___20169645.customBuilderParam1)})) ?? (content))) ?? (showTextBuilder)) + } + + public __updateStruct(initializers: __Options_Child | undefined): void {} + + private __backing_customBuilderParam2?: @memo() (()=> void) | undefined; + + public get customBuilderParam2(): @memo() (()=> void) | undefined { + return this.__backing_customBuilderParam2; + } + + public set customBuilderParam2(@memo() value: (()=> void) | undefined) { + this.__backing_customBuilderParam2 = value; + } + + private __backing_customBuilderParam1?: @memo() (()=> void); + + public get customBuilderParam1(): @memo() (()=> void) { + return this.__backing_customBuilderParam1!; + } + + public set customBuilderParam1(@memo() value: (()=> void)) { + this.__backing_customBuilderParam1 = value; + } + + @memo() public build() { + Row(undefined, (() => { + if (this.customBuilderParam2) { + (this.customBuilderParam2 as (()=> void))(); + } + this.customBuilderParam1(); + })); + } + + private constructor() {} + +} + +@Component() final struct Parent extends CustomComponent { + public __initializeStruct(initializers: __Options_Parent | undefined, @memo() content: (()=> void) | undefined): void {} + + public __updateStruct(initializers: __Options_Parent | undefined): void {} + + @memo() public componentBuilder() { + Text(undefined, "Parent builder"); + } + + @memo() public build() { + Column(undefined, (() => { + Child._instantiateImpl(undefined, (() => { + return new Child(); + })); + })); + } + + private constructor() {} + +} + +@Component() export interface __Options_Child { + set customBuilderParam2(customBuilderParam2: (()=> void) | undefined | undefined) + get customBuilderParam2(): (()=> void) | undefined | undefined + set customBuilderParam1(@memo() customBuilderParam1: (()=> void) | undefined) + get customBuilderParam1(): @memo() (()=> void) | undefined +} + +@Component() export interface __Options_Parent { +} +`; + +function testCheckedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedScript)); +} + +pluginTester.run( + 'test optional builder param', + [parsedTransform, uiNoRecheck, recheck], + { + 'checked:ui-no-recheck': [testCheckedTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/ui-plugins/property-translators/builderParam.ts b/arkui-plugins/ui-plugins/property-translators/builderParam.ts index 44266f3d1..9d5f928b7 100644 --- a/arkui-plugins/ui-plugins/property-translators/builderParam.ts +++ b/arkui-plugins/ui-plugins/property-translators/builderParam.ts @@ -52,12 +52,13 @@ export class BuilderParamTranslator extends PropertyTranslator implements Initia arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE, true ); - const thisGetValue: arkts.Expression = generateThisBacking(newName, false, true); const thisSetValue: arkts.Expression = generateThisBacking(newName, false, false); const getter: arkts.MethodDefinition = this.translateGetter( originalName, this.property.typeAnnotation, - thisGetValue + arkts.hasModifierFlag(this.property, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_OPTIONAL) + ? generateThisBacking(newName, false, false) + : generateThisBacking(newName, false, true) ); const setter: arkts.MethodDefinition = this.translateSetter( originalName, -- Gitee