From 9737f7df5e595f84636b5e2d673b72d334a1b636 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Thu, 15 May 2025 12:45:08 +0300 Subject: [PATCH 1/2] A test stub for a memo property on a setter/getter Signed-off-by: Alexander Gorshenev --- ui2abc/memo-plugin/test/test.ets | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ui2abc/memo-plugin/test/test.ets b/ui2abc/memo-plugin/test/test.ets index c2563ba70..731b919bd 100644 --- a/ui2abc/memo-plugin/test/test.ets +++ b/ui2abc/memo-plugin/test/test.ets @@ -206,6 +206,19 @@ declare class AbstractTest { ): @memo () => void } +declare interface Interface { + @memo + property: () => void + + @memo + get withoutField(): () => void + @memo + set withoutField(value: () => void) + + get explicit(): @memo () => void + set explicit(@memo value: () => void) +} + class Use { @memo test() { const test = new Test() -- Gitee From 91cba2005426b6e048e0f7c15a0922d15d9d53f1 Mon Sep 17 00:00:00 2001 From: vadimdolgachev Date: Fri, 16 May 2025 20:58:14 +0700 Subject: [PATCH 2/2] Handling memo for setters/getters --- ui2abc/memo-plugin/src/AnalysisVisitor.ts | 10 +--- ui2abc/memo-plugin/src/FunctionTransformer.ts | 47 ++++++++++++++++++- ui2abc/memo-plugin/src/api-utils.ts | 20 ++++++++ ui2abc/memo-plugin/test/golden/test.ets | 13 +++++ ui2abc/memo-plugin/test/test.ets | 2 +- 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/ui2abc/memo-plugin/src/AnalysisVisitor.ts b/ui2abc/memo-plugin/src/AnalysisVisitor.ts index 46110e99d..657f01695 100644 --- a/ui2abc/memo-plugin/src/AnalysisVisitor.ts +++ b/ui2abc/memo-plugin/src/AnalysisVisitor.ts @@ -15,20 +15,12 @@ import * as arkts from "@koalaui/libarkts" import { getDeclResolveGensym, getMemoFunctionKind, MemoFunctionKind } from "./utils" -import { getParams, isMemoAnnotatable, isMemoizable } from "./api-utils" +import { getParams, isGetter, isMemoAnnotatable, isMemoizable, isSetter } from "./api-utils" class AnalysisVisitorOptions { applyMemo?: MemoFunctionKind } -function isSetter(node: arkts.ScriptFunction) { - return node.flags & arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_SETTER -} - -function isGetter(node: arkts.ScriptFunction) { - return node.flags & arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_GETTER -} - export class AnalysisVisitor extends arkts.AbstractVisitor { // TODO: migrate to wrappers instead of pointers constructor( diff --git a/ui2abc/memo-plugin/src/FunctionTransformer.ts b/ui2abc/memo-plugin/src/FunctionTransformer.ts index ebfa49711..d990cba7e 100644 --- a/ui2abc/memo-plugin/src/FunctionTransformer.ts +++ b/ui2abc/memo-plugin/src/FunctionTransformer.ts @@ -31,13 +31,17 @@ import { ReturnTransformer } from "./ReturnTranformer" import { InternalsTransformer } from "./InternalsTransformer" import { SignatureTransformer } from "./SignatureTransformer" import { + createAnnotation, castParameters, getName, getParams, + isGetter, isMemo, isMemoizable, + isSetter, memoizableHasReceiver, parametersBlockHasReceiver, + removeAnnotation, } from "./api-utils" function needThisRewrite(hasReceiver: boolean, isStatic: boolean, stableThis: boolean) { @@ -298,9 +302,50 @@ export class FunctionTransformer extends arkts.AbstractVisitor { return this.signatureTransformer.visitor(node) } + transformSetGetFunctions(node: arkts.AstNode): arkts.AstNode { + if (arkts.isScriptFunction(node)) { + if (isSetter(node)) { + let isMemoRemoved = false + for (const param of node.params) { + if (arkts.isETSParameterExpression(param) && param.annotations.find(it => it.baseName?.name === "memo")) { + param.setAnnotations(removeAnnotation(param.annotations, "memo")) + isMemoRemoved = true + } + } + if (isMemoRemoved) { + return arkts.factory.updateScriptFunction(node, + node.body, + node.typeParams, + node.params.map(it => it), + node.returnTypeAnnotation, + node.hasReceiver, + node.flags, + node.modifierFlags, + node.id, + [createAnnotation("memo")]) + } + } else if (isGetter(node)) { + if (node.returnTypeAnnotation?.annotations.find(it => it.baseName?.name === "memo")) { + node.returnTypeAnnotation.setAnnotations(removeAnnotation(node.returnTypeAnnotation.annotations, "memo")) + return arkts.factory.updateScriptFunction(node, + node.body, + node.typeParams, + node.params, + node.returnTypeAnnotation, + node.hasReceiver, + node.flags, + node.modifierFlags, + node.id, + [createAnnotation("memo")]) + } + } + } + return node + } + visitor(beforeChildren: arkts.AstNode, options?: FunctionTransformerOptions): arkts.AstNode { this.enter(beforeChildren) - const node = this.visitEachChild(beforeChildren, { + const node = this.visitEachChild(this.transformSetGetFunctions(beforeChildren), { receiverContext: (options?.receiverContext || arkts.isMethodDefinition(beforeChildren)) && !arkts.isScriptFunction(beforeChildren) }) diff --git a/ui2abc/memo-plugin/src/api-utils.ts b/ui2abc/memo-plugin/src/api-utils.ts index 3482e4f8c..fa2a9143a 100644 --- a/ui2abc/memo-plugin/src/api-utils.ts +++ b/ui2abc/memo-plugin/src/api-utils.ts @@ -261,3 +261,23 @@ export function memoizableHasReceiver(node: Memoizable): boolean { } assertIsNever(node) } + +export function isSetter(node: arkts.ScriptFunction) { + return node.flags & arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_SETTER +} + +export function isGetter(node: arkts.ScriptFunction) { + return node.flags & arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_GETTER +} + +export function createAnnotation(name: string): arkts.AnnotationUsage { + const ident: arkts.Identifier = arkts.factory.createIdentifier(name, undefined).setAnnotationUsage() + const annotation: arkts.AnnotationUsage = arkts.factory.createAnnotationUsage(ident, []) + annotation.modifierFlags = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_ANNOTATION_USAGE + ident.parent = annotation + return annotation +} + +export function removeAnnotation(annotations: readonly arkts.AnnotationUsage[], annoName: string): arkts.AnnotationUsage[] { + return annotations.filter((it) => !(it.expr !== undefined && arkts.isIdentifier(it.expr) && it.expr.name === annoName)); +} diff --git a/ui2abc/memo-plugin/test/golden/test.ets b/ui2abc/memo-plugin/test/golden/test.ets index b9a33ee53..cffcd2301 100644 --- a/ui2abc/memo-plugin/test/golden/test.ets +++ b/ui2abc/memo-plugin/test/golden/test.ets @@ -435,6 +435,19 @@ declare class AbstractTest { } +interface Interface { + @memo() abstract set property(property: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)) + + @memo() get property(): ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void) + @memo() set withoutField(value: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)) + + @memo() get withoutField(): ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void) + @memo() set explicit(value: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)) + + @memo() get explicit(): ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void) + +} + class Use { @memo() public test(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { const __memo_scope = __memo_context.scope(((__memo_id) + (__hash("id_test_@test.test.ets"))), 1); diff --git a/ui2abc/memo-plugin/test/test.ets b/ui2abc/memo-plugin/test/test.ets index 731b919bd..fcf7a35c3 100644 --- a/ui2abc/memo-plugin/test/test.ets +++ b/ui2abc/memo-plugin/test/test.ets @@ -245,4 +245,4 @@ interface InterfaceWithSetter { interface InterfaceWithGetter { @memo get f(): () => void -} +} \ No newline at end of file -- Gitee