From 74b1cea209d6367faa1274eb121e2ebcf0247324 Mon Sep 17 00:00:00 2001 From: VictorS67 Date: Wed, 9 Jul 2025 00:01:02 +0800 Subject: [PATCH] sync code Signed-off-by: VictorS67 Change-Id: Ie0494a07c2bd94e52f9f194c7cfad331bb36ed42 --- .../memo-plugins/function-transformer.ts | 2 +- arkui-plugins/memo-plugins/memo-factory.ts | 38 ++++--- .../memo-plugins/parameter-transformer.ts | 5 +- arkui-plugins/memo-plugins/utils.ts | 98 ++++++++++++++++--- 4 files changed, 114 insertions(+), 29 deletions(-) diff --git a/arkui-plugins/memo-plugins/function-transformer.ts b/arkui-plugins/memo-plugins/function-transformer.ts index 68bc9083d..4512ba637 100644 --- a/arkui-plugins/memo-plugins/function-transformer.ts +++ b/arkui-plugins/memo-plugins/function-transformer.ts @@ -48,7 +48,7 @@ import { isStandaloneArrowFunction, isThisAttributeAssignment, removeMemoAnnotation, - parametrizedNodeHasReceiver + parametrizedNodeHasReceiver, } from './utils'; import { ParameterTransformer } from './parameter-transformer'; import { ReturnTransformer } from './return-transformer'; diff --git a/arkui-plugins/memo-plugins/memo-factory.ts b/arkui-plugins/memo-plugins/memo-factory.ts index dac886843..a9d43b591 100644 --- a/arkui-plugins/memo-plugins/memo-factory.ts +++ b/arkui-plugins/memo-plugins/memo-factory.ts @@ -17,12 +17,12 @@ import * as arkts from '@koalaui/libarkts'; import { fixGensymParams, buildeParamInfos, - isUnmemoizedInFunction, + isUnmemoizedInFunctionParams, mayAddLastReturn, ParamInfo, ReturnTypeInfo, RuntimeNames, - parametrizedNodeHasReceiver + parametrizedNodeHasReceiver, } from './utils'; import { moveToFront } from '../common/arkts-utils'; @@ -40,7 +40,6 @@ export class factory { arkts.factory.createIdentifier(RuntimeNames.ID_TYPE) ); } - static createContextTypesImportDeclaration(program?: arkts.Program): void { const source: arkts.StringLiteral = arkts.factory.createStringLiteral(RuntimeNames.MEMO_IMPORT_NAME); const importDecl: arkts.ETSImportDeclaration = arkts.factory.createImportDeclaration( @@ -89,7 +88,7 @@ export class factory { hasReceiver: boolean = false ): readonly arkts.Expression[] { const _params = params ?? []; - if (isUnmemoizedInFunction(_params)) { + if (isUnmemoizedInFunctionParams(_params)) { return _params; } let newParams: arkts.Expression[] = [...factory.createHiddenParameters(), ..._params]; @@ -98,12 +97,15 @@ export class factory { } return newParams; } - static updateFunctionTypeWithMemoParameters(type: arkts.ETSFunctionType): arkts.ETSFunctionType { + static updateFunctionTypeWithMemoParameters( + type: arkts.ETSFunctionType, + hasReceiver: boolean = false + ): arkts.ETSFunctionType { return arkts.factory.updateFunctionType( type, arkts.factory.createFunctionSignature( undefined, - factory.createHiddenParameterIfNotAdded(type.params), + factory.createHiddenParameterIfNotAdded(type.params, hasReceiver), type.returnType, false ), @@ -299,6 +301,18 @@ export class factory { returnStatement ); } + static createWrappedReturnStatement( + argument: arkts.Expression, + isReturnVoid: boolean + ): arkts.ReturnStatement | arkts.BlockStatement { + if (!isReturnVoid) { + return arkts.factory.createReturnStatement(argument); + } + return arkts.factory.createBlock([ + arkts.factory.createExpressionStatement(argument), + arkts.factory.createReturnStatement(), + ]); + } // Compute static createLambdaWrapper(node: arkts.Expression): arkts.ArrowFunctionExpression { @@ -390,11 +404,13 @@ export class factory { static insertHiddenArgumentsToCall( node: arkts.CallExpression, - hash: arkts.NumberLiteral | arkts.StringLiteral + hash: arkts.NumberLiteral | arkts.StringLiteral, + hasReceiver?: boolean ): arkts.CallExpression { - return arkts.factory.updateCallExpression(node, node.expression, node.typeArguments, [ - ...factory.createHiddenArguments(hash), - ...node.arguments, - ]); + let updatedArguments = [...factory.createHiddenArguments(hash), ...node.arguments]; + if (!!hasReceiver) { + updatedArguments = moveToFront(updatedArguments, 2); + } + return arkts.factory.updateCallExpression(node, node.expression, node.typeArguments, updatedArguments); } } diff --git a/arkui-plugins/memo-plugins/parameter-transformer.ts b/arkui-plugins/memo-plugins/parameter-transformer.ts index 061e5b80b..8aef0822c 100644 --- a/arkui-plugins/memo-plugins/parameter-transformer.ts +++ b/arkui-plugins/memo-plugins/parameter-transformer.ts @@ -22,8 +22,7 @@ import { findReturnTypeFromTypeAnnotation, isMemoETSParameterExpression, isMemoParametersDeclaration, - isUnmemoizedInFunction, - isVoidType, + isUnmemoizedInFunctionParams, MemoInfo, ParamInfo, PositionalIdTracker, @@ -140,7 +139,7 @@ export class ParameterTransformer extends AbstractVisitor { if (!scriptFunction.body || !arkts.isBlockStatement(scriptFunction.body)) { return initializer; } - if (isUnmemoizedInFunction(scriptFunction.params)) { + if (isUnmemoizedInFunctionParams(scriptFunction.params)) { return initializer; } const returnTypeInfo: ReturnTypeInfo = buildReturnTypeInfo( diff --git a/arkui-plugins/memo-plugins/utils.ts b/arkui-plugins/memo-plugins/utils.ts index fea2bffad..e3b415e7f 100644 --- a/arkui-plugins/memo-plugins/utils.ts +++ b/arkui-plugins/memo-plugins/utils.ts @@ -21,6 +21,7 @@ export enum RuntimeNames { __CONTEXT = '__context', __ID = '__id', __KEY = '__key', + ANNOTATION_BUILDER = 'Builder', ANNOTATION = 'memo', ANNOTATION_ENTRY = 'memo_entry', ANNOTATION_INTRINSIC = 'memo_intrinsic', @@ -42,7 +43,7 @@ export enum RuntimeNames { SCOPE = '__memo_scope', THIS = 'this', VALUE = 'value', - EQUAL_T = '=t' + EQUAL_T = '=t', } export interface ReturnTypeInfo { @@ -70,6 +71,15 @@ export class PositionalIdTracker { // Global for the whole program. static callCount: number = 0; + private static instance: PositionalIdTracker; + + static getInstance(fileName: string): PositionalIdTracker { + if (!this.instance) { + this.instance = new PositionalIdTracker(fileName); + } + return this.instance; + } + // Set `stable` to true if you want to have more predictable values. // For example for tests. // Don't use it in production! @@ -116,7 +126,9 @@ export type MemoAstNode = | arkts.VariableDeclaration; export function hasMemoAnnotation(node: T): boolean { - return node.annotations.some((it) => isMemoAnnotation(it, RuntimeNames.ANNOTATION)); + return node.annotations.some( + (it) => isMemoAnnotation(it, RuntimeNames.ANNOTATION) || isMemoAnnotation(it, RuntimeNames.ANNOTATION_BUILDER) + ); } export function hasMemoIntrinsicAnnotation(node: T): boolean { @@ -452,7 +464,7 @@ export function findMemoFromTypeAnnotation(typeAnnotation: arkts.AstNode | undef if (arkts.isETSTypeReference(typeAnnotation) && !!typeAnnotation.part && !!typeAnnotation.part.name) { let decl: arkts.AstNode | undefined = arkts.getDecl(typeAnnotation.part.name); if (!decl || !arkts.isTSTypeAliasDeclaration(decl)) { - return false; + return false; } let isMemo: boolean = hasMemoAnnotation(decl) || hasMemoIntrinsicAnnotation(decl); if (!isMemo && !!decl.typeAnnotation) { @@ -491,6 +503,21 @@ export function findReturnTypeFromTypeAnnotation( return undefined; } +export function findLocalReturnTypeFromTypeAnnotation( + typeAnnotation: arkts.AstNode | undefined +): arkts.TypeNode | undefined { + if (!typeAnnotation) { + return undefined; + } + if (arkts.isETSFunctionType(typeAnnotation)) { + return typeAnnotation.returnType; + } + if (arkts.isETSUnionType(typeAnnotation)) { + return typeAnnotation.types.find((type) => arkts.isETSFunctionType(type))?.returnType; + } + return undefined; +} + export function getDeclResolveAlias(node: arkts.AstNode): arkts.AstNode | undefined { const decl = arkts.getDecl(node); if (!!decl && !!decl.parent && arkts.isIdentifier(decl) && arkts.isVariableDeclarator(decl.parent)) { @@ -505,11 +532,17 @@ export function getDeclResolveAlias(node: arkts.AstNode): arkts.AstNode | undefi } export function mayAddLastReturn(node: arkts.BlockStatement): boolean { - return ( - node.statements.length === 0 || - (!arkts.isReturnStatement(node.statements[node.statements.length - 1]) && - !arkts.isThrowStatement(node.statements[node.statements.length - 1])) - ); + if (node.statements.length === 0) { + return true; + } + const lastStatement = node.statements[node.statements.length - 1]; + if (arkts.isBlockStatement(lastStatement)) { + return mayAddLastReturn(lastStatement); + } + if (arkts.isReturnStatement(lastStatement) || arkts.isThrowStatement(lastStatement)) { + return false; + } + return true; } export function fixGensymParams(params: ParamInfo[], body: arkts.BlockStatement): number { @@ -533,16 +566,49 @@ export function fixGensymParams(params: ParamInfo[], body: arkts.BlockStatement) return gensymParamsCount; } -export function isUnmemoizedInFunction(params?: readonly arkts.Expression[]): boolean { +export function isMemoContextParamAdded(param: arkts.Expression): boolean { + return arkts.isEtsParameterExpression(param) && param.identifier.name === RuntimeNames.CONTEXT; +} + +export function isMemoIdParamAdded(param: arkts.Expression): boolean { + return arkts.isEtsParameterExpression(param) && param.identifier.name === RuntimeNames.ID; +} + +export function isUnmemoizedInFunctionParams(params?: readonly arkts.Expression[], hasReceiver?: boolean): boolean { const _params = params ?? []; - const first = _params.at(0); - const isContextAdded = - !!first && arkts.isEtsParameterExpression(first) && first.identifier.name === RuntimeNames.CONTEXT; - const second = _params.at(1); - const isIdAdded = !!second && arkts.isEtsParameterExpression(second) && second.identifier.name === RuntimeNames.ID; + const startIndex = hasReceiver ? 1 : 0; + const isContextAdded = !!_params.at(startIndex) && isMemoContextParamAdded(_params.at(startIndex)!); + const isIdAdded = !!_params.at(startIndex + 1) && isMemoIdParamAdded(_params.at(startIndex + 1)!); return isContextAdded && isIdAdded; } +export function getFunctionParamsBeforeUnmemoized( + params?: readonly arkts.Expression[], + hasReceiver?: boolean +): readonly arkts.Expression[] { + const _params = params ?? []; + if (isUnmemoizedInFunctionParams(_params, hasReceiver)) { + if (!!hasReceiver) { + return [_params.at(0)!, ..._params.slice(3)]; + } + return _params.slice(2); + } + return _params; +} + +export function findUnmemoizedScopeInFunctionBody(body: arkts.BlockStatement, gensymCount: number = 0): boolean { + const startIndex = gensymCount; + if (body.statements.length < startIndex + 1) { + return false; + } + const statement = body.statements.at(startIndex)!; + if (!arkts.isVariableDeclaration(statement)) { + return false; + } + const declarator = statement.declarators.at(0)!; + return declarator.name.name === RuntimeNames.SCOPE; +} + export function buildReturnTypeInfo( returnType: arkts.TypeNode | undefined, isMemo?: boolean, @@ -586,3 +652,7 @@ function isThisParam(node: arkts.Expression | undefined): boolean { } return node.identifier?.isReceiver ?? false; } + +export function filterMemoSkipParams(params: readonly arkts.Expression[]): readonly arkts.Expression[] { + return params.filter((p) => !hasMemoSkipAnnotation(p as arkts.ETSParameterExpression)); +} -- Gitee