From 20daf7fc8bc9d9b81a55d66c5e72508f246bce2a Mon Sep 17 00:00:00 2001 From: Cuecuexiaoyu Date: Thu, 31 Jul 2025 20:58:06 +0800 Subject: [PATCH 1/2] fix block in switch case Signed-off-by: Cuecuexiaoyu Change-Id: I19197bbb98fd676b6fe0d7cc62ccaf658d359ad4 --- .../condition-scope/block-in-switch-case.ets | 63 ++++ .../block-in-switch-case.test.ts | 310 ++++++++++++++++++ .../builder-lambda-translators/factory.ts | 15 +- 3 files changed, 380 insertions(+), 8 deletions(-) create mode 100644 arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets create mode 100644 arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts diff --git a/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets b/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets new file mode 100644 index 000000000..965dd4b40 --- /dev/null +++ b/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets @@ -0,0 +1,63 @@ +/* + * 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 { Text, Column, Component } from "@ohos.arkui.component" + +@Component +struct SwitchCase { + num: int = 2; + + build() { + Column() { + switch (this.num) { + case 0: + break; + case 1: + break; + Text('111'); + case 2: + break; + { + Text('111'); + } + case 3: + { + Text('111'); + } + break; + { + Text('111'); + } + case 4: + { + Text('111'); + break; + } + case 5: + { + Text('111'); + } + break; + case 6: + { + break; + } + default: + break; + } + Text('hello world') + } + } +} \ No newline at end of file diff --git a/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts b/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts new file mode 100644 index 000000000..d3a267959 --- /dev/null +++ b/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts @@ -0,0 +1,310 @@ +/* + * 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 { memoNoRecheck, recheck, uiNoRecheck } from '../../../../utils/plugins'; +import { BuildConfig, PluginTestContext } from '../../../../utils/shared-types'; +import { uiTransform } from '../../../../../ui-plugins'; +import { Plugins } from '../../../../../common/plugin-context'; + +const BUILDER_LAMBDA_DIR_PATH: string = 'builder-lambda/condition-scope'; + +const buildConfig: BuildConfig = mockBuildConfig(); +buildConfig.compileFiles = [ + path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, BUILDER_LAMBDA_DIR_PATH, 'block-in-switch-case.ets'), +]; + +const pluginTester = new PluginTester('test block statement in switch case', buildConfig); + +const parsedTransform: Plugins = { + name: 'parsedTrans', + parsed: uiTransform().parsed, +}; + +const expectedUIScript: string = ` +import { ConditionScope as ConditionScope } from "arkui.component.builder"; +import { ConditionBranch as ConditionBranch } from "arkui.component.builder"; +import { memo as memo } from "arkui.stateManagement.runtime"; +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; +import { Text as Text, Column as Column, Component as Component } from "@ohos.arkui.component"; + +function main() {} + +@Component() final struct SwitchCase extends CustomComponent { + public __initializeStruct(initializers: (__Options_SwitchCase | undefined), @memo() content: ((()=> void) | undefined)): void { + this.__backing_num = ((({let gensym___83257243 = initializers; + (((gensym___83257243) == (null)) ? undefined : gensym___83257243.num)})) ?? (2)); + } + + public __updateStruct(initializers: (__Options_SwitchCase | undefined)): void {} + + private __backing_num?: int; + + public get num(): int { + return (this.__backing_num as int); + } + + public set num(value: int) { + this.__backing_num = value; + } + + @memo() public build() { + Column(undefined, undefined, @memo() (() => { + ConditionScope(@memo() (() => { + switch (this.num) { + case 0: { + break; + } + case 1: { + break; + Text(undefined, "111", undefined, undefined); + } + case 2: { + break; + Text(undefined, "111", undefined, undefined); + } + case 3: { + ConditionBranch(@memo() (() => { + { + Text(undefined, "111", undefined, undefined); + } + })); + break; + Text(undefined, "111", undefined, undefined); + } + case 4: { + ConditionBranch(@memo() (() => { + { + Text(undefined, "111", undefined, undefined); + return; + } + })); + } + case 5: { + ConditionBranch(@memo() (() => { + { + Text(undefined, "111", undefined, undefined); + } + })); + break; + } + case 6: { + ConditionBranch(@memo() (() => { + { + return; + } + })); + } + default: { + break; + } + } + })); + Text(undefined, "hello world", undefined, undefined); + })); + } + + private constructor() {} + +} + +@Component() export interface __Options_SwitchCase { + set num(num: (int | undefined)) + + get num(): (int | undefined) + +} +`; + +function testUITransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedUIScript)); +} + +const expectedMemoScript: string = ` +import { __memo_context_type as __memo_context_type, __memo_id_type as __memo_id_type } from "arkui.stateManagement.runtime"; + +import { ConditionScope as ConditionScope } from "arkui.component.builder"; + +import { ConditionBranch as ConditionBranch } from "arkui.component.builder"; + +import { memo as memo } from "arkui.stateManagement.runtime"; + +import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; + +import { Text as Text, Column as Column, Component as Component } from "@ohos.arkui.component"; + +function main() {} + +@Component() final struct SwitchCase extends CustomComponent { + public __initializeStruct(initializers: (__Options_SwitchCase | undefined), @memo() content: (((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void) | undefined)): void { + this.__backing_num = ((({let gensym___83257243 = initializers; + (((gensym___83257243) == (null)) ? undefined : gensym___83257243.num)})) ?? (2)); + } + + public __updateStruct(initializers: (__Options_SwitchCase | undefined)): void {} + + private __backing_num?: int; + + public get num(): int { + return (this.__backing_num as int); + } + + public set num(value: int) { + this.__backing_num = value; + } + + @memo() public build(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { + const __memo_scope = __memo_context.scope(((__memo_id) + (10737008)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + Column(__memo_context, ((__memo_id) + (7513933)), undefined, undefined, @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (235688754)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + ConditionScope(__memo_context, ((__memo_id) + (10971338)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (220324446)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + switch (this.num) { + case 0: { + break; + } + case 1: { + break; + Text(__memo_context, ((__memo_id) + (9185155)), undefined, "111", undefined, undefined); + } + case 2: { + break; + Text(__memo_context, ((__memo_id) + (246501778)), undefined, "111", undefined, undefined); + } + case 3: { + ConditionBranch(__memo_context, ((__memo_id) + (27357263)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (78642435)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + Text(__memo_context, ((__memo_id) + (235279187)), undefined, "111", undefined, undefined); + } + { + __memo_scope.recache(); + return; + } + })); + break; + Text(__memo_context, ((__memo_id) + (222088696)), undefined, "111", undefined, undefined); + } + case 4: { + ConditionBranch(__memo_context, ((__memo_id) + (220977109)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (91459184)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + Text(__memo_context, ((__memo_id) + (241855776)), undefined, "111", undefined, undefined); + return; + } + })); + } + case 5: { + ConditionBranch(__memo_context, ((__memo_id) + (214575380)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (225601197)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + Text(__memo_context, ((__memo_id) + (240873793)), undefined, "111", undefined, undefined); + } + { + __memo_scope.recache(); + return; + } + })); + break; + } + case 6: { + ConditionBranch(__memo_context, ((__memo_id) + (5873742)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (143235624)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + return; + } + })); + } + default: { + break; + } + } + { + __memo_scope.recache(); + return; + } + })); + Text(__memo_context, ((__memo_id) + (72849900)), undefined, "hello world", undefined, undefined); + { + __memo_scope.recache(); + return; + } + })); + { + __memo_scope.recache(); + return; + } + } + + private constructor() {} + +} + +@Component() export interface __Options_SwitchCase { + set num(num: (int | undefined)) + + get num(): (int | undefined) + +} +`; + +function testMemoTransformer(this: PluginTestContext): void { + expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedMemoScript)); +} + +pluginTester.run( + 'test block statement in switch case', + [parsedTransform, uiNoRecheck, memoNoRecheck, recheck], + { + 'checked:ui-no-recheck': [testUITransformer], + 'checked:memo-no-recheck': [testMemoTransformer], + }, + { + stopAfter: 'checked', + } +); diff --git a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts index 7ff48d4bb..8a5a0abec 100644 --- a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts +++ b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts @@ -616,17 +616,13 @@ export class factory { : this.wrapConditionToBlock([newStatement], ConditionNames.CONDITION_SCOPE)) as arkts.AstNode as T; } if (arkts.isSwitchCaseStatement(statement)) { - let { statements, breakIndex } = this.updateConditionBranchInScope( - statement.consequent, - shouldWrap, - stopAtBuilderLambda - ); - if (shouldWrap) { + let { statements, breakIndex } = this.updateConditionBranchInScope(statement.consequent, shouldWrap); + if (shouldWrap && breakIndex > 0) { const beforeBreak = this.wrapConditionToBlock( - breakIndex > 0 ? statements.slice(0, breakIndex) : statements, + statements.slice(0, breakIndex), ConditionNames.CONDITION_BRANCH ); - const afterBreak = breakIndex > 0 ? statements.slice(breakIndex) : []; + const afterBreak = statements.slice(breakIndex); statements = [beforeBreak, ...afterBreak]; } return arkts.factory.updateSwitchCaseStatement(statement, statement.test, statements) as T; @@ -707,6 +703,9 @@ export class factory { ); return arkts.factory.updateBlock(statement, newStatements); } + if (arkts.isBreakStatement(statement) && statement.parent && arkts.isBlockStatement(statement.parent)) { + return arkts.factory.createReturnStatement(); + } return statement; } -- Gitee From 1662f05f4d490d80daf4dade9c5eaaf57f0762dd Mon Sep 17 00:00:00 2001 From: Cuecuexiaoyu Date: Sun, 10 Aug 2025 18:01:25 +0800 Subject: [PATCH 2/2] fix block in switch Signed-off-by: Cuecuexiaoyu Change-Id: Ic6703ad414ce29ea15b66ac8ac8ccd64194c89c4 --- .../condition-scope/block-in-switch-case.ets | 7 +- .../block-in-switch-case.test.ts | 269 +++++++++++++++--- .../cache/conditionBreakCache.ts | 91 ++++++ .../builder-lambda-translators/factory.ts | 23 +- .../builder-lambda-translators/utils.ts | 6 - .../src/arkts-api/factory/nodeFactory.ts | 8 + .../node-utilities/BreakStatement.ts | 27 ++ 7 files changed, 382 insertions(+), 49 deletions(-) create mode 100644 arkui-plugins/ui-plugins/builder-lambda-translators/cache/conditionBreakCache.ts create mode 100644 koala-wrapper/src/arkts-api/node-utilities/BreakStatement.ts diff --git a/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets b/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets index 965dd4b40..77df2cf84 100644 --- a/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets +++ b/arkui-plugins/test/demo/mock/builder-lambda/condition-scope/block-in-switch-case.ets @@ -25,10 +25,8 @@ struct SwitchCase { case 0: break; case 1: - break; Text('111'); case 2: - break; { Text('111'); } @@ -54,6 +52,11 @@ struct SwitchCase { { break; } + case 7: + { + break; + Text('111'); + } default: break; } diff --git a/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts b/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts index d3a267959..0c2b3d7c0 100644 --- a/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/builder-lambda/condition-scope/block-in-switch-case.test.ts @@ -39,9 +39,13 @@ const parsedTransform: Plugins = { }; const expectedUIScript: string = ` +import { ColumnAttribute as ColumnAttribute } from "arkui.component.column"; import { ConditionScope as ConditionScope } from "arkui.component.builder"; import { ConditionBranch as ConditionBranch } from "arkui.component.builder"; import { memo as memo } from "arkui.stateManagement.runtime"; +import { TextAttribute as TextAttribute } from "arkui.component.text"; +import { TextImpl as TextImpl } from "arkui.component.text"; +import { ColumnImpl as ColumnImpl } from "arkui.component.column"; import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; import { Text as Text, Column as Column, Component as Component } from "@ohos.arkui.component"; @@ -66,41 +70,67 @@ function main() {} } @memo() public build() { - Column(undefined, undefined, @memo() (() => { + ColumnImpl(@memo() ((instance: ColumnAttribute): void => { + instance.setColumnOptions(undefined).applyAttributesFinish(); + return; + }), @memo() (() => { ConditionScope(@memo() (() => { switch (this.num) { case 0: { break; } case 1: { - break; - Text(undefined, "111", undefined, undefined); + ConditionBranch(@memo() (() => { + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); + })); } case 2: { - break; - Text(undefined, "111", undefined, undefined); + ConditionBranch(@memo() (() => { + { + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); + } + })); } case 3: { ConditionBranch(@memo() (() => { { - Text(undefined, "111", undefined, undefined); + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); } })); break; - Text(undefined, "111", undefined, undefined); + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); } case 4: { ConditionBranch(@memo() (() => { { - Text(undefined, "111", undefined, undefined); + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); return; } })); + break; } case 5: { ConditionBranch(@memo() (() => { { - Text(undefined, "111", undefined, undefined); + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); } })); break; @@ -111,13 +141,29 @@ function main() {} return; } })); + break; + } + case 7: { + ConditionBranch(@memo() (() => { + { + return; + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("111", undefined).applyAttributesFinish(); + return; + }), undefined); + } + })); + break; } default: { break; } } })); - Text(undefined, "hello world", undefined, undefined); + TextImpl(@memo() ((instance: TextAttribute): void => { + instance.setTextOptions("hello world", undefined).applyAttributesFinish(); + return; + }), undefined); })); } @@ -139,15 +185,14 @@ function testUITransformer(this: PluginTestContext): void { const expectedMemoScript: string = ` import { __memo_context_type as __memo_context_type, __memo_id_type as __memo_id_type } from "arkui.stateManagement.runtime"; - +import { ColumnAttribute as ColumnAttribute } from "arkui.component.column"; import { ConditionScope as ConditionScope } from "arkui.component.builder"; - import { ConditionBranch as ConditionBranch } from "arkui.component.builder"; - import { memo as memo } from "arkui.stateManagement.runtime"; - +import { TextAttribute as TextAttribute } from "arkui.component.text"; +import { TextImpl as TextImpl } from "arkui.component.text"; +import { ColumnImpl as ColumnImpl } from "arkui.component.column"; import { CustomComponent as CustomComponent } from "arkui.component.customComponent"; - import { Text as Text, Column as Column, Component as Component } from "@ohos.arkui.component"; function main() {} @@ -171,19 +216,31 @@ function main() {} } @memo() public build(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { - const __memo_scope = __memo_context.scope(((__memo_id) + (10737008)), 0); + const __memo_scope = __memo_context.scope(((__memo_id) + (261239291)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; } - Column(__memo_context, ((__memo_id) + (7513933)), undefined, undefined, @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (235688754)), 0); + ColumnImpl(__memo_context, ((__memo_id) + (112404751)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: ColumnAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (9185155)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setColumnOptions(undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (147868395)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; } - ConditionScope(__memo_context, ((__memo_id) + (10971338)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (220324446)), 0); + ConditionScope(__memo_context, ((__memo_id) + (186113)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (186336799)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; @@ -193,22 +250,80 @@ function main() {} break; } case 1: { - break; - Text(__memo_context, ((__memo_id) + (9185155)), undefined, "111", undefined, undefined); + ConditionBranch(__memo_context, ((__memo_id) + (27357263)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (78642435)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + TextImpl(__memo_context, ((__memo_id) + (235279187)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (246501778)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); + { + __memo_scope.recache(); + return; + } + })); } case 2: { - break; - Text(__memo_context, ((__memo_id) + (246501778)), undefined, "111", undefined, undefined); + ConditionBranch(__memo_context, ((__memo_id) + (220977109)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (91459184)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + TextImpl(__memo_context, ((__memo_id) + (241855776)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (222088696)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); + } + { + __memo_scope.recache(); + return; + } + })); } case 3: { - ConditionBranch(__memo_context, ((__memo_id) + (27357263)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (78642435)), 0); + ConditionBranch(__memo_context, ((__memo_id) + (143235624)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (214575380)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; } { - Text(__memo_context, ((__memo_id) + (235279187)), undefined, "111", undefined, undefined); + TextImpl(__memo_context, ((__memo_id) + (225601197)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (240873793)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); } { __memo_scope.recache(); @@ -216,30 +331,67 @@ function main() {} } })); break; - Text(__memo_context, ((__memo_id) + (222088696)), undefined, "111", undefined, undefined); + TextImpl(__memo_context, ((__memo_id) + (220324446)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (5873742)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); } case 4: { - ConditionBranch(__memo_context, ((__memo_id) + (220977109)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (91459184)), 0); + ConditionBranch(__memo_context, ((__memo_id) + (7513933)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (235688754)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; } { - Text(__memo_context, ((__memo_id) + (241855776)), undefined, "111", undefined, undefined); + TextImpl(__memo_context, ((__memo_id) + (72849900)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (10971338)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); return; } })); + break; } case 5: { - ConditionBranch(__memo_context, ((__memo_id) + (214575380)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (225601197)), 0); + ConditionBranch(__memo_context, ((__memo_id) + (58475451)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (257250368)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; } { - Text(__memo_context, ((__memo_id) + (240873793)), undefined, "111", undefined, undefined); + TextImpl(__memo_context, ((__memo_id) + (264582197)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (138238536)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); } { __memo_scope.recache(); @@ -249,8 +401,8 @@ function main() {} break; } case 6: { - ConditionBranch(__memo_context, ((__memo_id) + (5873742)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { - const __memo_scope = __memo_context.scope(((__memo_id) + (143235624)), 0); + ConditionBranch(__memo_context, ((__memo_id) + (60292460)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (21099142)), 0); if (__memo_scope.unchanged) { __memo_scope.cached; return; @@ -259,6 +411,37 @@ function main() {} return; } })); + break; + } + case 7: { + ConditionBranch(__memo_context, ((__memo_id) + (34940192)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type) => { + const __memo_scope = __memo_context.scope(((__memo_id) + (15961624)), 0); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + { + return; + TextImpl(__memo_context, ((__memo_id) + (123392926)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (181839521)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("111", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); + } + { + __memo_scope.recache(); + return; + } + })); + break; } default: { break; @@ -269,7 +452,19 @@ function main() {} return; } })); - Text(__memo_context, ((__memo_id) + (72849900)), undefined, "hello world", undefined, undefined); + TextImpl(__memo_context, ((__memo_id) + (262734369)), @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type, instance: TextAttribute): void => { + const __memo_scope = __memo_context.scope(((__memo_id) + (229820618)), 1); + const __memo_parameter_instance = __memo_scope.param(0, instance); + if (__memo_scope.unchanged) { + __memo_scope.cached; + return; + } + __memo_parameter_instance.value.setTextOptions("hello world", undefined).applyAttributesFinish(); + { + __memo_scope.recache(); + return; + } + }), undefined); { __memo_scope.recache(); return; diff --git a/arkui-plugins/ui-plugins/builder-lambda-translators/cache/conditionBreakCache.ts b/arkui-plugins/ui-plugins/builder-lambda-translators/cache/conditionBreakCache.ts new file mode 100644 index 000000000..693053ba8 --- /dev/null +++ b/arkui-plugins/ui-plugins/builder-lambda-translators/cache/conditionBreakCache.ts @@ -0,0 +1,91 @@ +/* + * 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 class ConditionBreakCache { + private _shouldBreak: boolean; + private _shouldReturn: boolean; + private _shouldContinue: boolean; + private static instance: ConditionBreakCache | null = null; + + private constructor() { + this._shouldBreak = false; + this._shouldReturn = false; + this._shouldContinue = false; + } + + static getInstance(): ConditionBreakCache { + if (!this.instance) { + this.instance = new ConditionBreakCache(); + } + return this.instance; + } + + get shouldBreak(): boolean { + return this._shouldBreak; + } + + get shouldReturn(): boolean { + return this._shouldReturn; + } + + get shouldContinue(): boolean { + return this._shouldContinue; + } + + collectBreak(): void { + if (this._shouldBreak) { + return; + } + this._shouldBreak = true; + } + + collectReturn(): void { + if (this._shouldReturn) { + return; + } + this._shouldReturn = true; + } + + collectContinue(): void { + if (this._shouldContinue) { + return; + } + this._shouldContinue = true; + } + + collect(st: arkts.AstNode): boolean { + if (arkts.isBreakStatement(st)) { + this.collectBreak(); + return true; + } + if (arkts.isReturnStatement(st)) { + this.collectReturn(); + return true; + } + if (arkts.isContinueStatement(st)) { + this.collectContinue(); + return true; + } + return false; + } + + reset(): void { + this._shouldBreak = false; + this._shouldReturn = false; + this._shouldContinue = false; + } +} diff --git a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts index 8a5a0abec..9b2e6609c 100644 --- a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts +++ b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts @@ -42,7 +42,6 @@ import { builderLambdaType, BuilderLambdaSecondLastArgInfo, buildSecondLastArgInfo, - checkShouldBreakFromStatement, checkIsWithInIfConditionScope, BuilderLambdaConditionBranchInfo, BuilderLambdaChainingCallArgInfo, @@ -76,6 +75,7 @@ import { import { TypeRecord } from '../../collectors/utils/collect-types'; import { BuilderFactory } from './builder-factory'; import { StyleInternalsVisitor } from './style-internals-visitor'; +import { ConditionBreakCache } from './cache/conditionBreakCache'; export class factory { /** @@ -618,18 +618,32 @@ export class factory { if (arkts.isSwitchCaseStatement(statement)) { let { statements, breakIndex } = this.updateConditionBranchInScope(statement.consequent, shouldWrap); if (shouldWrap && breakIndex > 0) { + const hasBreak = breakIndex !== statements.length; const beforeBreak = this.wrapConditionToBlock( statements.slice(0, breakIndex), ConditionNames.CONDITION_BRANCH ); - const afterBreak = statements.slice(breakIndex); - statements = [beforeBreak, ...afterBreak]; + const afterBreak = statements.slice(hasBreak ? breakIndex + 1 : breakIndex); + const breakStatement = this.createBreakBetweenConditionStatements(); + statements = [beforeBreak, ...breakStatement, ...afterBreak]; } + ConditionBreakCache.getInstance().reset(); return arkts.factory.updateSwitchCaseStatement(statement, statement.test, statements) as T; } return statement; } + static createBreakBetweenConditionStatements(): arkts.AstNode[] { + const cache = ConditionBreakCache.getInstance(); + if (cache.shouldBreak) { + return [arkts.factory.createBreakStatement()]; + } + if (cache.shouldReturn) { + return [arkts.factory.createReturnStatement()]; + } + return []; + } + /** * update ConditionBranch in an if-else or swith-case body. * @internal @@ -641,7 +655,7 @@ export class factory { ): BuilderLambdaConditionBranchInfo { let breakIndex = statements.length; const newStatements = statements.map((st, index) => { - if (checkShouldBreakFromStatement(st)) { + if (ConditionBreakCache.getInstance().collect(st)) { breakIndex = index; } return this.updateContentBodyInBuilderLambda(st, shouldWrap, stopAtBuilderLambda); @@ -704,6 +718,7 @@ export class factory { return arkts.factory.updateBlock(statement, newStatements); } if (arkts.isBreakStatement(statement) && statement.parent && arkts.isBlockStatement(statement.parent)) { + ConditionBreakCache.getInstance().collectBreak(); return arkts.factory.createReturnStatement(); } return statement; diff --git a/arkui-plugins/ui-plugins/builder-lambda-translators/utils.ts b/arkui-plugins/ui-plugins/builder-lambda-translators/utils.ts index 04ba680ca..e38cd83d3 100644 --- a/arkui-plugins/ui-plugins/builder-lambda-translators/utils.ts +++ b/arkui-plugins/ui-plugins/builder-lambda-translators/utils.ts @@ -565,12 +565,6 @@ export function checkIsWithInIfConditionScope(statement: arkts.AstNode): boolean return false; } -export function checkShouldBreakFromStatement(statement: arkts.AstNode): boolean { - return ( - arkts.isReturnStatement(statement) || arkts.isBreakStatement(statement) || arkts.isContinueStatement(statement) - ); -} - /** * check whether the last parameter is trailing lambda in components. */ diff --git a/koala-wrapper/src/arkts-api/factory/nodeFactory.ts b/koala-wrapper/src/arkts-api/factory/nodeFactory.ts index 844384d34..e07d61b0e 100644 --- a/koala-wrapper/src/arkts-api/factory/nodeFactory.ts +++ b/koala-wrapper/src/arkts-api/factory/nodeFactory.ts @@ -86,6 +86,7 @@ import { ETSNullType, TSThisType, TSQualifiedName, + BreakStatement, } from '../../generated'; import { updateIdentifier } from '../node-utilities/Identifier'; import { updateCallExpression } from '../node-utilities/CallExpression'; @@ -152,6 +153,7 @@ import { updateTSArrayType } from '../node-utilities/TSArrayType'; import { updateETSNullType } from '../node-utilities/ETSNullType'; import { updateTSThisType } from '../node-utilities/TSThisType'; import { updateTSQualifiedName } from '../node-utilities/TSQualifiedName'; +import { updateBreakStatement } from '../node-utilities/BreakStatement'; export const factory = { get createIdentifier(): (...args: Parameters) => Identifier { @@ -657,6 +659,12 @@ export const factory = { get updateTSQualifiedName(): (...args: Parameters) => TSQualifiedName { return updateTSQualifiedName; }, + get createBreakStatement(): (...args: Parameters) => BreakStatement { + return BreakStatement.createBreakStatement; + }, + get updateBreakStatement(): (...args: Parameters) => BreakStatement { + return updateBreakStatement; + }, /** @deprecated */ createTypeParameter1_(name: Identifier, constraint?: TypeNode, defaultType?: TypeNode) { return TSTypeParameter.createTSTypeParameter(Identifier.create1Identifier(name.name), constraint, defaultType); diff --git a/koala-wrapper/src/arkts-api/node-utilities/BreakStatement.ts b/koala-wrapper/src/arkts-api/node-utilities/BreakStatement.ts new file mode 100644 index 000000000..03ed1b141 --- /dev/null +++ b/koala-wrapper/src/arkts-api/node-utilities/BreakStatement.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 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 { BreakStatement } from '../../generated'; +import { NodeCache } from '../utilities/nodeCache'; +import { attachModifiers, updateThenAttach } from '../utilities/private'; + +export function updateBreakStatement(original: BreakStatement): BreakStatement { + const update = updateThenAttach(BreakStatement.updateBreakStatement, attachModifiers); + const newNode = update(original); + if (NodeCache.getInstance().has(original)) { + NodeCache.getInstance().refresh(original, newNode); + } + return newNode; +} -- Gitee