diff --git a/arkui-plugins/test/demo/mock/decorators/monitor/monitor-before-state-variable.ets b/arkui-plugins/test/demo/mock/decorators/monitor/monitor-before-state-variable.ets new file mode 100644 index 0000000000000000000000000000000000000000..2a0e4d4c6da54e1d8de6a64319187bf921605d7b --- /dev/null +++ b/arkui-plugins/test/demo/mock/decorators/monitor/monitor-before-state-variable.ets @@ -0,0 +1,45 @@ +/* + * 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 { ComponentV2 } from "@ohos.arkui.component" +import { Monitor, Local, IMonitor } from "@ohos.arkui.stateManagement" + +@ComponentV2 +struct Index { + @Monitor(["message", "name"]) + onStrChange1(monitor: IMonitor) { + monitor.dirty.forEach((path: string) => { + console.info(`${path} changed from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`); + }); + } + @Monitor(["message", "name"]) + onStrChange2(monitor: IMonitor) { + monitor.dirty.forEach((path: string) => { + console.info(`${path} changed from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`); + }); + } + @Monitor(["name"]) + onStrChange3(monitor: IMonitor) { + monitor.dirty.forEach((path: string) => { + console.info(`${path} changed from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`); + }); + } + @Local message: string = "Hello World"; + @Local name: string = "Tom"; + @Local age: number = 24; + + build() { + } +} \ No newline at end of file diff --git a/arkui-plugins/test/demo/mock/decorators/once/once-only.ets b/arkui-plugins/test/demo/mock/decorators/once/once-only.ets new file mode 100644 index 0000000000000000000000000000000000000000..ba4f2892a3073c55d0f35594b46651fa82a5c7e9 --- /dev/null +++ b/arkui-plugins/test/demo/mock/decorators/once/once-only.ets @@ -0,0 +1,25 @@ +/* + * 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 { ComponentV2 } from "@ohos.arkui.component" +import { Once } from "@ohos.arkui.stateManagement" + +@ComponentV2 +struct Child { + @Once onceParamNum: number = 0; + @Once onceVar4: Set = new Set(new Array('aa', 'bb')); + + build() {} +} \ No newline at end of file diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/monitor/monitor-before-state-variable.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/monitor/monitor-before-state-variable.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..88cb56b7cb788f624ce2809e99363f2e3a02f1d6 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/decorators/monitor/monitor-before-state-variable.test.ts @@ -0,0 +1,189 @@ +/* + * 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 STATE_DIR_PATH: string = 'decorators/monitor'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, STATE_DIR_PATH, 'monitor-before-state-variable.ets'), +]; + +const pluginTester = new PluginTester('test @Monitor method declared before state variables', buildConfig); + +const parsedTransform: Plugins = { + name: 'parsedTrans', + parsed: uiTransform().parsed +}; + +const expectedScript: string = ` +import { memo as memo } from "arkui.stateManagement.runtime"; + +import { STATE_MGMT_FACTORY as STATE_MGMT_FACTORY } from "arkui.stateManagement.decorator"; + +import { ILocalDecoratedVariable as ILocalDecoratedVariable } from "arkui.stateManagement.decorator"; + +import { IMonitorDecoratedVariable as IMonitorDecoratedVariable } from "arkui.stateManagement.decorator"; + +import { CustomComponentV2 as CustomComponentV2 } from "arkui.component.customComponent"; + +import { ComponentV2 as ComponentV2 } from "@ohos.arkui.component"; + +import { Monitor as Monitor, Local as Local, IMonitor as IMonitor } from "@ohos.arkui.stateManagement"; + +function main() {} + +@ComponentV2() final struct Index extends CustomComponentV2 { + public __initializeStruct(initializers: (__Options_Index | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_message = STATE_MGMT_FACTORY.makeLocal(this, "message", "Hello World"); + this.__backing_name = STATE_MGMT_FACTORY.makeLocal(this, "name", "Tom"); + this.__backing_age = STATE_MGMT_FACTORY.makeLocal(this, "age", 24); + this.__monitor_onStrChange2 = STATE_MGMT_FACTORY.makeMonitor([{ + path: "message", + valueCallback: ((): NullishType => { + return this.message; + }), + }, { + path: "name", + valueCallback: ((): NullishType => { + return this.name; + }), + }], ((_m: IMonitor) => { + this.onStrChange2(_m); + })); + this.__monitor_onStrChange3 = STATE_MGMT_FACTORY.makeMonitor([{ + path: "name", + valueCallback: ((): NullishType => { + return this.name; + }), + }], ((_m: IMonitor) => { + this.onStrChange3(_m); + })); + } + + public __updateStruct(initializers: (__Options_Index | undefined)): void {} + + private __monitor_onStrChange1: (IMonitorDecoratedVariable | undefined); + + private __monitor_onStrChange2: (IMonitorDecoratedVariable | undefined); + + private __monitor_onStrChange3: (IMonitorDecoratedVariable | undefined); + + private __backing_message?: ILocalDecoratedVariable; + + public get message(): string { + return this.__backing_message!.get(); + } + + public set message(value: string) { + this.__backing_message!.set(value); + } + + private __backing_name?: ILocalDecoratedVariable; + + public get name(): string { + return this.__backing_name!.get(); + } + + public set name(value: string) { + this.__backing_name!.set(value); + } + + private __backing_age?: ILocalDecoratedVariable; + + public get age(): number { + return this.__backing_age!.get(); + } + + public set age(value: number) { + this.__backing_age!.set(value); + } + + @Monitor({value:["message", "name"]}) public onStrChange1(monitor: IMonitor) { + monitor.dirty.forEach(((path: string) => { + console.info(\`\${path} changed from \${({let gensym%%_74 = monitor.value(path); + (((gensym%%_74) == (null)) ? undefined : gensym%%_74.before)})} to \${({let gensym%%_75 = monitor.value(path); + (((gensym%%_75) == (null)) ? undefined : gensym%%_75.now)})}\`); + })); + } + + @Monitor({value:["message", "name"]}) public onStrChange2(monitor: IMonitor) { + monitor.dirty.forEach(((path: string) => { + console.info(\`\${path} changed from \${({let gensym%%_76 = monitor.value(path); + (((gensym%%_76) == (null)) ? undefined : gensym%%_76.before)})} to \${({let gensym%%_77 = monitor.value(path); + (((gensym%%_77) == (null)) ? undefined : gensym%%_77.now)})}\`); + })); + } + + @Monitor({value:["name"]}) public onStrChange3(monitor: IMonitor) { + monitor.dirty.forEach(((path: string) => { + console.info(\`\${path} changed from \${({let gensym%%_78 = monitor.value(path); + (((gensym%%_78) == (null)) ? undefined : gensym%%_78.before)})} to \${({let gensym%%_79 = monitor.value(path); + (((gensym%%_79) == (null)) ? undefined : gensym%%_79.now)})}\`); + })); + } + + @memo() public build() {} + + private constructor() {} + +} + +@ComponentV2() export interface __Options_Index { + set message(message: (string | undefined)) + + get message(): (string | undefined) + set __backing_message(__backing_message: (ILocalDecoratedVariable | undefined)) + + get __backing_message(): (ILocalDecoratedVariable | undefined) + set name(name: (string | undefined)) + + get name(): (string | undefined) + set __backing_name(__backing_name: (ILocalDecoratedVariable | undefined)) + + get __backing_name(): (ILocalDecoratedVariable | undefined) + set age(age: (number | undefined)) + + get age(): (number | undefined) + set __backing_age(__backing_age: (ILocalDecoratedVariable | undefined)) + + get __backing_age(): (ILocalDecoratedVariable | undefined) + +} +`; + +function testParsedAndCheckedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedScript)); +} + +pluginTester.run( + 'test @Monitor method declared before state variables', + [parsedTransform, uiNoRecheck, recheck], + { + 'checked:ui-no-recheck': [testParsedAndCheckedTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/once/once-only.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/once/once-only.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4212ed0b9e0c982989664be2f2b3652cc9ca8653 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/decorators/once/once-only.test.ts @@ -0,0 +1,116 @@ +/* + * 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 OBSERVED_DIR_PATH: string = 'decorators/once'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, OBSERVED_DIR_PATH, 'once-only.ets'), +]; + +const parsedTransform: Plugins = { + name: 'parsedTrans', + parsed: uiTransform().parsed, +} + +const pluginTester = new PluginTester('test only @Once decorated variables transformation', buildConfig); + +const expectedScript: string = ` +import { memo as memo } from "arkui.stateManagement.runtime"; +import { STATE_MGMT_FACTORY as STATE_MGMT_FACTORY } from "arkui.stateManagement.decorator"; +import { IParamOnceDecoratedVariable as IParamOnceDecoratedVariable } from "arkui.stateManagement.decorator"; +import { CustomComponentV2 as CustomComponentV2 } from "arkui.component.customComponent"; +import { ComponentV2 as ComponentV2 } from "@ohos.arkui.component"; +import { Once as Once } from "@ohos.arkui.stateManagement"; + +function main() {} + +@ComponentV2() final struct Child extends CustomComponentV2 { + public __initializeStruct(initializers: (__Options_Child | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_onceParamNum = STATE_MGMT_FACTORY.makeParamOnce(this, "onceParamNum", ((({let gensym___118919021 = initializers; + (((gensym___118919021) == (null)) ? undefined : gensym___118919021.onceParamNum)})) ?? (0))); + this.__backing_onceVar4 = STATE_MGMT_FACTORY.makeParamOnce>(this, "onceVar4", ((({let gensym___71001521 = initializers; + (((gensym___71001521) == (null)) ? undefined : gensym___71001521.onceVar4)})) ?? (new Set(new Array("aa", "bb"))))); + } + + public __updateStruct(initializers: (__Options_Child | undefined)): void {} + + private __backing_onceParamNum?: IParamOnceDecoratedVariable; + + public get onceParamNum(): number { + return this.__backing_onceParamNum!.get(); + } + + public set onceParamNum(value: number) { + this.__backing_onceParamNum!.set(value); + } + + private __backing_onceVar4?: IParamOnceDecoratedVariable>; + + public get onceVar4(): Set { + return this.__backing_onceVar4!.get(); + } + + public set onceVar4(value: Set) { + this.__backing_onceVar4!.set(value); + } + + @memo() public build() {} + + private constructor() {} + +} + +@ComponentV2() export interface __Options_Child { + set onceParamNum(onceParamNum: (number | undefined)) + + get onceParamNum(): (number | undefined) + set __backing_onceParamNum(__backing_onceParamNum: (IParamOnceDecoratedVariable | undefined)) + + get __backing_onceParamNum(): (IParamOnceDecoratedVariable | undefined) + set onceVar4(onceVar4: (Set | undefined)) + + get onceVar4(): (Set | undefined) + set __backing_onceVar4(__backing_onceVar4: (IParamOnceDecoratedVariable> | undefined)) + + get __backing_onceVar4(): (IParamOnceDecoratedVariable> | undefined) + +} +`; + +function testParsedAndCheckedTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedScript)); +} + +pluginTester.run( + 'test only @Once decorated variables transformation', + [parsedTransform, uiNoRecheck, recheck], + { + 'checked:ui-no-recheck': [testParsedAndCheckedTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/once/once-with-require.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/once/once-with-require.test.ts index 98dd8f1286ec7e1b17eb676f87c0e8760139ebd5..dade76adca247401e09905d05e3053683924150c 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/once/once-with-require.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/once/once-with-require.test.ts @@ -92,9 +92,9 @@ import { Param as Param, Once as Once, ObservedV2 as ObservedV2, Trace as Trace, @ComponentV2() export interface __Options_Child { onceParamNum?: number; - @Once() @Param() __backing_onceParamNum?: number; + @Param() @Once() __backing_onceParamNum?: number; onceParamInfo?: Info; - @Once() @Param() __backing_onceParamInfo?: Info; + @Param() @Once() @Require() __backing_onceParamInfo?: Info; } @@ -283,9 +283,9 @@ function main() {} set onceParamInfo(onceParamInfo: (Info | undefined)) get onceParamInfo(): (Info | undefined) - @Param() set __backing_onceParamInfo(__backing_onceParamInfo: (IParamOnceDecoratedVariable | undefined)) + @Param() @Require() set __backing_onceParamInfo(__backing_onceParamInfo: (IParamOnceDecoratedVariable | undefined)) - @Param() get __backing_onceParamInfo(): (IParamOnceDecoratedVariable | undefined) + @Param() @Require() get __backing_onceParamInfo(): (IParamOnceDecoratedVariable | undefined) } diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/param/param-with-require.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/param/param-with-require.test.ts index 5833664982d56b03e2717f0e0a971e72f962c9bc..488decbf21500a31fb40407961d24a77d6b6521f 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/param/param-with-require.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/param/param-with-require.test.ts @@ -131,13 +131,13 @@ class Info { @ComponentV2() export interface __Options_MiddleComponent { info?: Info; - @Param() __backing_info?: Info; + @Require() @Param() __backing_info?: Info; } @ComponentV2() export interface __Options_SubComponent { region?: Region; - @Param() __backing_region?: Region; + @Require() @Param() __backing_region?: Region; } `; @@ -309,9 +309,9 @@ class Info { set info(info: (Info | undefined)) get info(): (Info | undefined) - set __backing_info(__backing_info: (IParamDecoratedVariable | undefined)) + @Require() set __backing_info(__backing_info: (IParamDecoratedVariable | undefined)) - get __backing_info(): (IParamDecoratedVariable | undefined) + @Require() get __backing_info(): (IParamDecoratedVariable | undefined) } @@ -319,9 +319,9 @@ class Info { set region(region: (Region | undefined)) get region(): (Region | undefined) - set __backing_region(__backing_region: (IParamDecoratedVariable | undefined)) + @Require() set __backing_region(__backing_region: (IParamDecoratedVariable | undefined)) - get __backing_region(): (IParamDecoratedVariable | undefined) + @Require() get __backing_region(): (IParamDecoratedVariable | undefined) } `; 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 index 659935b0028cadb56a65258f91ae607ee1f508a7..a4b93ab3eaadedffd491d5e21e3de99c892f8a85 100644 --- 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 @@ -76,24 +76,24 @@ import { State as State, Require as Require, Prop as Prop, Provide as Provide, P @State() __backing_state1?: boolean; select100?: string; select0?: number; - @State() __backing_select0?: number; + @Require() @State() __backing_select0?: number; select3?: (number | null); - @State() __backing_select3?: (number | null); + @Require() @State() __backing_select3?: (number | null); select4?: undefined; - @State() __backing_select4?: undefined; + @Require() @State() __backing_select4?: undefined; select1?: string; - @Prop() __backing_select1?: string; + @Require() @Prop() __backing_select1?: string; select2?: string[]; - @Provide({alias:"15"}) __backing_select2?: string[]; + @Require() @Provide({alias:"15"}) __backing_select2?: string[]; select6?: (string[] | undefined | string); - @Provide({alias:"t"}) __backing_select6?: (string[] | undefined | string); + @Require() @Provide({alias:"t"}) __backing_select6?: (string[] | undefined | string); @BuilderParam() builder?: (()=> void); } @ComponentV2() export interface __Options_V2222 { select1?: string; - @Param() __backing_select1?: string; + @Require() @Param() __backing_select1?: string; } `; @@ -283,39 +283,39 @@ function main() {} set select0(select0: (number | undefined)) get select0(): (number | undefined) - set __backing_select0(__backing_select0: (IStateDecoratedVariable | undefined)) + @Require() set __backing_select0(__backing_select0: (IStateDecoratedVariable | undefined)) - get __backing_select0(): (IStateDecoratedVariable | undefined) + @Require() 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)) + @Require() set __backing_select3(__backing_select3: (IStateDecoratedVariable<(number | null)> | undefined)) - get __backing_select3(): (IStateDecoratedVariable<(number | null)> | undefined) + @Require() get __backing_select3(): (IStateDecoratedVariable<(number | null)> | undefined) set select4(select4: (undefined | undefined)) get select4(): (undefined | undefined) - set __backing_select4(__backing_select4: (IStateDecoratedVariable | undefined)) + @Require() set __backing_select4(__backing_select4: (IStateDecoratedVariable | undefined)) - get __backing_select4(): (IStateDecoratedVariable | undefined) + @Require() get __backing_select4(): (IStateDecoratedVariable | undefined) set select1(select1: (string | undefined)) get select1(): (string | undefined) - set __backing_select1(__backing_select1: (IPropDecoratedVariable | undefined)) + @Require() set __backing_select1(__backing_select1: (IPropDecoratedVariable | undefined)) - get __backing_select1(): (IPropDecoratedVariable | undefined) + @Require() get __backing_select1(): (IPropDecoratedVariable | undefined) set select2(select2: (Array | undefined)) get select2(): (Array | undefined) - set __backing_select2(__backing_select2: (IProvideDecoratedVariable> | undefined)) + @Require() set __backing_select2(__backing_select2: (IProvideDecoratedVariable> | undefined)) - get __backing_select2(): (IProvideDecoratedVariable> | undefined) + @Require() 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)) + @Require() set __backing_select6(__backing_select6: (IProvideDecoratedVariable<(Array | undefined | string)> | undefined)) - get __backing_select6(): (IProvideDecoratedVariable<(Array | undefined | string)> | undefined) + @Require() get __backing_select6(): (IProvideDecoratedVariable<(Array | undefined | string)> | undefined) set builder(builder: (@memo() (()=> void) | undefined)) get builder(): (@memo() (()=> void) | undefined) @@ -326,9 +326,9 @@ function main() {} set select1(select1: (string | undefined)) get select1(): (string | undefined) - set __backing_select1(__backing_select1: (IParamDecoratedVariable | undefined)) + @Require() set __backing_select1(__backing_select1: (IParamDecoratedVariable | undefined)) - get __backing_select1(): (IParamDecoratedVariable | undefined) + @Require() get __backing_select1(): (IParamDecoratedVariable | undefined) } `; diff --git a/arkui-plugins/test/ut/ui-plugins/decorators/watch/watch-basic.test.ts b/arkui-plugins/test/ut/ui-plugins/decorators/watch/watch-basic.test.ts index 5cda30f78d7ee3003f509342463f848a241e0643..115ed67c5292fef9ad4ae8a2da993fbfabc181fe 100644 --- a/arkui-plugins/test/ut/ui-plugins/decorators/watch/watch-basic.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/decorators/watch/watch-basic.test.ts @@ -313,45 +313,45 @@ __EntryWrapper.RegisterNamedRouter("", new __EntryWrapper(), ({ set statevar(statevar: (string | undefined)) get statevar(): (string | undefined) - set __backing_statevar(__backing_statevar: (IStateDecoratedVariable | undefined)) + @Watch({value:"stateOnChange"}) set __backing_statevar(__backing_statevar: (IStateDecoratedVariable | undefined)) - get __backing_statevar(): (IStateDecoratedVariable | undefined) + @Watch({value:"stateOnChange"}) get __backing_statevar(): (IStateDecoratedVariable | undefined) set propvar(propvar: (string | undefined)) get propvar(): (string | undefined) - set __backing_propvar(__backing_propvar: (IPropDecoratedVariable | undefined)) + @Watch({value:"propOnChange"}) set __backing_propvar(__backing_propvar: (IPropDecoratedVariable | undefined)) - get __backing_propvar(): (IPropDecoratedVariable | undefined) + @Watch({value:"propOnChange"}) get __backing_propvar(): (IPropDecoratedVariable | undefined) @__Link_intrinsic() set linkvar(linkvar: (string | undefined)) @__Link_intrinsic() get linkvar(): (string | undefined) - set __backing_linkvar(__backing_linkvar: (LinkSourceType | undefined)) + @Watch({value:"linkOnChange"}) set __backing_linkvar(__backing_linkvar: (LinkSourceType | undefined)) - get __backing_linkvar(): (LinkSourceType | undefined) + @Watch({value:"linkOnChange"}) get __backing_linkvar(): (LinkSourceType | undefined) set storagelinkvar(storagelinkvar: (string | undefined)) get storagelinkvar(): (string | undefined) - set __backing_storagelinkvar(__backing_storagelinkvar: (IStorageLinkDecoratedVariable | undefined)) + @Watch({value:"storageLinkOnChange"}) set __backing_storagelinkvar(__backing_storagelinkvar: (IStorageLinkDecoratedVariable | undefined)) - get __backing_storagelinkvar(): (IStorageLinkDecoratedVariable | undefined) + @Watch({value:"storageLinkOnChange"}) get __backing_storagelinkvar(): (IStorageLinkDecoratedVariable | undefined) set storagepropvar(storagepropvar: (string | undefined)) get storagepropvar(): (string | undefined) - set __backing_storagepropvar(__backing_storagepropvar: (IStoragePropRefDecoratedVariable | undefined)) + @Watch({value:"storagePropOnChange"}) set __backing_storagepropvar(__backing_storagepropvar: (IStoragePropRefDecoratedVariable | undefined)) - get __backing_storagepropvar(): (IStoragePropRefDecoratedVariable | undefined) + @Watch({value:"storagePropOnChange"}) get __backing_storagepropvar(): (IStoragePropRefDecoratedVariable | undefined) set objectlinkvar(objectlinkvar: (A | undefined)) get objectlinkvar(): (A | undefined) - set __backing_objectlinkvar(__backing_objectlinkvar: (IObjectLinkDecoratedVariable | undefined)) + @Watch({value:"objectLinkOnChange"}) set __backing_objectlinkvar(__backing_objectlinkvar: (IObjectLinkDecoratedVariable | undefined)) - get __backing_objectlinkvar(): (IObjectLinkDecoratedVariable | undefined) + @Watch({value:"objectLinkOnChange"}) get __backing_objectlinkvar(): (IObjectLinkDecoratedVariable | undefined) set providevar(providevar: (string | undefined)) get providevar(): (string | undefined) - set __backing_providevar(__backing_providevar: (IProvideDecoratedVariable | undefined)) + @Watch({value:"ProvideOnChange"}) set __backing_providevar(__backing_providevar: (IProvideDecoratedVariable | undefined)) - get __backing_providevar(): (IProvideDecoratedVariable | undefined) + @Watch({value:"ProvideOnChange"}) get __backing_providevar(): (IProvideDecoratedVariable | undefined) } @@ -359,9 +359,9 @@ __EntryWrapper.RegisterNamedRouter("", new __EntryWrapper(), ({ set providevar(providevar: (string | undefined)) get providevar(): (string | undefined) - set __backing_providevar(__backing_providevar: (IConsumeDecoratedVariable | undefined)) + @Watch({value:"ConsumeOnChange"}) set __backing_providevar(__backing_providevar: (IConsumeDecoratedVariable | undefined)) - get __backing_providevar(): (IConsumeDecoratedVariable | undefined) + @Watch({value:"ConsumeOnChange"}) get __backing_providevar(): (IConsumeDecoratedVariable | undefined) } diff --git a/arkui-plugins/ui-plugins/checked-transformer.ts b/arkui-plugins/ui-plugins/checked-transformer.ts index 016dbd524589838a90512847d141c2bef8563d9e..ee4daa33a228c5cbb3d21bb6821ccb5c5f691031 100644 --- a/arkui-plugins/ui-plugins/checked-transformer.ts +++ b/arkui-plugins/ui-plugins/checked-transformer.ts @@ -23,7 +23,7 @@ import { isBuilderLambda, isBuilderLambdaMethodDecl } from './builder-lambda-tra import { isEntryWrapperClass } from './entry-translators/utils'; import { ImportCollector } from '../common/import-collector'; import { DeclarationCollector } from '../common/declaration-collector'; -import { PropertyCache } from './property-translators/utils'; +import { PropertyCache } from './property-translators/cache/propertyCache'; import { LogCollector } from '../common/log-collector'; import { CustomComponentScopeInfo, @@ -45,6 +45,7 @@ import { findAndCollectMemoableNode } from '../collectors/memo-collectors/factor import { InteroperAbilityNames } from './interop/predefines'; import { generateBuilderCompatible } from './interop/builder-interop'; import { builderRewriteByType } from './builder-lambda-translators/builder-factory'; +import { MonitorCache } from './property-translators/cache/monitorCache'; export class CheckedTransformer extends AbstractVisitor { private scope: ScopeInfoCollection; @@ -84,6 +85,7 @@ export class CheckedTransformer extends AbstractVisitor { super.reset(); this.scope = { customComponents: [] }; PropertyCache.getInstance().reset(); + MonitorCache.getInstance().reset(); ImportCollector.getInstance().reset(); DeclarationCollector.getInstance().reset(); LogCollector.getInstance().reset(); diff --git a/arkui-plugins/ui-plugins/component-transformer.ts b/arkui-plugins/ui-plugins/component-transformer.ts index a4c436972cfdb33ca6422c8112069ea3f6e933a7..37db0024f5b3ea6ce69facc144e4fa580015e668 100644 --- a/arkui-plugins/ui-plugins/component-transformer.ts +++ b/arkui-plugins/ui-plugins/component-transformer.ts @@ -462,7 +462,6 @@ export class ComponentTransformer extends AbstractVisitor { originMember.setAnnotations([buildParamInfo.annotation.clone()]); return [originMember]; } - const OnceInfo = infos.find((it) => it.name === DecoratorNames.ONCE); const targetInfo = infos.find((it) => DECORATOR_TYPE_MAP.has(it.name)); if (!!targetInfo) { const newName: string = backingField(originalName); @@ -472,10 +471,7 @@ export class ComponentTransformer extends AbstractVisitor { undefined, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC ); - const annos = !!OnceInfo - ? [OnceInfo.annotation.clone(), targetInfo.annotation.clone()] - : [targetInfo.annotation.clone()]; - newMember.setAnnotations(annos); + newMember.setAnnotations(member.annotations); if (isDecoratorAnnotation(targetInfo.annotation, DecoratorNames.LINK, true)) { this.shouldAddLinkIntrinsic = true; originMember.setAnnotations([annotation(DecoratorIntrinsicNames.LINK)]); diff --git a/arkui-plugins/ui-plugins/property-translators/builderParam.ts b/arkui-plugins/ui-plugins/property-translators/builderParam.ts index b83357cb252fbd0e66258db733e84b917ee89f4f..40b3a54ea1c4d3043f8fb38482805ca38170f3e3 100644 --- a/arkui-plugins/ui-plugins/property-translators/builderParam.ts +++ b/arkui-plugins/ui-plugins/property-translators/builderParam.ts @@ -17,11 +17,12 @@ import * as arkts from '@koalaui/libarkts'; import { backingField, expectName } from '../../common/arkts-utils'; import { DecoratorNames } from '../../common/predefines'; -import { createGetter, createSetter, generateThisBacking, hasDecorator, removeDecorator, PropertyCache } from './utils'; +import { createGetter, createSetter, generateThisBacking, hasDecorator, removeDecorator } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; import { addMemoAnnotation, findCanAddMemoFromTypeAnnotation } from '../../collectors/memo-collectors/utils'; +import { PropertyCache } from './cache/propertyCache'; export class BuilderParamTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/cache/monitorCache.ts b/arkui-plugins/ui-plugins/property-translators/cache/monitorCache.ts new file mode 100644 index 0000000000000000000000000000000000000000..898d2aa21e2add45a3b7ab88d0032b4e637460ab --- /dev/null +++ b/arkui-plugins/ui-plugins/property-translators/cache/monitorCache.ts @@ -0,0 +1,62 @@ +/* + * 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 arkts from '@koalaui/libarkts'; +import { factory } from '../factory'; + +export interface MonitorInfo { + monitorItem: string[] | undefined; + originalName: string; + newName: string; +} + +export class MonitorCache { + private _cache: Map>; + private static instance: MonitorCache | null = null; + + private constructor() { + this._cache = new Map>(); + } + + static getInstance(): MonitorCache { + if (!this.instance) { + this.instance = new MonitorCache(); + } + return this.instance; + } + + reset(): void { + this._cache.clear(); + } + + getCachedMonitors(className: string): arkts.AstNode[] { + if (!this._cache.has(className)) { + return []; + } + return Object.entries(this._cache.get(className)!).map((item: [string, MonitorInfo]) => { + const { monitorItem, originalName, newName } = item[1]; + return factory.generateinitAssignment(monitorItem, originalName, newName); + }); + } + + collectMonitors(className: string, monitorPath: string, info: MonitorInfo): void { + let classCache: Record = {}; + if (this._cache.has(className)) { + classCache = this._cache.get(className)!; + } + classCache[monitorPath] = info; + this._cache.set(className, classCache); + } +} diff --git a/arkui-plugins/ui-plugins/property-translators/cache/propertyCache.ts b/arkui-plugins/ui-plugins/property-translators/cache/propertyCache.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed76775865f04320b32bcf785d054bbec1d1c52c --- /dev/null +++ b/arkui-plugins/ui-plugins/property-translators/cache/propertyCache.ts @@ -0,0 +1,73 @@ +/* + * 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 arkts from '@koalaui/libarkts'; + +export interface PropertyCachedBody { + initializeBody?: arkts.AstNode[]; + updateBody?: arkts.AstNode[]; + toRecordBody?: arkts.Property[]; + constructorBody?: arkts.AstNode[]; + monitorBody?: arkts.AstNode[]; +} + +export class PropertyCache { + private _cache: Map; + private static instance: PropertyCache; + + private constructor() { + this._cache = new Map(); + } + + static getInstance(): PropertyCache { + if (!this.instance) { + this.instance = new PropertyCache(); + } + return this.instance; + } + + reset(): void { + this._cache.clear(); + } + + getInitializeBody(name: string): arkts.AstNode[] { + return this._cache.get(name)?.initializeBody ?? []; + } + + getUpdateBody(name: string): arkts.AstNode[] { + return this._cache.get(name)?.updateBody ?? []; + } + + getToRecordBody(name: string): arkts.Property[] { + return this._cache.get(name)?.toRecordBody ?? []; + } + + collectInitializeStruct(name: string, initializeStruct: arkts.AstNode[]): void { + const initializeBody = this._cache.get(name)?.initializeBody ?? []; + const newInitializeBody = [...initializeBody, ...initializeStruct]; + this._cache.set(name, { ...this._cache.get(name), initializeBody: newInitializeBody }); + } + + collectUpdateStruct(name: string, updateStruct: arkts.AstNode[]): void { + const updateBody = this._cache.get(name)?.updateBody ?? []; + const newUpdateBody = [...updateBody, ...updateStruct]; + this._cache.set(name, { ...this._cache.get(name), updateBody: newUpdateBody }); + } + + collectToRecord(name: string, toRecord: arkts.Property[]): void { + const toRecordBody = this._cache.get(name)?.toRecordBody ?? []; + const newToRecordBody = [...toRecordBody, ...toRecord]; + this._cache.set(name, { ...this._cache.get(name), toRecordBody: newToRecordBody }); + } +} diff --git a/arkui-plugins/ui-plugins/property-translators/consume.ts b/arkui-plugins/ui-plugins/property-translators/consume.ts index 78bda68beab17705a08dd707558c64dad20dfc33..52f38c6fa53ffe1f7668a1aa7d8d67c8d846b4cd 100644 --- a/arkui-plugins/ui-plugins/property-translators/consume.ts +++ b/arkui-plugins/ui-plugins/property-translators/consume.ts @@ -25,11 +25,11 @@ import { generateGetOrSetCall, getValueInAnnotation, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ConsumeTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/consumer.ts b/arkui-plugins/ui-plugins/property-translators/consumer.ts index 239b0e6720ca3830f18fa6889855012ee716228c..ccfb63461aebc739a052439144d73cf48c5aad62 100644 --- a/arkui-plugins/ui-plugins/property-translators/consumer.ts +++ b/arkui-plugins/ui-plugins/property-translators/consumer.ts @@ -24,11 +24,11 @@ import { generateGetOrSetCall, getValueInAnnotation, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ConsumerTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/factory.ts b/arkui-plugins/ui-plugins/property-translators/factory.ts index 17678248bc2bb7643bc74beb76d4b32d15b7351a..ee7dd3895ad3642c2f3e2c7551f14f65e9f29303 100644 --- a/arkui-plugins/ui-plugins/property-translators/factory.ts +++ b/arkui-plugins/ui-plugins/property-translators/factory.ts @@ -808,6 +808,53 @@ export class factory { undefined ); } + + static generateinitAssignment( + monitorItem: string[] | undefined, + originalName: string, + newName: string + ): arkts.ExpressionStatement { + const thisValue: arkts.Expression = generateThisBacking(newName, false, false); + const right: arkts.CallExpression = factory.generateStateMgmtFactoryCall( + StateManagementTypes.MAKE_MONITOR, + undefined, + [this.generatePathArg(monitorItem), this.generateLambdaArg(originalName)], + false + ); + return arkts.factory.createExpressionStatement( + arkts.factory.createAssignmentExpression( + thisValue, + arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION, + right + ) + ); + } + + static generatePathArg(monitorItem: string[] | undefined): arkts.ArrayExpression { + if (!monitorItem || monitorItem.length <= 0) { + return arkts.factory.createArrayExpression([]); + } + const params = monitorItem.map((itemName: string) => { + return factory.createMonitorPathsInfoParameter(itemName); + }); + return arkts.factory.createArrayExpression(params); + } + + static generateLambdaArg(originalName: string): arkts.ArrowFunctionExpression { + return arkts.factory.createArrowFunction( + UIFactory.createScriptFunction({ + params: [UIFactory.createParameterDeclaration(MonitorNames.M_PARAM, MonitorNames.I_MONITOR)], + body: arkts.factory.createBlock([ + arkts.factory.createExpressionStatement( + arkts.factory.createCallExpression(generateThisBacking(originalName), undefined, [ + arkts.factory.createIdentifier(MonitorNames.M_PARAM), + ]) + ), + ]), + flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW, + }) + ); + } static generateMonitorVariable(itemNameSplit: string[]): arkts.Expression { const objectFirst: arkts.Expression = generateThisBacking(itemNameSplit[0]); diff --git a/arkui-plugins/ui-plugins/property-translators/link.ts b/arkui-plugins/ui-plugins/property-translators/link.ts index 1b9b2a259d378d08a97f39baf1660c67668fbafb..35c50150f046a2ecbc597a6285e65285218d4fed 100644 --- a/arkui-plugins/ui-plugins/property-translators/link.ts +++ b/arkui-plugins/ui-plugins/property-translators/link.ts @@ -26,11 +26,11 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class LinkTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/local.ts b/arkui-plugins/ui-plugins/property-translators/local.ts index 8fdd09ba2285d436409f7cc9efb1d96299f6779e..396497217a1c3b11f101cfe37a2fea018ea56111 100644 --- a/arkui-plugins/ui-plugins/property-translators/local.ts +++ b/arkui-plugins/ui-plugins/property-translators/local.ts @@ -24,11 +24,11 @@ import { generateGetOrSetCall, hasDecorator, collectStateManagementTypeImport, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class LocalTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/localStoragePropRef.ts b/arkui-plugins/ui-plugins/property-translators/localStoragePropRef.ts index 6b86afd4a8aec8bac6bf80c9e7256a229a28ff11..85ea5b42494e1d90cf265159fc9b128eb693f0b4 100644 --- a/arkui-plugins/ui-plugins/property-translators/localStoragePropRef.ts +++ b/arkui-plugins/ui-plugins/property-translators/localStoragePropRef.ts @@ -27,10 +27,10 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class LocalStoragePropRefTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/localstoragelink.ts b/arkui-plugins/ui-plugins/property-translators/localstoragelink.ts index 873388948bcba7e52cb73f5ca56251eb50643fc3..e025c5cae66e3a00c06a70184de6b85ddfd2f71b 100755 --- a/arkui-plugins/ui-plugins/property-translators/localstoragelink.ts +++ b/arkui-plugins/ui-plugins/property-translators/localstoragelink.ts @@ -27,10 +27,10 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class LocalStorageLinkTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/localstorageprop.ts b/arkui-plugins/ui-plugins/property-translators/localstorageprop.ts index 9622c3012e04e6bac484e51e7ac0d5b56e63e8f6..7b5840e62f24d9e7e365605ac92fd2656b23ebfb 100644 --- a/arkui-plugins/ui-plugins/property-translators/localstorageprop.ts +++ b/arkui-plugins/ui-plugins/property-translators/localstorageprop.ts @@ -17,10 +17,11 @@ import * as arkts from '@koalaui/libarkts'; import { backingField, expectName } from '../../common/arkts-utils'; import { DecoratorNames, StateManagementTypes } from '../../common/predefines'; -import { collectStateManagementTypeImport, generateToRecord, hasDecorator, PropertyCache } from './utils'; +import { collectStateManagementTypeImport, generateToRecord, hasDecorator } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; function getLocalStorageporpValueStr(node: arkts.AstNode): string | undefined { if (!arkts.isClassProperty(node) || !node.value) return undefined; diff --git a/arkui-plugins/ui-plugins/property-translators/monitor.ts b/arkui-plugins/ui-plugins/property-translators/monitor.ts index 9dffc1ad8586177e7ec7805a3b8304387af5f11f..2070b4fd5f068b66d3ff3531e628fe548ce7c1f7 100644 --- a/arkui-plugins/ui-plugins/property-translators/monitor.ts +++ b/arkui-plugins/ui-plugins/property-translators/monitor.ts @@ -16,13 +16,13 @@ import * as arkts from '@koalaui/libarkts'; import { expectName } from '../../common/arkts-utils'; -import { DecoratorNames, MonitorNames, StateManagementTypes } from '../../common/predefines'; +import { StateManagementTypes } from '../../common/predefines'; import { monitorField } from '../utils'; -import { generateThisBacking, PropertyCache, collectStateManagementTypeImport } from './utils'; +import { collectStateManagementTypeImport, getValueInMonitorAnnotation } from './utils'; import { MethodTranslator } from './base'; import { InitializerConstructor } from './types'; import { factory as UIFactory } from '../ui-factory'; -import { factory } from './factory'; +import { MonitorCache, MonitorInfo } from './cache/monitorCache'; export class MonitorTranslator extends MethodTranslator implements InitializerConstructor { translateMember(): arkts.AstNode[] { @@ -33,12 +33,16 @@ export class MonitorTranslator extends MethodTranslator implements InitializerCo } cacheTranslatedInitializer(newName: string, originalName: string): void { - const monitorAssign: arkts.AstNode = this.generateinitAssignment(newName, originalName); - if (this.classInfo.isFromStruct) { - PropertyCache.getInstance().collectInitializeStruct(this.classInfo.className, [monitorAssign]); - } else { - PropertyCache.getInstance().collectContructor(this.classInfo.className, [monitorAssign]); - } + const monitorItem: string[] | undefined = getValueInMonitorAnnotation( + this.method.scriptFunction.annotations + ); + const monitorPathsStr: string = !!monitorItem ? monitorItem.join(',') : ''; + const monitorInfo: MonitorInfo = { + monitorItem: monitorItem, + originalName: originalName, + newName: newName, + }; + MonitorCache.getInstance().collectMonitors(this.classInfo.className, monitorPathsStr, monitorInfo); } translateWithoutInitializer(newName: string, originalName: string): arkts.AstNode[] { @@ -56,77 +60,4 @@ export class MonitorTranslator extends MethodTranslator implements InitializerCo return [field]; } - - generateinitAssignment(newName: string, originalName: string): arkts.ExpressionStatement { - const monitorItem: string[] | undefined = this.getValueInMonitorAnnotation(); - const thisValue: arkts.Expression = generateThisBacking(newName, false, false); - const right: arkts.CallExpression = factory.generateStateMgmtFactoryCall( - StateManagementTypes.MAKE_MONITOR, - undefined, - [this.generatePathArg(monitorItem), this.generateLambdaArg(originalName)], - false - ); - return arkts.factory.createExpressionStatement( - arkts.factory.createAssignmentExpression( - thisValue, - arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION, - right - ) - ); - } - - generatePathArg(monitorItem: string[] | undefined): arkts.ArrayExpression { - if (!monitorItem || monitorItem.length <= 0) { - return arkts.factory.createArrayExpression([]); - } - const params = monitorItem.map((itemName: string) => { - return factory.createMonitorPathsInfoParameter(itemName); - }); - return arkts.factory.createArrayExpression(params); - } - - generateLambdaArg(originalName: string): arkts.ArrowFunctionExpression { - return arkts.factory.createArrowFunction( - UIFactory.createScriptFunction({ - params: [UIFactory.createParameterDeclaration(MonitorNames.M_PARAM, MonitorNames.I_MONITOR)], - body: arkts.factory.createBlock([ - arkts.factory.createExpressionStatement( - arkts.factory.createCallExpression(generateThisBacking(originalName), undefined, [ - arkts.factory.createIdentifier(MonitorNames.M_PARAM), - ]) - ), - ]), - flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW, - }) - ); - } - - getValueInMonitorAnnotation(): string[] | undefined { - const annotations: readonly arkts.AnnotationUsage[] = this.method.scriptFunction.annotations; - for (let i = 0; i < annotations.length; i++) { - const anno: arkts.AnnotationUsage = annotations[i]; - if ( - anno.expr && - arkts.isIdentifier(anno.expr) && - anno.expr.name === DecoratorNames.MONITOR && - anno.properties.length === 1 - ) { - return this.getArrayFromAnnoProperty(anno.properties[0]); - } - } - return undefined; - } - - getArrayFromAnnoProperty(property: arkts.AstNode): string[] | undefined { - if (arkts.isClassProperty(property) && property.value && arkts.isArrayExpression(property.value)) { - const resArr: string[] = []; - property.value.elements.forEach((item: arkts.Expression) => { - if (arkts.isStringLiteral(item)) { - resArr.push(item.str); - } - }); - return resArr; - } - return undefined; - } } diff --git a/arkui-plugins/ui-plugins/property-translators/objectlink.ts b/arkui-plugins/ui-plugins/property-translators/objectlink.ts index 7d4b23c5f135484de0f948acd420c0eefb718c23..0e5a4b48804878e95b5109abe655d66be0d95e35 100644 --- a/arkui-plugins/ui-plugins/property-translators/objectlink.ts +++ b/arkui-plugins/ui-plugins/property-translators/objectlink.ts @@ -18,17 +18,11 @@ import * as arkts from '@koalaui/libarkts'; import { backingField, expectName } from '../../common/arkts-utils'; import { DecoratorNames, GetSetTypes, StateManagementTypes } from '../../common/predefines'; import { CustomComponentNames } from '../utils'; -import { - createGetter, - generateGetOrSetCall, - generateThisBacking, - generateToRecord, - hasDecorator, - PropertyCache, -} from './utils'; +import { createGetter, generateGetOrSetCall, generateThisBacking, generateToRecord, hasDecorator } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ObjectLinkTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/once.ts b/arkui-plugins/ui-plugins/property-translators/once.ts index 516f0d97fecf9c3c5e2826d9451e6b34eef10874..df0468990e8c9782fd8635a6cc10fd423a21783d 100644 --- a/arkui-plugins/ui-plugins/property-translators/once.ts +++ b/arkui-plugins/ui-plugins/property-translators/once.ts @@ -25,11 +25,11 @@ import { generateGetOrSetCall, hasDecorator, collectStateManagementTypeImport, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class OnceTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/param.ts b/arkui-plugins/ui-plugins/property-translators/param.ts index bc4bd90cff8f08bda591eed09d5e24f4a475040c..95caf467a11ca75b30bf0f353c1254db96b43643 100644 --- a/arkui-plugins/ui-plugins/property-translators/param.ts +++ b/arkui-plugins/ui-plugins/property-translators/param.ts @@ -24,11 +24,11 @@ import { generateGetOrSetCall, hasDecorator, collectStateManagementTypeImport, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ParamTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/prop.ts b/arkui-plugins/ui-plugins/property-translators/prop.ts index b301e38bfe081058caa7174e6bd5ba547b2e879a..f4e6fbcb1038f592abc98f3a3f301b488a9451d4 100644 --- a/arkui-plugins/ui-plugins/property-translators/prop.ts +++ b/arkui-plugins/ui-plugins/property-translators/prop.ts @@ -26,11 +26,11 @@ import { generateThisBacking, generateToRecord, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class PropTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/propRef.ts b/arkui-plugins/ui-plugins/property-translators/propRef.ts index f11de78d795ed63373117bd6ae6f3bd412f8fade..750b1a5d9e3bb559e8b93ffb9172659b895f0a96 100644 --- a/arkui-plugins/ui-plugins/property-translators/propRef.ts +++ b/arkui-plugins/ui-plugins/property-translators/propRef.ts @@ -26,11 +26,11 @@ import { generateThisBacking, collectStateManagementTypeImport, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class PropRefTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/provide.ts b/arkui-plugins/ui-plugins/property-translators/provide.ts index 8531ae4965b1d1c197561daf7f86855cbaa9239c..84a84a4f7c2a08310d7abde697317dd8673f4307 100644 --- a/arkui-plugins/ui-plugins/property-translators/provide.ts +++ b/arkui-plugins/ui-plugins/property-translators/provide.ts @@ -27,11 +27,11 @@ import { getValueInProvideAnnotation, ProvideOptions, hasDecorator, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ProvideTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/provider.ts b/arkui-plugins/ui-plugins/property-translators/provider.ts index f627d3eb79b0a4d72ded68c4082d96c4e5828adc..1b70ff77dc188461c7e46f6cecd9aaa7585a0571 100644 --- a/arkui-plugins/ui-plugins/property-translators/provider.ts +++ b/arkui-plugins/ui-plugins/property-translators/provider.ts @@ -23,12 +23,12 @@ import { generateThisBacking, generateGetOrSetCall, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class ProviderTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/regularProperty.ts b/arkui-plugins/ui-plugins/property-translators/regularProperty.ts index fc6b52845585f3edefebb703f9f1939536acfce9..9cae2857dabee1cf4823c2c1bc143eaa6e1cc497 100644 --- a/arkui-plugins/ui-plugins/property-translators/regularProperty.ts +++ b/arkui-plugins/ui-plugins/property-translators/regularProperty.ts @@ -15,19 +15,13 @@ import * as arkts from '@koalaui/libarkts'; -import { - createGetter, - generateToRecord, - generateThisBacking, - createSetter2, - PropertyCache, - isCustomDialogController, -} from './utils'; +import { createGetter, generateToRecord, generateThisBacking, createSetter2, isCustomDialogController } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { backingField, expectName } from '../../common/arkts-utils'; import { factory } from './factory'; import { CustomComponentNames } from '../utils'; +import { PropertyCache } from './cache/propertyCache'; export class RegularPropertyTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/state.ts b/arkui-plugins/ui-plugins/property-translators/state.ts index e939d4df95fae3b57fb9b6bb57f1ca4c9cc14ead..20df22709c73a8de83689a51bad060c8368cc84c 100644 --- a/arkui-plugins/ui-plugins/property-translators/state.ts +++ b/arkui-plugins/ui-plugins/property-translators/state.ts @@ -26,11 +26,11 @@ import { generateGetOrSetCall, hasDecorator, collectStateManagementTypeImport, - PropertyCache, } from './utils'; import { InterfacePropertyTranslator, InterfacePropertyTypes, PropertyTranslator } from './base'; import { GetterSetter, InitializerConstructor } from './types'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class StateTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { @@ -86,7 +86,7 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo generateInitializeStruct(newName: string, originalName: string): arkts.AstNode { const args: arkts.Expression[] = [ arkts.factory.create1StringLiteral(originalName), - factory.generateInitializeValue(this.property, this.propertyType, originalName) + factory.generateInitializeValue(this.property, this.propertyType, originalName), ]; factory.judgeIfAddWatchFunc(args, this.property); collectStateManagementTypeImport(StateManagementTypes.STATE_DECORATED); diff --git a/arkui-plugins/ui-plugins/property-translators/storageProp.ts b/arkui-plugins/ui-plugins/property-translators/storageProp.ts index 028514266c9cc47a3538f7059c29f2a32fc2751c..1fc9bf304e37e0b62e35e8dd133f07cc9f58a3f0 100644 --- a/arkui-plugins/ui-plugins/property-translators/storageProp.ts +++ b/arkui-plugins/ui-plugins/property-translators/storageProp.ts @@ -27,10 +27,10 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class StoragePropTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/storagePropRef.ts b/arkui-plugins/ui-plugins/property-translators/storagePropRef.ts index b04d0120c3dc96bff7ce5051d532cb371bcc4f71..5887e4341d2a74d25f100b07e3eee959cabbc594 100644 --- a/arkui-plugins/ui-plugins/property-translators/storagePropRef.ts +++ b/arkui-plugins/ui-plugins/property-translators/storagePropRef.ts @@ -27,10 +27,10 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class StoragePropRefTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/storagelink.ts b/arkui-plugins/ui-plugins/property-translators/storagelink.ts index 9abdb3d5ff51378341ed50b2d05a17a74c4a7618..e5bf41efb2a4873fa93e2bc3f7afc64cf17950ae 100644 --- a/arkui-plugins/ui-plugins/property-translators/storagelink.ts +++ b/arkui-plugins/ui-plugins/property-translators/storagelink.ts @@ -27,10 +27,10 @@ import { generateGetOrSetCall, collectStateManagementTypeImport, hasDecorator, - PropertyCache, getValueInAnnotation, } from './utils'; import { factory } from './factory'; +import { PropertyCache } from './cache/propertyCache'; export class StorageLinkTranslator extends PropertyTranslator implements InitializerConstructor, GetterSetter { translateMember(): arkts.AstNode[] { diff --git a/arkui-plugins/ui-plugins/property-translators/utils.ts b/arkui-plugins/ui-plugins/property-translators/utils.ts index 9190b5f059abb6185cdf5bf3b820b611a35f4680..6a7abfbe8b22ab541daf072b7404b524f2e4d772 100644 --- a/arkui-plugins/ui-plugins/property-translators/utils.ts +++ b/arkui-plugins/ui-plugins/property-translators/utils.ts @@ -428,70 +428,30 @@ export function removeImplementProperty(originalName: string): string { return originalName.substring(prefix.length); } -// CACHE -export interface PropertyCachedBody { - initializeBody?: arkts.AstNode[]; - updateBody?: arkts.AstNode[]; - toRecordBody?: arkts.Property[]; - constructorBody?: arkts.AstNode[]; +export function getValueInMonitorAnnotation(annotations: readonly arkts.AnnotationUsage[]): string[] | undefined { + const monitorAnno: arkts.AnnotationUsage | undefined = annotations.find((anno: arkts.AnnotationUsage) => { + return ( + anno.expr && + arkts.isIdentifier(anno.expr) && + anno.expr.name === DecoratorNames.MONITOR && + anno.properties.length === 1 + ); + }); + if (!monitorAnno) { + return undefined; + } + return getArrayFromAnnoProperty(monitorAnno.properties.at(0)!); } -export class PropertyCache { - private _cache: Map; - private static instance: PropertyCache; - - private constructor() { - this._cache = new Map(); +export function getArrayFromAnnoProperty(property: arkts.AstNode): string[] | undefined { + if (!arkts.isClassProperty(property) || !property.value || !arkts.isArrayExpression(property.value)) { + return undefined; } - - static getInstance(): PropertyCache { - if (!this.instance) { - this.instance = new PropertyCache(); + const resArr: string[] = []; + property.value.elements.forEach((item: arkts.Expression) => { + if (arkts.isStringLiteral(item)) { + resArr.push(item.str); } - return this.instance; - } - - reset(): void { - this._cache.clear(); - } - - getInitializeBody(name: string): arkts.AstNode[] { - return this._cache.get(name)?.initializeBody ?? []; - } - - getUpdateBody(name: string): arkts.AstNode[] { - return this._cache.get(name)?.updateBody ?? []; - } - - getToRecordBody(name: string): arkts.Property[] { - return this._cache.get(name)?.toRecordBody ?? []; - } - - getConstructorBody(name: string): arkts.AstNode[] { - return this._cache.get(name)?.constructorBody ?? []; - } - - collectInitializeStruct(name: string, initializeStruct: arkts.AstNode[]): void { - const initializeBody = this._cache.get(name)?.initializeBody ?? []; - const newInitializeBody = [...initializeBody, ...initializeStruct]; - this._cache.set(name, { ...this._cache.get(name), initializeBody: newInitializeBody }); - } - - collectUpdateStruct(name: string, updateStruct: arkts.AstNode[]): void { - const updateBody = this._cache.get(name)?.updateBody ?? []; - const newUpdateBody = [...updateBody, ...updateStruct]; - this._cache.set(name, { ...this._cache.get(name), updateBody: newUpdateBody }); - } - - collectToRecord(name: string, toRecord: arkts.Property[]): void { - const toRecordBody = this._cache.get(name)?.toRecordBody ?? []; - const newToRecordBody = [...toRecordBody, ...toRecord]; - this._cache.set(name, { ...this._cache.get(name), toRecordBody: newToRecordBody }); - } - - collectContructor(name: string, insertedConstructorBody: arkts.AstNode[]): void { - const constructorBody = this._cache.get(name)?.constructorBody ?? []; - const newConstructorBody = [...constructorBody, ...insertedConstructorBody]; - this._cache.set(name, { ...this._cache.get(name), constructorBody: newConstructorBody }); - } + }); + return resArr; } diff --git a/arkui-plugins/ui-plugins/struct-translators/factory.ts b/arkui-plugins/ui-plugins/struct-translators/factory.ts index 7961f0ce9cd9fabb7499d0e41cc3bbe1126769c7..2e41cd8d30f0db3ac89b7c67b775c6fc90f6fe41 100644 --- a/arkui-plugins/ui-plugins/struct-translators/factory.ts +++ b/arkui-plugins/ui-plugins/struct-translators/factory.ts @@ -58,12 +58,7 @@ import { ObservedAnnoInfo, getNoTransformationMembersInClass, } from './utils'; -import { - collectStateManagementTypeImport, - generateThisBacking, - hasDecorator, - PropertyCache, -} from '../property-translators/utils'; +import { collectStateManagementTypeImport, generateThisBacking, hasDecorator } from '../property-translators/utils'; import { ProjectConfig } from '../../common/plugin-context'; import { ImportCollector } from '../../common/import-collector'; import { @@ -86,6 +81,8 @@ import { import { generateArkUICompatible, isArkUICompatible } from '../interop/interop'; import { GenSymGenerator } from '../../common/gensym-generator'; import { MethodTranslator } from 'ui-plugins/property-translators/base'; +import { MonitorCache } from '../property-translators/cache/monitorCache'; +import { PropertyCache } from '../property-translators/cache/propertyCache'; export class factory { /** @@ -110,7 +107,10 @@ export class factory { let modifiers: arkts.Es2pandaModifierFlags = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE; if (!scope.isDecl) { - body = arkts.factory.createBlock(PropertyCache.getInstance().getInitializeBody(scope.name)); + body = arkts.factory.createBlock([ + ...PropertyCache.getInstance().getInitializeBody(scope.name), + ...MonitorCache.getInstance().getCachedMonitors(scope.name), + ]); modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC; } const scriptFunction: arkts.ScriptFunction = arkts.factory @@ -919,13 +919,14 @@ export class factory { ...restMembers, ...classScopeInfo.getters, ]; - return ObservedAnno.isObservedV2 + const isDecl: boolean = arkts.hasModifierFlag(definition, arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE); + return ObservedAnno.isObservedV2 && !isDecl ? returnNodes.concat(this.transformObservedV2Constuctor(definition, classScopeInfo.className)) : returnNodes; } static transformObservedV2Constuctor(definition: arkts.ClassDefinition, className: string): arkts.MethodDefinition { - const addConstructorNodes: arkts.AstNode[] = PropertyCache.getInstance().getConstructorBody(className); + const addConstructorNodes: arkts.AstNode[] = MonitorCache.getInstance().getCachedMonitors(className); let originConstructorMethod: arkts.MethodDefinition | undefined = definition.body.find( (it) => arkts.isMethodDefinition(it) && diff --git a/arkui-plugins/ui-plugins/struct-translators/struct-transformer.ts b/arkui-plugins/ui-plugins/struct-translators/struct-transformer.ts index 3101184cdba3342b645ef30ed3c71c73166d4cfb..722453b7a966f09e1018ec4a2d89d0d09ede4e16 100644 --- a/arkui-plugins/ui-plugins/struct-translators/struct-transformer.ts +++ b/arkui-plugins/ui-plugins/struct-translators/struct-transformer.ts @@ -31,8 +31,8 @@ import { isEntryWrapperClass } from '../entry-translators/utils'; import { factory as entryFactory } from '../entry-translators/factory'; import { ImportCollector } from '../../common/import-collector'; import { DeclarationCollector } from '../../common/declaration-collector'; -import { PropertyCache } from '../property-translators/utils'; import { generateArkUICompatible, isArkUICompatible } from '../interop/interop'; +import { PropertyCache } from '../property-translators/cache/propertyCache'; export class StructTransformer extends AbstractVisitor { private scope: ScopeInfoCollection;