From d861398ddb55acc018a2f68174f65ede9b9a54b0 Mon Sep 17 00:00:00 2001 From: Cuecuexiaoyu Date: Fri, 25 Jul 2025 17:38:20 +0800 Subject: [PATCH 1/2] add getTypeNodeFromTsType api Signed-off-by: Cuecuexiaoyu Change-Id: I0aaecf7ccb0571ac4483df4f9c654d5fd6c25a52 --- .../test/demo/mock/component/for-each.ets | 7 +++++++ .../ut/ui-plugins/component/for-each.test.ts | 19 +++++++++++++++++-- .../ui-plugins/struct-translators/factory.ts | 13 +++---------- koala-wrapper/native/src/bridges.cc | 17 +++++++++++++++++ koala-wrapper/src/Es2pandaNativeModule.ts | 4 ++++ .../src/arkts-api/utilities/public.ts | 9 +++++++++ 6 files changed, 57 insertions(+), 12 deletions(-) diff --git a/arkui-plugins/test/demo/mock/component/for-each.ets b/arkui-plugins/test/demo/mock/component/for-each.ets index acb51f102..d615581b6 100644 --- a/arkui-plugins/test/demo/mock/component/for-each.ets +++ b/arkui-plugins/test/demo/mock/component/for-each.ets @@ -43,6 +43,13 @@ struct ImportStruct { ForEach((new AB()).bar, (item: string) => { Text(item) }) + ForEach((new AB()).bar, () => {}) + ForEach(this.getArray(), () => {}) + ForEach(new Array('1', '2'), () => { + ForEach(new Array('1', '2'), (item: string) => { + Text(item) + }) + }) } } } \ No newline at end of file diff --git a/arkui-plugins/test/ut/ui-plugins/component/for-each.test.ts b/arkui-plugins/test/ut/ui-plugins/component/for-each.test.ts index 2c925d38b..2be3db75b 100644 --- a/arkui-plugins/test/ut/ui-plugins/component/for-each.test.ts +++ b/arkui-plugins/test/ut/ui-plugins/component/for-each.test.ts @@ -95,7 +95,7 @@ class AB { @memo() public build() { Column(undefined, undefined, @memo() (() => { - ForEach(((): Array => { + ForEach(((): Array => { return this.arr; }), ((item: string) => { Text(undefined, item, undefined, undefined); @@ -105,11 +105,26 @@ class AB { }), ((item: Person) => { Text(undefined, item.name, undefined, undefined); })); - ForEach(((): Array => { + ForEach(((): Array => { return new AB().bar; }), ((item: string) => { Text(undefined, item, undefined, undefined); })); + ForEach(((): Array => { + return new AB().bar; + }), (() => {})); + ForEach(((): Array => { + return this.getArray(); + }), (() => {})); + ForEach(((): Array => { + return new Array("1", "2"); + }), (() => { + ForEach(((): Array => { + return new Array("1", "2"); + }), ((item: string) => { + Text(undefined, item, undefined, undefined); + })); + })); })); } diff --git a/arkui-plugins/ui-plugins/struct-translators/factory.ts b/arkui-plugins/ui-plugins/struct-translators/factory.ts index d4fd4e5d1..6d07d5bd0 100644 --- a/arkui-plugins/ui-plugins/struct-translators/factory.ts +++ b/arkui-plugins/ui-plugins/struct-translators/factory.ts @@ -1040,20 +1040,13 @@ export class factory { if (!arkts.isArrowFunctionExpression(node.arguments[1])) { return node; } - const argTypeParam: arkts.Expression = node.arguments[1].scriptFunction.params[0]; - if ( - !arkts.isEtsParameterExpression(argTypeParam) || - !argTypeParam.type || - !arkts.isTypeNode(argTypeParam.type) - ) { + const returnType = arkts.getTypeNodeFromTsType(node.arguments[0]); + if (!returnType || !arkts.isTypeNode(returnType)) { return node; } - const referenceType = UIFactory.createComplexTypeFromStringAndTypeParameter('Array', [ - argTypeParam.type.clone(), - ]); const newFunc = UIFactory.createScriptFunction({ body: arkts.factory.createBlock([arkts.factory.createReturnStatement(node.arguments[0])]), - returnTypeAnnotation: referenceType, + returnTypeAnnotation: returnType, flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW, modifiers: arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, }); diff --git a/koala-wrapper/native/src/bridges.cc b/koala-wrapper/native/src/bridges.cc index c4e5a34a4..dcab96d83 100644 --- a/koala-wrapper/native/src/bridges.cc +++ b/koala-wrapper/native/src/bridges.cc @@ -495,6 +495,23 @@ KNativePointer impl_ClassVariableDeclaration(KNativePointer context, KNativePoin } KOALA_INTEROP_2(ClassVariableDeclaration, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_CreateTypeNodeFromTsType(KNativePointer context, KNativePointer nodePtr) +{ + const auto _context = reinterpret_cast(context); + const auto _nodePtr = reinterpret_cast(nodePtr); + auto _tsType = GetImpl()->TypedTsType(_context, _nodePtr); + if (_tsType == nullptr) { + _tsType = GetImpl()->ExpressionTsType(_context, _nodePtr); + } + if (_tsType == nullptr) { + return nullptr; + } + const auto _nodeTsType = reinterpret_cast(_tsType); + auto _typeAnnotation = GetImpl()->CreateTypeNodeFromTsType(_context, _nodeTsType); + return _typeAnnotation; +} +KOALA_INTEROP_2(CreateTypeNodeFromTsType, KNativePointer, KNativePointer, KNativePointer); + KBoolean impl_IsMethodDefinition(KNativePointer nodePtr) { auto node = reinterpret_cast(nodePtr); diff --git a/koala-wrapper/src/Es2pandaNativeModule.ts b/koala-wrapper/src/Es2pandaNativeModule.ts index 0e45639b9..96fadd880 100644 --- a/koala-wrapper/src/Es2pandaNativeModule.ts +++ b/koala-wrapper/src/Es2pandaNativeModule.ts @@ -866,6 +866,10 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } + _CreateTypeNodeFromTsType(context: KNativePointer, classInstance: KNativePointer): KNativePointer { + throw new Error('Not implemented'); + } + _IsMethodDefinition(node: KPtr): KBoolean { throw new Error('Not implemented'); } diff --git a/koala-wrapper/src/arkts-api/utilities/public.ts b/koala-wrapper/src/arkts-api/utilities/public.ts index c630d2ac8..6af596408 100644 --- a/koala-wrapper/src/arkts-api/utilities/public.ts +++ b/koala-wrapper/src/arkts-api/utilities/public.ts @@ -36,6 +36,7 @@ import { isScriptFunction, isTSInterfaceDeclaration, Property, + TypeNode, type AnnotationUsage, } from '../../generated'; import { Program } from '../peers/Program'; @@ -166,6 +167,14 @@ export function getPeerObjectDecl(peer: KNativePointer): AstNode | undefined { return unpackNonNullableNode(decl); } +export function getTypeNodeFromTsType(node: AstNode): AstNode | undefined { + const typeAnnotation = global.es2panda._CreateTypeNodeFromTsType(global.context, node.peer); + if (typeAnnotation === nullptr) { + return undefined; + } + return unpackNonNullableNode(typeAnnotation); +} + export function getAnnotations(node: AstNode): readonly AnnotationUsage[] { if (!isFunctionDeclaration(node) && !isScriptFunction(node) && !isClassDefinition(node)) { throwError('for now annotations allowed only for: functionDeclaration, scriptFunction, classDefinition'); -- Gitee From 13ef39c1e34cab60ad99eb221dab2edb6079c0d2 Mon Sep 17 00:00:00 2001 From: Cuecuexiaoyu Date: Mon, 28 Jul 2025 15:34:19 +0800 Subject: [PATCH 2/2] support no type classProperty in struct Signed-off-by: Cuecuexiaoyu Change-Id: I90d499450473282c57099a934d0f345d2afe9a4c --- .../ui-plugins/property-translators/base.ts | 3 +++ .../ui-plugins/property-translators/factory.ts | 8 +++++--- .../ui-plugins/property-translators/prop.ts | 12 ++++++------ .../property-translators/regularProperty.ts | 6 +++--- .../ui-plugins/property-translators/state.ts | 10 +++++----- arkui-plugins/ui-plugins/utils.ts | 14 +++++++++++++- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/arkui-plugins/ui-plugins/property-translators/base.ts b/arkui-plugins/ui-plugins/property-translators/base.ts index ba0c0bd41..1fcd929e9 100644 --- a/arkui-plugins/ui-plugins/property-translators/base.ts +++ b/arkui-plugins/ui-plugins/property-translators/base.ts @@ -18,6 +18,7 @@ import { collectStateManagementTypeImport, createGetter, createSetter } from './ import { CustomComponentInfo, ClassInfo } from '../utils'; import { StateManagementTypes } from '../../common/predefines'; import { ClassScopeInfo } from '../struct-translators/utils'; +import { getClassPropertyType } from '../utils'; export interface PropertyTranslatorOptions { property: arkts.ClassProperty; @@ -27,10 +28,12 @@ export interface PropertyTranslatorOptions { export abstract class PropertyTranslator { protected property: arkts.ClassProperty; protected structInfo: CustomComponentInfo; + protected propertyType: arkts.TypeNode | undefined; constructor(options: PropertyTranslatorOptions) { this.property = options.property; this.structInfo = options.structInfo; + this.propertyType = getClassPropertyType(options.property); } abstract translateMember(): arkts.AstNode[]; diff --git a/arkui-plugins/ui-plugins/property-translators/factory.ts b/arkui-plugins/ui-plugins/property-translators/factory.ts index 0cc0f24ef..a2183b31b 100644 --- a/arkui-plugins/ui-plugins/property-translators/factory.ts +++ b/arkui-plugins/ui-plugins/property-translators/factory.ts @@ -32,7 +32,7 @@ import { OptionalMemberInfo, removeDecorator, } from './utils'; -import { CustomComponentNames } from '../utils'; +import { CustomComponentNames, getClassPropertyType } from '../utils'; import { addMemoAnnotation, findCanAddMemoFromTypeAnnotation } from '../../collectors/memo-collectors/utils'; import { annotation, isNumeric } from '../../common/arkts-utils'; @@ -321,7 +321,9 @@ export class factory { modifiers: arkts.Es2pandaModifierFlags, needMemo: boolean = false ): arkts.ClassProperty { - const newType: arkts.TypeNode | undefined = property.typeAnnotation?.clone(); + const newType: arkts.TypeNode | undefined = !stageManagementType + ? property.typeAnnotation ?? UIFactory.createTypeReferenceFromString('Any') + : getClassPropertyType(property); if (needMemo && findCanAddMemoFromTypeAnnotation(newType)) { addMemoAnnotation(newType); } @@ -344,7 +346,7 @@ export class factory { arkts.factory.createTypeReferencePart( arkts.factory.createIdentifier(stageManagementType), arkts.factory.createTSTypeParameterInstantiation([ - property.typeAnnotation ? property.typeAnnotation.clone() : arkts.factory.createETSUndefinedType(), + getClassPropertyType(property) ?? arkts.factory.createETSUndefinedType(), ]) ) ); diff --git a/arkui-plugins/ui-plugins/property-translators/prop.ts b/arkui-plugins/ui-plugins/property-translators/prop.ts index 47722196d..aea392437 100644 --- a/arkui-plugins/ui-plugins/property-translators/prop.ts +++ b/arkui-plugins/ui-plugins/property-translators/prop.ts @@ -67,12 +67,12 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon ); const getter: arkts.MethodDefinition = this.translateGetter( originalName, - this.property.typeAnnotation, + this.propertyType, thisGet ); const setter: arkts.MethodDefinition = this.translateSetter( originalName, - this.property.typeAnnotation, + this.propertyType, thisSet ); @@ -107,8 +107,8 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon const args: arkts.Expression[] = [ arkts.factory.create1StringLiteral(originalName), this.property.value - ? binaryItem - : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), + ? arkts.factory.createTSAsExpression(binaryItem, this.propertyType, false) + : factory.generateDefiniteInitializers(this.propertyType, originalName), ]; factory.judgeIfAddWatchFunc(args, this.property); collectStateManagementTypeImport(StateManagementTypes.PROP_DECORATED); @@ -117,7 +117,7 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION, factory.generateStateMgmtFactoryCall( StateManagementTypes.MAKE_PROP, - this.property.typeAnnotation, + this.propertyType, args, true ) @@ -141,7 +141,7 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon false, true ), - this.property.typeAnnotation ? this.property.typeAnnotation.clone() : undefined, + this.propertyType ? this.propertyType.clone() : undefined, false ), ]); diff --git a/arkui-plugins/ui-plugins/property-translators/regularProperty.ts b/arkui-plugins/ui-plugins/property-translators/regularProperty.ts index 03ff22e98..aed91c836 100644 --- a/arkui-plugins/ui-plugins/property-translators/regularProperty.ts +++ b/arkui-plugins/ui-plugins/property-translators/regularProperty.ts @@ -71,12 +71,12 @@ export class RegularPropertyTranslator extends PropertyTranslator implements Ini ); const getter: arkts.MethodDefinition = this.translateGetter( originalName, - this.property.typeAnnotation, - arkts.factory.createTSAsExpression(thisValue, this.property.typeAnnotation, false) + this.propertyType, + arkts.factory.createTSAsExpression(thisValue, this.propertyType, false) ); const setter: arkts.MethodDefinition = this.translateSetter( originalName, - this.property.typeAnnotation, + this.propertyType, thisSet ); diff --git a/arkui-plugins/ui-plugins/property-translators/state.ts b/arkui-plugins/ui-plugins/property-translators/state.ts index 13f5095a8..937afca35 100644 --- a/arkui-plugins/ui-plugins/property-translators/state.ts +++ b/arkui-plugins/ui-plugins/property-translators/state.ts @@ -63,12 +63,12 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo ); const getter: arkts.MethodDefinition = this.translateGetter( originalName, - this.property.typeAnnotation, + this.propertyType, thisGet ); const setter: arkts.MethodDefinition = this.translateSetter( originalName, - this.property.typeAnnotation, + this.propertyType, thisSet ); @@ -103,8 +103,8 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo const args: arkts.Expression[] = [ arkts.factory.create1StringLiteral(originalName), this.property.value - ? binaryItem - : factory.generateDefiniteInitializers(this.property.typeAnnotation, originalName), + ? arkts.factory.createTSAsExpression(binaryItem, this.propertyType, false) + : factory.generateDefiniteInitializers(this.propertyType, originalName), ]; factory.judgeIfAddWatchFunc(args, this.property); collectStateManagementTypeImport(StateManagementTypes.STATE_DECORATED); @@ -113,7 +113,7 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION, factory.generateStateMgmtFactoryCall( StateManagementTypes.MAKE_STATE, - this.property.typeAnnotation, + this.propertyType, args, true ) diff --git a/arkui-plugins/ui-plugins/utils.ts b/arkui-plugins/ui-plugins/utils.ts index 5bcfa6918..0149858eb 100644 --- a/arkui-plugins/ui-plugins/utils.ts +++ b/arkui-plugins/ui-plugins/utils.ts @@ -371,4 +371,16 @@ export function computedField(name: string): string { export function monitorField(name: string): string { return `__monitor_${name}`; -} \ No newline at end of file +} + +export function getClassPropertyType(property: arkts.ClassProperty): arkts.TypeNode | undefined { + if (!!property.typeAnnotation) { + return property.typeAnnotation; + } + let value: arkts.Expression | undefined = property.value; + let inferredType = value ? arkts.getTypeNodeFromTsType(value) : undefined; + if (inferredType && arkts.isTypeNode(inferredType)) { + return inferredType; + } + return undefined; +} -- Gitee