diff --git a/arkui-plugins/common/predefines.ts b/arkui-plugins/common/predefines.ts index e2ff4e25b06d0c68ee84a12cc4da16417d89d561..de04875ea5abe398c9d4fa4e4b22972cfca43658 100644 --- a/arkui-plugins/common/predefines.ts +++ b/arkui-plugins/common/predefines.ts @@ -161,10 +161,12 @@ export enum DecoratorNames { MONITOR = 'Monitor', COMPUTED = 'Computed', EVENT = 'Event', + REQUIRE = 'Require' } export enum TypeNames { NULLISH_TYPE = 'NullishType', + ANY = 'Any' } export enum DecoratorIntrinsicNames { diff --git a/arkui-plugins/test/demo/mock/decorators/custom-dialog/controller-in-method.ets b/arkui-plugins/test/demo/mock/decorators/custom-dialog/controller-in-method.ets new file mode 100644 index 0000000000000000000000000000000000000000..677b6298247ae00a1f46507529f406db63463837 --- /dev/null +++ b/arkui-plugins/test/demo/mock/decorators/custom-dialog/controller-in-method.ets @@ -0,0 +1,47 @@ +/* + * 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, CustomDialog, CustomDialogController } from "@ohos.arkui.component" +import hilog from '@ohos.hilog' + +@CustomDialog +struct CustomDialogExample { + aaController?: CustomDialogController; + build() {} +} + +@Component +struct CustomDialogUser { + dialogController: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExample({}), + }); + + updateController1() { + this.dialogController = new CustomDialogController({ + builder: CustomDialogExample({}), + autoCancel: true, + }); + } + + updateController2() { + let temp = new CustomDialogController({ + builder: CustomDialogExample({}), + autoCancel: true, + }); + this.dialogController = temp; + } + + build() {} +} \ No newline at end of file diff --git a/arkui-plugins/test/demo/mock/decorators/require/basic-require.ets b/arkui-plugins/test/demo/mock/decorators/require/basic-require.ets new file mode 100644 index 0000000000000000000000000000000000000000..86703f8b58e981eff528f1fd518c952b5a66a735 --- /dev/null +++ b/arkui-plugins/test/demo/mock/decorators/require/basic-require.ets @@ -0,0 +1,40 @@ +/* + * 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, ComponentV2, BuilderParam } from "@ohos.arkui.component" +import { State, Require, Prop, Provide, Param } from "@ohos.arkui.stateManagement" + +@Component +struct MyStateSample { + hello: string = 'hello'; + @State state1: boolean = false; + @Require select100: string; + @Require @State select0: number; + @Require @State select3: number | null; + @Require @State select4: undefined; + @Require @Prop select1: string; + @Require @Provide({ alias: '15' }) select2: string[]; + @Require @Provide({ alias: 't' }) select6: string[] | undefined | string; + @Require @BuilderParam builder: () => void; + + build() {} +} + +@ComponentV2 +struct V2222 { + @Require @Param select1: string; + + build() {} +} \ No newline at end of file diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/base-custom-dialog.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/base-custom-dialog.test.ts index 6de9a9682da0f4dbd537ab4060f358917891e496..7547b4bfe17a101048e2c8d8eac4c05f11dd47a2 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/base-custom-dialog.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/base-custom-dialog.test.ts @@ -159,11 +159,12 @@ function main() {} @Component() final struct CustomDialogUser extends CustomComponent { public __initializeStruct(initializers: (__Options_CustomDialogUser | undefined), @memo() content: ((()=> void) | undefined)): void { this.__backing_dialogController = ((({let gensym___56650533 = initializers; - (((gensym___56650533) == (null)) ? undefined : gensym___56650533.dialogController)})) ?? (new CustomDialogController({ + (((gensym___56650533) == (null)) ? undefined : gensym___56650533.dialogController)})) ?? (({let gensym___249621102: Any; + gensym___249621102 = new CustomDialogController({ builder: @memo() (() => { CustomDialogExample._instantiateImpl(undefined, (() => { const instance = new CustomDialogExample(); - instance.__setDialogController__((this.dialogController as CustomDialogController)); + instance.__setDialogController__((gensym___249621102 as CustomDialogController)); return instance; }), { cancel: (() => { @@ -188,7 +189,8 @@ function main() {} cornerRadius: 10, focusable: true, baseComponent: this, - }))); + }) + (gensym___249621102 as CustomDialogController)}))); } public __updateStruct(initializers: (__Options_CustomDialogUser | undefined)): void {} diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/builder-dialog-options.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/builder-dialog-options.test.ts index dd536fdd69c7592323dcf489183a2f8281d08f82..32f6024036510467b129890a4bac4c787ecfa644 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/builder-dialog-options.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/builder-dialog-options.test.ts @@ -108,13 +108,15 @@ function main() {} @Component() final struct CustomDialogUser extends CustomComponent { public __initializeStruct(initializers: (__Options_CustomDialogUser | undefined), @memo() content: ((()=> void) | undefined)): void { - this.__backing_dialogController = ((({let gensym___50325868 = initializers; - (((gensym___50325868) == (null)) ? undefined : gensym___50325868.dialogController)})) ?? (new CustomDialogController({ + this.__backing_dialogController = ((({let gensym___51459619 = initializers; + (((gensym___51459619) == (null)) ? undefined : gensym___51459619.dialogController)})) ?? (({let gensym___203542966: Any; + gensym___203542966 = new CustomDialogController({ builder: @memo() (() => { builder1("nihao"); }), baseComponent: this, - }))); + }) + (gensym___203542966 as CustomDialogController)}))); } public __updateStruct(initializers: (__Options_CustomDialogUser | undefined)): void {} @@ -139,11 +141,13 @@ function main() {} @Component() final struct CustomDialogUser2 extends CustomComponent { public __initializeStruct(initializers: (__Options_CustomDialogUser2 | undefined), @memo() content: ((()=> void) | undefined)): void { - this.__backing_dialogController = ((({let gensym___51459619 = initializers; - (((gensym___51459619) == (null)) ? undefined : gensym___51459619.dialogController)})) ?? (new CustomDialogController({ + this.__backing_dialogController = ((({let gensym___176924847 = initializers; + (((gensym___176924847) == (null)) ? undefined : gensym___176924847.dialogController)})) ?? (({let gensym___46528967: Any; + gensym___46528967 = new CustomDialogController({ builder: builder2, baseComponent: this, - }))); + }) + (gensym___46528967 as CustomDialogController)}))); } public __updateStruct(initializers: (__Options_CustomDialogUser2 | undefined)): void {} diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-build.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-build.test.ts index 53e1ee0aa02a8028888296d980c8ffddcbfd8b71..9ad581f09cae75e99d9b61ba4101a9b9f5eae658 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-build.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-build.test.ts @@ -130,7 +130,7 @@ function main() {} Column(undefined, undefined, @memo() (() => { Button(@memo() ((instance: ButtonAttribute): void => { instance.onClick(((e: ClickEvent) => { - let dialogController: (CustomDialogController | undefined) = ({let gensym___220374545: (CustomDialogController | undefined); + let dialogController: (CustomDialogController | undefined) = ({let gensym___220374545: Any; gensym___220374545 = new CustomDialogController({ builder: @memo() (() => { CustomDialogExample._instantiateImpl(undefined, (() => { @@ -141,7 +141,7 @@ function main() {} }), baseComponent: this, }) - gensym___220374545}); + (gensym___220374545 as CustomDialogController)}); })).backgroundColor(0x317aff); return; }), "click me", undefined, undefined); diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-method.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-method.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ea1b773addc3dc8845ccd7c6e7a63be604ac2650 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/controller-in-method.test.ts @@ -0,0 +1,176 @@ +/* + * 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/custom-dialog'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, FUNCTION_DIR_PATH, 'controller-in-method.ets'), +]; + +const pluginTester = new PluginTester('test CutomDialogController assignment in method', buildConfig); + +const parsedTransform: Plugins = { + name: 'controller-in-method', + parsed: uiTransform().parsed, +}; + +const expectedScript: string = ` +import { memo as memo } from "arkui.stateManagement.runtime"; +import { BaseCustomDialog as BaseCustomDialog } from "arkui.component.customComponent"; +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; +import { Component as Component, CustomDialog as CustomDialog, CustomDialogController as CustomDialogController } from "@ohos.arkui.component"; +import hilog from "@ohos.hilog"; + +function main() {} + +@CustomDialog() final struct CustomDialogExample extends BaseCustomDialog { + public __initializeStruct(initializers: (__Options_CustomDialogExample | undefined), @memo() content: ((()=> void) | undefined)): void { + if (({let gensym___45519047 = initializers; + (((gensym___45519047) == (null)) ? undefined : gensym___45519047.aaController)})) { + this.__backing_aaController = ((({let gensym___180078470 = initializers; + (((gensym___180078470) == (null)) ? undefined : gensym___180078470.aaController)})) ?? (undefined)); + } + } + + public __updateStruct(initializers: (__Options_CustomDialogExample | undefined)): void {} + + private __backing_aaController?: (CustomDialogController | undefined); + + public get aaController(): (CustomDialogController | undefined) { + return (this.__backing_aaController as (CustomDialogController | undefined)); + } + + public set aaController(value: (CustomDialogController | undefined)) { + this.__backing_aaController = value; + } + + public __setDialogController__(controller: CustomDialogController): void { + this.__backing_aaController = controller; + } + + @memo() public build() {} + + private constructor() {} + +} + +@Component() final struct CustomDialogUser extends CustomComponent { + public __initializeStruct(initializers: (__Options_CustomDialogUser | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_dialogController = ((({let gensym___95501822 = initializers; + (((gensym___95501822) == (null)) ? undefined : gensym___95501822.dialogController)})) ?? (({let gensym___46528967: Any; + gensym___46528967 = new CustomDialogController({ + builder: @memo() (() => { + CustomDialogExample._instantiateImpl(undefined, (() => { + const instance = new CustomDialogExample(); + instance.__setDialogController__((gensym___46528967 as CustomDialogController)); + return instance; + }), {}, undefined); + }), + baseComponent: this, + }) + (gensym___46528967 as CustomDialogController)}))); + } + + public __updateStruct(initializers: (__Options_CustomDialogUser | undefined)): void {} + + private __backing_dialogController?: (CustomDialogController | null); + + public get dialogController(): (CustomDialogController | null) { + return (this.__backing_dialogController as (CustomDialogController | null)); + } + + public set dialogController(value: (CustomDialogController | null)) { + this.__backing_dialogController = value; + } + + public updateController1() { + this.dialogController = ({let gensym___17371929: Any; + gensym___17371929 = new CustomDialogController({ + builder: @memo() (() => { + CustomDialogExample._instantiateImpl(undefined, (() => { + const instance = new CustomDialogExample(); + instance.__setDialogController__((gensym___17371929 as CustomDialogController)); + return instance; + }), {}, undefined); + }), + autoCancel: true, + baseComponent: this, + }) + (gensym___17371929 as CustomDialogController)}); + } + + public updateController2() { + let temp = ({let gensym___90667230: Any; + gensym___90667230 = new CustomDialogController({ + builder: @memo() (() => { + CustomDialogExample._instantiateImpl(undefined, (() => { + const instance = new CustomDialogExample(); + instance.__setDialogController__((gensym___90667230 as CustomDialogController)); + return instance; + }), {}, undefined); + }), + autoCancel: true, + baseComponent: this, + }) + (gensym___90667230 as CustomDialogController)}); + this.dialogController = temp; + } + + @memo() public build() {} + + private constructor() {} + +} + +@CustomDialog() export interface __Options_CustomDialogExample { + set aaController(aaController: ((CustomDialogController | undefined) | undefined)) + + get aaController(): ((CustomDialogController | undefined) | undefined) + +} + +@Component() export interface __Options_CustomDialogUser { + set dialogController(dialogController: ((CustomDialogController | null) | undefined)) + + get dialogController(): ((CustomDialogController | null) | undefined) + +} +`; + +function testCheckedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedScript)); +} + +pluginTester.run( + 'test CutomDialogController assignment in method', + [parsedTransform, uiNoRecheck, recheck], + { + 'checked:ui-no-recheck': [testCheckedTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/extends-dialog-controller.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/extends-dialog-controller.test.ts index 955038153872063d6069cfe1224159e0b7ff2354..1785866b1612271345d6d1533d4f195af72fc34f 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/extends-dialog-controller.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/custom-dialog/extends-dialog-controller.test.ts @@ -108,18 +108,20 @@ class DialogControllerV3 extends DialogControllerV2 { @Component() final struct CustomDialogUser extends CustomComponent { public __initializeStruct(initializers: (__Options_CustomDialogUser | undefined), @memo() content: ((()=> void) | undefined)): void { this.__backing_dialogController = ((({let gensym___176924847 = initializers; - (((gensym___176924847) == (null)) ? undefined : gensym___176924847.dialogController)})) ?? ((new CustomDialogController(({ + (((gensym___176924847) == (null)) ? undefined : gensym___176924847.dialogController)})) ?? ((({let gensym___46528967: Any; + gensym___46528967 = new CustomDialogController(({ gridCount: 4, showInSubWindow: true, builder: @memo() (() => { CustomDialogExample._instantiateImpl(undefined, (() => { const instance = new CustomDialogExample(); - instance.__setDialogController__((this.dialogController as CustomDialogController)); + instance.__setDialogController__((gensym___46528967 as CustomDialogController)); return instance; }), undefined, undefined); }), baseComponent: this, - } as CustomDialogControllerOptions)) as DialogControllerV3))); + } as CustomDialogControllerOptions)) + (gensym___46528967 as CustomDialogController)}) as DialogControllerV3))); } public __updateStruct(initializers: (__Options_CustomDialogUser | undefined)): void {} diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/require/basic-require.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/require/basic-require.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..659935b0028cadb56a65258f91ae607ee1f508a7 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/decorators/require/basic-require.test.ts @@ -0,0 +1,354 @@ +/* + * 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 { structNoRecheck, recheck, uiNoRecheck } from '../../../../utils/plugins'; +import { BuildConfig, PluginTestContext } from '../../../../utils/shared-types'; +import { uiTransform } from '../../../../../ui-plugins'; +import { Plugins } from '../../../../../common/plugin-context'; + +const STATE_DIR_PATH: string = 'decorators/require'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, STATE_DIR_PATH, 'basic-require.ets'), +]; + +const pluginTester = new PluginTester('test @Require decorator capability', buildConfig); + +const parsedTransform: Plugins = { + name: 'parsedTrans', + parsed: uiTransform().parsed +}; + +const expectedParsedScript: string = ` +import { CustomComponentV2 as CustomComponentV2 } from "arkui.component.customComponent"; +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; +import { Component as Component, ComponentV2 as ComponentV2, BuilderParam as BuilderParam } from "@ohos.arkui.component"; +import { State as State, Require as Require, Prop as Prop, Provide as Provide, Param as Param } from "@ohos.arkui.stateManagement"; + +@Component() final struct MyStateSample extends CustomComponent { + public hello: string = "hello"; + @State() public state1: boolean = false; + @Require() public select100!: string; + @Require() @State() public select0!: number; + @Require() @State() public select3?: (number | null); + @Require() @State() public select4?: undefined; + @Require() @Prop() public select1!: string; + @Require() @Provide({alias:"15"}) public select2!: string[]; + @Require() @Provide({alias:"t"}) public select6?: (string[] | undefined | string); + @Require() @BuilderParam() public builder!: (()=> void); + + public build() {} + + public constructor() {} + +} + +@ComponentV2() final struct V2222 extends CustomComponentV2 { + @Require() @Param() public select1!: string; + + public build() {} + + public constructor() {} + +} + +@Component() export interface __Options_MyStateSample { + hello?: string; + state1?: boolean; + @State() __backing_state1?: boolean; + select100?: string; + select0?: number; + @State() __backing_select0?: number; + select3?: (number | null); + @State() __backing_select3?: (number | null); + select4?: undefined; + @State() __backing_select4?: undefined; + select1?: string; + @Prop() __backing_select1?: string; + select2?: string[]; + @Provide({alias:"15"}) __backing_select2?: string[]; + select6?: (string[] | undefined | string); + @Provide({alias:"t"}) __backing_select6?: (string[] | undefined | string); + @BuilderParam() builder?: (()=> void); + +} + +@ComponentV2() export interface __Options_V2222 { + select1?: string; + @Param() __backing_select1?: string; + +} +`; + +const expectedCheckedScript: string = ` +import { IParamDecoratedVariable as IParamDecoratedVariable } from "arkui.stateManagement.decorator"; +import { IProvideDecoratedVariable as IProvideDecoratedVariable } from "arkui.stateManagement.decorator"; +import { IPropDecoratedVariable as IPropDecoratedVariable } from "arkui.stateManagement.decorator"; +import { STATE_MGMT_FACTORY as STATE_MGMT_FACTORY } from "arkui.stateManagement.decorator"; +import { IStateDecoratedVariable as IStateDecoratedVariable } from "arkui.stateManagement.decorator"; +import { memo as memo } from "arkui.stateManagement.runtime"; +import { CustomComponentV2 as CustomComponentV2 } from "arkui.component.customComponent"; +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; +import { Component as Component, ComponentV2 as ComponentV2, BuilderParam as BuilderParam } from "@ohos.arkui.component"; +import { State as State, Require as Require, Prop as Prop, Provide as Provide, Param as Param } from "@ohos.arkui.stateManagement"; + +function main() {} + +@Component() final struct MyStateSample extends CustomComponent { + public __initializeStruct(initializers: (__Options_MyStateSample | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_hello = ((({let gensym___159351621 = initializers; + (((gensym___159351621) == (null)) ? undefined : gensym___159351621.hello)})) ?? ("hello")); + this.__backing_state1 = STATE_MGMT_FACTORY.makeState(this, "state1", ((({let gensym___152317197 = initializers; + (((gensym___152317197) == (null)) ? undefined : gensym___152317197.state1)})) ?? (false))); + this.__backing_select100 = ((({let gensym___257385749 = initializers; + (((gensym___257385749) == (null)) ? undefined : gensym___257385749.select100)})) ?? (undefined)); + this.__backing_select0 = STATE_MGMT_FACTORY.makeState(this, "select0", (initializers!.select0 as number)); + this.__backing_select3 = STATE_MGMT_FACTORY.makeState<(number | null)>(this, "select3", (initializers!.select3 as (number | null))); + this.__backing_select4 = STATE_MGMT_FACTORY.makeState(this, "select4", (initializers!.select4 as undefined)); + this.__backing_select1 = STATE_MGMT_FACTORY.makeProp(this, "select1", (initializers!.select1 as string)); + this.__backing_select2 = STATE_MGMT_FACTORY.makeProvide>(this, "select2", "15", (initializers!.select2 as Array), false); + this.__backing_select6 = STATE_MGMT_FACTORY.makeProvide<(Array | undefined | string)>(this, "select6", "t", (initializers!.select6 as (Array | undefined | string)), false); + this.__backing_builder = ((((({let gensym___57081607 = initializers; + (((gensym___57081607) == (null)) ? undefined : gensym___57081607.builder)})) ?? (content))) ?? (undefined)) + } + + public __updateStruct(initializers: (__Options_MyStateSample | undefined)): void { + if (((({let gensym___171969630 = initializers; + (((gensym___171969630) == (null)) ? undefined : gensym___171969630.select1)})) !== (undefined))) { + this.__backing_select1!.update((initializers!.select1 as string)); + } + } + + private __backing_hello?: string; + + public get hello(): string { + return (this.__backing_hello as string); + } + + public set hello(value: string) { + this.__backing_hello = value; + } + + private __backing_state1?: IStateDecoratedVariable; + + public get state1(): boolean { + return this.__backing_state1!.get(); + } + + public set state1(value: boolean) { + this.__backing_state1!.set(value); + } + + private __backing_select100?: string; + + public get select100(): string { + return (this.__backing_select100 as string); + } + + public set select100(value: string) { + this.__backing_select100 = value; + } + + private __backing_select0?: IStateDecoratedVariable; + + public get select0(): number { + return this.__backing_select0!.get(); + } + + public set select0(value: number) { + this.__backing_select0!.set(value); + } + + private __backing_select3?: IStateDecoratedVariable<(number | null)>; + + public get select3(): (number | null) { + return this.__backing_select3!.get(); + } + + public set select3(value: (number | null)) { + this.__backing_select3!.set(value); + } + + private __backing_select4?: IStateDecoratedVariable; + + public get select4(): undefined { + return this.__backing_select4!.get(); + } + + public set select4(value: undefined) { + this.__backing_select4!.set(value); + } + + private __backing_select1?: IPropDecoratedVariable; + + public get select1(): string { + return this.__backing_select1!.get(); + } + + public set select1(value: string) { + this.__backing_select1!.set(value); + } + + private __backing_select2?: IProvideDecoratedVariable>; + + public get select2(): Array { + return this.__backing_select2!.get(); + } + + public set select2(value: Array) { + this.__backing_select2!.set(value); + } + + private __backing_select6?: IProvideDecoratedVariable<(Array | undefined | string)>; + + public get select6(): (Array | undefined | string) { + return this.__backing_select6!.get(); + } + + public set select6(value: (Array | undefined | string)) { + this.__backing_select6!.set(value); + } + + private __backing_builder?: @memo() (()=> void); + + public get builder(): @memo() (()=> void) { + return this.__backing_builder!; + } + + public set builder(value: @memo() (()=> void)) { + this.__backing_builder = value; + } + + @memo() public build() {} + + private constructor() {} + +} + +@ComponentV2() final struct V2222 extends CustomComponentV2 { + public __initializeStruct(initializers: (__Options_V2222 | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_select1 = STATE_MGMT_FACTORY.makeParam(this, "select1", (initializers!.select1 as string)); + } + + public __updateStruct(initializers: (__Options_V2222 | undefined)): void { + if (((({let gensym___155019449 = initializers; + (((gensym___155019449) == (null)) ? undefined : gensym___155019449.select1)})) !== (undefined))) { + this.__backing_select1!.update((initializers!.select1 as string)); + } + } + + private __backing_select1?: IParamDecoratedVariable; + + public get select1(): string { + return this.__backing_select1!.get(); + } + + @memo() public build() {} + + private constructor() {} + +} + +@Component() export interface __Options_MyStateSample { + set hello(hello: (string | undefined)) + + get hello(): (string | undefined) + set state1(state1: (boolean | undefined)) + + get state1(): (boolean | undefined) + set __backing_state1(__backing_state1: (IStateDecoratedVariable | undefined)) + + get __backing_state1(): (IStateDecoratedVariable | undefined) + set select100(select100: (string | undefined)) + + get select100(): (string | undefined) + set select0(select0: (number | undefined)) + + get select0(): (number | undefined) + set __backing_select0(__backing_select0: (IStateDecoratedVariable | undefined)) + + get __backing_select0(): (IStateDecoratedVariable | undefined) + set select3(select3: ((number | null) | undefined)) + + get select3(): ((number | null) | undefined) + set __backing_select3(__backing_select3: (IStateDecoratedVariable<(number | null)> | undefined)) + + get __backing_select3(): (IStateDecoratedVariable<(number | null)> | undefined) + set select4(select4: (undefined | undefined)) + + get select4(): (undefined | undefined) + set __backing_select4(__backing_select4: (IStateDecoratedVariable | undefined)) + + get __backing_select4(): (IStateDecoratedVariable | undefined) + set select1(select1: (string | undefined)) + + get select1(): (string | undefined) + set __backing_select1(__backing_select1: (IPropDecoratedVariable | undefined)) + + get __backing_select1(): (IPropDecoratedVariable | undefined) + set select2(select2: (Array | undefined)) + + get select2(): (Array | undefined) + set __backing_select2(__backing_select2: (IProvideDecoratedVariable> | undefined)) + + get __backing_select2(): (IProvideDecoratedVariable> | undefined) + set select6(select6: ((Array | undefined | string) | undefined)) + + get select6(): ((Array | undefined | string) | undefined) + set __backing_select6(__backing_select6: (IProvideDecoratedVariable<(Array | undefined | string)> | undefined)) + + get __backing_select6(): (IProvideDecoratedVariable<(Array | undefined | string)> | undefined) + set builder(builder: (@memo() (()=> void) | undefined)) + + get builder(): (@memo() (()=> void) | undefined) + +} + +@ComponentV2() export interface __Options_V2222 { + set select1(select1: (string | undefined)) + + get select1(): (string | undefined) + set __backing_select1(__backing_select1: (IParamDecoratedVariable | undefined)) + + get __backing_select1(): (IParamDecoratedVariable | undefined) + +} +`; + +function testParsedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedParsedScript)); +} + +function testCheckedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedCheckedScript)); +} + +pluginTester.run( + 'test @Require decorator capability', + [parsedTransform, uiNoRecheck, recheck], + { + 'parsed': [testParsedTransformer], + 'checked:ui-no-recheck': [testCheckedTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/ui-plugins/property-translators/factory.ts b/arkui-plugins/ui-plugins/property-translators/factory.ts index af331b60fb79df1fbaf80240de114fdc186d419c..0cc0f24ef46b1d12804784a225739ba06b7005ad 100644 --- a/arkui-plugins/ui-plugins/property-translators/factory.ts +++ b/arkui-plugins/ui-plugins/property-translators/factory.ts @@ -289,6 +289,22 @@ export class factory { ); } + /* + * create `initializers!. as `. + */ + static generateDefiniteInitializers(type: arkts.TypeNode | undefined, originalName: string): arkts.Expression { + return arkts.factory.createTSAsExpression( + factory.createNonNullOrOptionalMemberExpression( + CustomComponentNames.COMPONENT_INITIALIZERS_NAME, + originalName, + false, + true + ), + type ? type.clone() : undefined, + false + ); + } + static judgeIfAddWatchFunc(args: arkts.Expression[], property: arkts.ClassProperty): void { if (hasDecorator(property, DecoratorNames.WATCH)) { const watchStr: string | undefined = getValueInAnnotation(property, DecoratorNames.WATCH); diff --git a/arkui-plugins/ui-plugins/property-translators/param.ts b/arkui-plugins/ui-plugins/property-translators/param.ts index 5332703c1158418c91e217759f2c850fba3d4f65..8f307b7535d37a8fbf27e829499d3b6922e8ad77 100644 --- a/arkui-plugins/ui-plugins/property-translators/param.ts +++ b/arkui-plugins/ui-plugins/property-translators/param.ts @@ -84,16 +84,7 @@ export class ParamTranslator extends PropertyTranslator implements InitializerCo this.property.value, arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING ) - : arkts.factory.createTSAsExpression( - factory.createNonNullOrOptionalMemberExpression( - CustomComponentNames.COMPONENT_INITIALIZERS_NAME, - originalName, - false, - true - ), - this.property.typeAnnotation?.clone(), - false - ), + : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), ]; collectStateManagementTypeImport(StateManagementTypes.PARAM_DECORATED); const assign: arkts.AssignmentExpression = arkts.factory.createAssignmentExpression( diff --git a/arkui-plugins/ui-plugins/property-translators/prop.ts b/arkui-plugins/ui-plugins/property-translators/prop.ts index efabedecdc92023de46bc9203f33f5d59a60eb98..47722196db452e716a43b5c89decfcd99d79c50b 100644 --- a/arkui-plugins/ui-plugins/property-translators/prop.ts +++ b/arkui-plugins/ui-plugins/property-translators/prop.ts @@ -108,16 +108,7 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon arkts.factory.create1StringLiteral(originalName), this.property.value ? binaryItem - : arkts.factory.createTSAsExpression( - factory.createNonNullOrOptionalMemberExpression( - CustomComponentNames.COMPONENT_INITIALIZERS_NAME, - originalName, - false, - true - ), - this.property.typeAnnotation ? this.property.typeAnnotation.clone() : undefined, - false - ), + : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), ]; factory.judgeIfAddWatchFunc(args, this.property); collectStateManagementTypeImport(StateManagementTypes.PROP_DECORATED); diff --git a/arkui-plugins/ui-plugins/property-translators/provide.ts b/arkui-plugins/ui-plugins/property-translators/provide.ts index c1141a5ac63d1e5bf00c2f0c417c50da74482cfd..fcdc93b168b8bc34044e3b7777bfa5f05f7f1ef6 100644 --- a/arkui-plugins/ui-plugins/property-translators/provide.ts +++ b/arkui-plugins/ui-plugins/property-translators/provide.ts @@ -99,14 +99,16 @@ export class ProvideTranslator extends PropertyTranslator implements Initializer const args: arkts.Expression[] = [ arkts.factory.create1StringLiteral(originalName), arkts.factory.create1StringLiteral(alias), - arkts.factory.createBinaryExpression( - factory.createBlockStatementForOptionalExpression( - arkts.factory.createIdentifier(CustomComponentNames.COMPONENT_INITIALIZERS_NAME), - originalName - ), - this.property.value ?? arkts.factory.createUndefinedLiteral(), - arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING - ), + this.property.value + ? arkts.factory.createBinaryExpression( + factory.createBlockStatementForOptionalExpression( + arkts.factory.createIdentifier(CustomComponentNames.COMPONENT_INITIALIZERS_NAME), + originalName + ), + this.property.value ?? arkts.factory.createUndefinedLiteral(), + arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING + ) + : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), arkts.factory.createBooleanLiteral(allowOverride), ]; factory.judgeIfAddWatchFunc(args, this.property); diff --git a/arkui-plugins/ui-plugins/property-translators/state.ts b/arkui-plugins/ui-plugins/property-translators/state.ts index 704a56f711b3614520ceaa4cf517a9d069d44290..13f5095a847c38a1eafce791ea0e95dffb61b339 100644 --- a/arkui-plugins/ui-plugins/property-translators/state.ts +++ b/arkui-plugins/ui-plugins/property-translators/state.ts @@ -100,7 +100,12 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo this.property.value ?? arkts.factory.createUndefinedLiteral(), arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING ); - const args: arkts.Expression[] = [arkts.factory.create1StringLiteral(originalName), binaryItem]; + const args: arkts.Expression[] = [ + arkts.factory.create1StringLiteral(originalName), + this.property.value + ? binaryItem + : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), + ]; factory.judgeIfAddWatchFunc(args, this.property); collectStateManagementTypeImport(StateManagementTypes.STATE_DECORATED); const assign: arkts.AssignmentExpression = arkts.factory.createAssignmentExpression( diff --git a/arkui-plugins/ui-plugins/property-translators/utils.ts b/arkui-plugins/ui-plugins/property-translators/utils.ts index 8c3a3d35f44608acb8c609739bc11d5fc8838456..868e43aa1f8f43db12aadd71b33d5b7a119644a0 100644 --- a/arkui-plugins/ui-plugins/property-translators/utils.ts +++ b/arkui-plugins/ui-plugins/property-translators/utils.ts @@ -108,7 +108,8 @@ export function needDefiniteOrOptionalModifier(st: arkts.ClassProperty): boolean (hasDecoratorName(st, DecoratorNames.PROP) && !st.value) || (hasDecoratorName(st, DecoratorNames.PROP_REF) && !st.value) || (hasDecoratorName(st, DecoratorNames.PARAM) && !st.value) || - (hasDecoratorName(st, DecoratorNames.EVENT) && !st.value) + (hasDecoratorName(st, DecoratorNames.EVENT) && !st.value) || + (hasDecoratorName(st, DecoratorNames.REQUIRE) && !st.value) ); } diff --git a/arkui-plugins/ui-plugins/struct-translators/factory.ts b/arkui-plugins/ui-plugins/struct-translators/factory.ts index 247be18c75a08a72c9208920f654e8032913567c..744a67b04b0b67e7e9f12911d17150c7ae6b585c 100644 --- a/arkui-plugins/ui-plugins/struct-translators/factory.ts +++ b/arkui-plugins/ui-plugins/struct-translators/factory.ts @@ -54,8 +54,6 @@ import { getCustomDialogController, isInvalidDialogControllerOptions, findBuilderIndexInControllerOptions, - getControllerName, - DialogControllerInfo, ObservedAnnoInfo, getNoTransformationMembersInClass, } from './utils'; @@ -76,6 +74,7 @@ import { StateManagementTypes, RESOURCE_TYPE, ARKUI_BUILDER_SOURCE_NAME, + TypeNames, } from '../../common/predefines'; import { ObservedTranslator } from '../property-translators/index'; import { addMemoAnnotation } from '../../collectors/memo-collectors/utils'; @@ -1106,20 +1105,20 @@ export class factory { node: arkts.ETSNewClassInstanceExpression ): arkts.ETSNewClassInstanceExpression | arkts.Expression { if (isInvalidDialogControllerOptions(node.getArguments)) { - throw new Error('Error CustomDialogOptions'); + return node; } const optionArg = node.getArguments[0]; const options: arkts.ObjectExpression = arkts.isObjectExpression(optionArg) ? optionArg : ((optionArg as arkts.TSAsExpression).expr as arkts.ObjectExpression); - const builderIndex: number = findBuilderIndexInControllerOptions(options.properties); - if (builderIndex < 0 || !(options.properties[builderIndex] as arkts.Property).value) { - throw new Error('Error CustomDialogOptions'); + const properties = options.properties as arkts.Property[]; + const builderIndex: number = findBuilderIndexInControllerOptions(properties); + if (builderIndex < 0 || !properties.at(builderIndex)!.value) { + return node; } - const builder: arkts.Property = options.properties[builderIndex] as arkts.Property; - const controllerInfo: DialogControllerInfo = getControllerName(node); - const gensymName: string = GenSymGenerator.getInstance().id(controllerInfo.controllerName); - const newBuilderValue = this.createDialogBuilderArrow(builder.value!, controllerInfo, gensymName); + const builder: arkts.Property = properties.at(builderIndex)!; + const gensymName: string = GenSymGenerator.getInstance().id(); + const newBuilderValue = this.createDialogBuilderArrow(builder.value!, gensymName); const newProperty = arkts.factory.updateProperty(builder, builder.key, newBuilderValue); const newObj = arkts.factory.updateObjectExpression( options, @@ -1137,17 +1136,10 @@ export class factory { : newObj; const typeRef = node.getTypeRef as arkts.ETSTypeReference; const newNode = arkts.factory.updateETSNewClassInstanceExpression(node, typeRef, [newOptions]); - if (controllerInfo.parent && arkts.isVariableDeclarator(controllerInfo.parent)) { - return factory.createBlockStatementForOptionalExpression(controllerInfo.parent, newNode, gensymName); - } - return newNode; + return factory.createBlockStatementForOptionalExpression(newNode, gensymName); } - static createDialogBuilderArrow( - value: arkts.Expression, - controllerInfo: DialogControllerInfo, - gensymName: string - ): arkts.Expression { + static createDialogBuilderArrow(value: arkts.Expression, gensymName: string): arkts.Expression { if ( arkts.isCallExpression(value) && arkts.isMemberExpression(value.expression) && @@ -1159,7 +1151,7 @@ export class factory { UIFactory.createScriptFunction({ body: arkts.factory.createBlock([ arkts.factory.createExpressionStatement( - this.transformCustomDialogComponentCall(value, controllerInfo, gensymName) + this.transformCustomDialogComponentCall(value, gensymName) ), ]), flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW, @@ -1174,15 +1166,11 @@ export class factory { return value; } - static transformCustomDialogComponentCall( - value: arkts.CallExpression, - controllerInfo: DialogControllerInfo, - gensymName: string - ): arkts.CallExpression { + static transformCustomDialogComponentCall(value: arkts.CallExpression, gensymName: string): arkts.CallExpression { if (value.arguments.length >= 2 && arkts.isArrowFunctionExpression(value.arguments[1])) { const originScript: arkts.ScriptFunction = value.arguments[1].scriptFunction; const newScript: arkts.ScriptFunction = UIFactory.updateScriptFunction(originScript, { - body: this.generateInstanceSetController(originScript.body, controllerInfo, gensymName), + body: this.generateInstanceSetController(originScript.body, gensymName), }); return arkts.factory.updateCallExpression(value, value.expression, value.typeArguments, [ value.arguments[0], @@ -1195,7 +1183,6 @@ export class factory { static generateInstanceSetController( body: arkts.AstNode | undefined, - controllerInfo: DialogControllerInfo, gensymName: string ): arkts.AstNode | undefined { if ( @@ -1219,18 +1206,14 @@ export class factory { ), ] ), - this.genertateControllerSetCall(instanceIdent, controllerInfo, gensymName), + this.genertateControllerSetCall(instanceIdent, gensymName), arkts.factory.createReturnStatement(instanceIdent.clone()), ]); } return body; } - static genertateControllerSetCall( - instanceIdent: arkts.Identifier, - controllerInfo: DialogControllerInfo, - gensymName: string - ): arkts.AstNode { + static genertateControllerSetCall(instanceIdent: arkts.Identifier, gensymName: string): arkts.AstNode { return arkts.factory.createExpressionStatement( arkts.factory.createCallExpression( arkts.factory.createMemberExpression( @@ -1243,9 +1226,7 @@ export class factory { undefined, [ arkts.factory.createTSAsExpression( - controllerInfo.isClassProperty - ? generateThisBacking(controllerInfo.controllerName) - : arkts.factory.createIdentifier(gensymName), + arkts.factory.createIdentifier(gensymName), UIFactory.createTypeReferenceFromString(CustomDialogNames.CUSTOM_DIALOG_CONTROLLER), false ), @@ -1276,13 +1257,12 @@ export class factory { } static createBlockStatementForOptionalExpression( - variableNode: arkts.VariableDeclarator, newNode: arkts.ETSNewClassInstanceExpression, gensymName: string ): arkts.Expression { const statements: arkts.Statement[] = [ factory.generateLetVariableDecl( - arkts.factory.createIdentifier(gensymName, variableNode.name.typeAnnotation) + arkts.factory.createIdentifier(gensymName, UIFactory.createTypeReferenceFromString(TypeNames.ANY)) ), arkts.factory.createExpressionStatement( arkts.factory.createAssignmentExpression( @@ -1291,7 +1271,13 @@ export class factory { newNode ) ), - arkts.factory.createExpressionStatement(arkts.factory.createIdentifier(gensymName)), + arkts.factory.createExpressionStatement( + arkts.factory.createTSAsExpression( + arkts.factory.createIdentifier(gensymName), + UIFactory.createTypeReferenceFromString(CustomDialogNames.CUSTOM_DIALOG_CONTROLLER), + false + ) + ), ]; return arkts.factory.createBlockExpression(statements); } diff --git a/arkui-plugins/ui-plugins/struct-translators/utils.ts b/arkui-plugins/ui-plugins/struct-translators/utils.ts index f133af551112f6131213d061d6b8e20e382766ea..ecba338d0f2218eb219efc9b0dbd8431ded149ac 100644 --- a/arkui-plugins/ui-plugins/struct-translators/utils.ts +++ b/arkui-plugins/ui-plugins/struct-translators/utils.ts @@ -65,12 +65,6 @@ export interface ResourceParameter { params: arkts.Expression[]; } -export interface DialogControllerInfo { - controllerName: string; - isClassProperty: boolean; - parent?: arkts.AstNode; -} - export interface ObservedAnnoInfo { className: string; isObserved: boolean; @@ -591,28 +585,6 @@ export function findBuilderIndexInControllerOptions(properties: readonly arkts.E }); } -export function getControllerName(node: arkts.ETSNewClassInstanceExpression): DialogControllerInfo { - let controllerName: string = ''; - let isClassProperty: boolean = false; - let parent: arkts.AstNode | undefined = node.parent; - if (!parent) { - return { controllerName, isClassProperty }; - } - while (!!parent && !arkts.isClassDefinition(parent)) { - if (arkts.isClassProperty(parent) && parent.key && arkts.isIdentifier(parent.key)) { - controllerName = parent.key.name; - isClassProperty = true; - break; - } else if (arkts.isVariableDeclarator(parent)) { - controllerName = parent.name.name; - break; - } - parent = parent?.parent; - } - - return { controllerName, isClassProperty, parent }; -} - export function getNoTransformationMembersInClass( definition: arkts.ClassDefinition, ObservedAnno: ObservedAnnoInfo