1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import * as path from 'path'; 17import { PluginTestContext, PluginTester } from '../../../utils/plugin-tester'; 18import { BuildConfig, mockBuildConfig } from '../../../utils/artkts-config'; 19import { getRootPath, MOCK_ENTRY_DIR_PATH } from '../../../utils/path-config'; 20import { parseDumpSrc } from '../../../utils/parse-string'; 21import { memoNoRecheck } from '../../../utils/plugins'; 22 23const METHOD_DIR_PATH: string = 'memo/methods'; 24 25const buildConfig: BuildConfig = mockBuildConfig(); 26buildConfig.compileFiles = [path.resolve(getRootPath(), MOCK_ENTRY_DIR_PATH, METHOD_DIR_PATH, 'callable.ets')]; 27 28const pluginTester = new PluginTester('test memo method', buildConfig); 29 30const expectedScript: string = ` 31import { memo as memo, __memo_context_type as __memo_context_type, __memo_id_type as __memo_id_type } from \"@ohos.arkui.stateManagement\"; 32function main() {} 33@memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type): void => { 34 const __memo_scope = __memo_context.scope<void>(((__memo_id) + (<some_random_number>)), 0); 35 if (__memo_scope.unchanged) { 36 __memo_scope.cached; 37 return; 38 } 39 A.$_invoke(__memo_context, ((__memo_id) + (<some_random_number>))); 40 B.$_invoke(((__memo_context: __memo_context_type, __memo_id: __memo_id_type): void => { 41 const __memo_scope = __memo_context.scope<void>(((__memo_id) + (<some_random_number>)), 0); 42 if (__memo_scope.unchanged) { 43 __memo_scope.cached; 44 return; 45 } 46 { 47 __memo_scope.recache(); 48 return; 49 } 50 })); 51 let x: C | D = C.$_instantiate(__memo_context, ((__memo_id) + (<some_random_number>)), (() => { 52 return new C(); 53 })); 54 x = D.$_instantiate((() => { 55 return new D(); 56 })); 57 { 58 __memo_scope.recache(); 59 return; 60 } 61}); 62class A { 63 public static $_invoke(__memo_context: __memo_context_type, __memo_id: __memo_id_type): void { 64 const __memo_scope = __memo_context.scope<void>(((__memo_id) + (<some_random_number>)), 0); 65 if (__memo_scope.unchanged) { 66 __memo_scope.cached; 67 return; 68 } 69 { 70 __memo_scope.recache(); 71 return; 72 } 73 } 74 public constructor() {} 75} 76class B { 77 @functions.OptionalParametersAnnotation({minArgCount:0}) public static $_invoke(@memo() p?: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)): void {} 78 public constructor() {} 79} 80class C { 81 public static $_instantiate(__memo_context: __memo_context_type, __memo_id: __memo_id_type, factory: (()=> C)): C { 82 const __memo_scope = __memo_context.scope<C>(((__memo_id) + (<some_random_number>)), 1); 83 const __memo_parameter_factory = __memo_scope.param(0, factory); 84 if (__memo_scope.unchanged) { 85 return __memo_scope.cached; 86 } 87 return __memo_scope.recache(__memo_parameter_factory.value()); 88 } 89 public constructor() {} 90} 91class D { 92 @functions.OptionalParametersAnnotation({minArgCount:1}) public static $_instantiate(factory: (()=> D), @memo() content?: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)): D { 93 return factory(); 94 } 95 public constructor() {} 96} 97`; 98 99function testMemoTransformer(this: PluginTestContext): void { 100 expect(parseDumpSrc(this.scriptSnapshot ?? '')).toBe(parseDumpSrc(expectedScript)); 101} 102 103pluginTester.run( 104 'transform callable class', 105 [memoNoRecheck], 106 { 107 'checked:memo-no-recheck': [testMemoTransformer], 108 }, 109 { 110 stopAfter: 'checked', 111 } 112); 113