diff --git a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts index 4aede630988609c741f39ea51db5b1e189fee1d8..dbf8f0ce371d048d7c977cb14a88a6feffe84e64 100644 --- a/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts +++ b/arkui-plugins/ui-plugins/builder-lambda-translators/factory.ts @@ -604,6 +604,7 @@ export class factory { const args: (arkts.AstNode | undefined)[] = this.generateArgsInBuilderLambda(leaf, lambdaBody!, declInfo); const newNode = arkts.factory.updateCallExpression(node, replace, leaf.typeArguments, filterDefined(args)); arkts.NodeCache.getInstance().collect(newNode); + newNode.range = node.range; return newNode; } diff --git a/arkui-plugins/ui-plugins/component-transformer.ts b/arkui-plugins/ui-plugins/component-transformer.ts index 8d9c5aaf41c0fcb5d391b2acd908fd664a5479e9..621f447b9a98b135cd3b84e05f966092072b2418 100644 --- a/arkui-plugins/ui-plugins/component-transformer.ts +++ b/arkui-plugins/ui-plugins/component-transformer.ts @@ -69,10 +69,15 @@ export interface InteropContext { arguments?: arkts.ObjectExpression; } +interface EntryConfig { + entryName: string; + entryRange: arkts.SourceRange; +} + export class ComponentTransformer extends AbstractVisitor { private scopeInfos: ScopeInfo[] = []; private componentInterfaceCollection: arkts.TSInterfaceDeclaration[] = []; - private entryNames: string[] = []; + private entryConfigs: EntryConfig[] = []; private structMembersMap: Map = new Map(); private isCustomComponentImported: boolean = false; private isCustomComponentV2Imported: boolean = false; @@ -97,7 +102,7 @@ export class ComponentTransformer extends AbstractVisitor { super.reset(); this.scopeInfos = []; this.componentInterfaceCollection = []; - this.entryNames = []; + this.entryConfigs = []; this.structMembersMap = new Map(); this.isCustomComponentImported = false; this.isCustomComponentV2Imported = false; @@ -221,7 +226,7 @@ export class ComponentTransformer extends AbstractVisitor { navInterface.modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_EXPORT; return arkts.factory.updateEtsScript(node, [...node.statements, navInterface]); } - if (this.isExternal && this.componentInterfaceCollection.length === 0 && this.entryNames.length === 0) { + if (this.isExternal && this.componentInterfaceCollection.length === 0 && this.entryConfigs.length === 0) { return node; } const updateStatements: arkts.AstNode[] = []; @@ -245,13 +250,19 @@ export class ComponentTransformer extends AbstractVisitor { updateStatements.push(...this.componentInterfaceCollection); } - if (this.entryNames.length > 0) { + if (this.entryConfigs.length > 0) { if (!this.isEntryPointImported) entryFactory.createAndInsertEntryPointImport(this.program); // normally, we should only have at most one @Entry component in a single file. // probably need to handle error message here. - if (!this.isPageLifeCycleImported) + if (!this.isPageLifeCycleImported) { this.createImportDeclaration(CUSTOM_COMPONENT_IMPORT_SOURCE_NAME, CustomComponentNames.PAGE_LIFE_CYCLE); - updateStatements.push(...this.entryNames.map(entryFactory.generateEntryWrapper)); + } + updateStatements.push( + ...this.entryConfigs.map(({ entryName, entryRange }) => { + const entryWrapper = entryFactory.generateEntryWrapper(entryName, entryRange); + return entryWrapper; + }) + ); updateStatements.push( entryFactory.callRegisterNamedRouter( this.entryRouteName, @@ -342,7 +353,7 @@ export class ComponentTransformer extends AbstractVisitor { const definition: arkts.ClassDefinition = node.definition!; const newDefinitionBody: arkts.AstNode[] = []; if (!!scopeInfo.annotations?.entry) { - this.entryNames.push(className); + this.entryConfigs.push({ entryName: className, entryRange: scopeInfo.annotations.entry.range }); const { storage, useSharedStorage, routeName } = getEntryParams(definition); entryFactory.transformStorageParams(storage, useSharedStorage, definition); if (routeName && routeName.value && arkts.isStringLiteral(routeName.value)) { @@ -367,6 +378,7 @@ export class ComponentTransformer extends AbstractVisitor { _node.modifiers = node.modifiers; _node.startPosition = node.startPosition; _node.endPosition = node.endPosition; + _node.range = node.range; return _node; } else { return arkts.factory.updateClassDeclaration(node, newDefinition); diff --git a/arkui-plugins/ui-plugins/entry-translators/factory.ts b/arkui-plugins/ui-plugins/entry-translators/factory.ts index e4dd29d224a73bb929913285ac9d5fb2cb602a91..46091b9e83748027b4b52b09a19e5211ea998a12 100644 --- a/arkui-plugins/ui-plugins/entry-translators/factory.ts +++ b/arkui-plugins/ui-plugins/entry-translators/factory.ts @@ -181,7 +181,7 @@ export class factory { * * @param name class/struct name that has `@Entry` annotation. */ - static generateEntryWrapper(name: string): arkts.ClassDeclaration { + static generateEntryWrapper(name: string, entryAnnotationRange: arkts.SourceRange): arkts.ClassDeclaration { const ctor = factory.generateConstructor(); const definition: arkts.ClassDefinition = arkts.factory .createClassDefinition( @@ -202,6 +202,7 @@ export class factory { arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE ) .setCtor(ctor as any); + definition.range = entryAnnotationRange; const newClass = arkts.factory.createClassDeclaration(definition); newClass.modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE; return newClass; diff --git a/arkui-plugins/ui-plugins/property-translators/link.ts b/arkui-plugins/ui-plugins/property-translators/link.ts index 65217d539ea207a9cd60a0503eeea15a59d8a442..8245b54e6b04c9b12beefcc29fac781218e4583a 100644 --- a/arkui-plugins/ui-plugins/property-translators/link.ts +++ b/arkui-plugins/ui-plugins/property-translators/link.ts @@ -43,6 +43,7 @@ export class LinkTranslator extends PropertyTranslator implements InitializerCon cacheTranslatedInitializer(newName: string, originalName: string): void { const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName); + initializeStruct.range = this.property.range; PropertyCache.getInstance().collectInitializeStruct(this.structInfo.name, [initializeStruct]); if (!!this.structInfo.annotations?.reusable) { const toRecord = generateToRecord(newName, originalName); diff --git a/arkui-plugins/ui-plugins/property-translators/prop.ts b/arkui-plugins/ui-plugins/property-translators/prop.ts index df2bce7938f7871c223864bbb2700b93a031e9aa..aa9bfec7cecbad48f20f940a156c12f9578c2d92 100644 --- a/arkui-plugins/ui-plugins/property-translators/prop.ts +++ b/arkui-plugins/ui-plugins/property-translators/prop.ts @@ -44,8 +44,10 @@ export class PropTranslator extends PropertyTranslator implements InitializerCon cacheTranslatedInitializer(newName: string, originalName: string): void { const mutableThis: arkts.Expression = generateThisBacking(newName); const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName); + initializeStruct.range = this.property.range; PropertyCache.getInstance().collectInitializeStruct(this.structInfo.name, [initializeStruct]); const updateStruct: arkts.AstNode = this.generateUpdateStruct(mutableThis, originalName); + updateStruct.range = this.property.range; PropertyCache.getInstance().collectUpdateStruct(this.structInfo.name, [updateStruct]); if (!!this.structInfo.annotations?.reusable) { const toRecord = generateToRecord(newName, originalName); diff --git a/arkui-plugins/ui-plugins/property-translators/state.ts b/arkui-plugins/ui-plugins/property-translators/state.ts index 704a56f711b3614520ceaa4cf517a9d069d44290..adf44294214149993b431a1bc79bab3fb7bb6645 100644 --- a/arkui-plugins/ui-plugins/property-translators/state.ts +++ b/arkui-plugins/ui-plugins/property-translators/state.ts @@ -42,6 +42,7 @@ export class StateTranslator extends PropertyTranslator implements InitializerCo cacheTranslatedInitializer(newName: string, originalName: string): void { const initializeStruct: arkts.AstNode = this.generateInitializeStruct(newName, originalName); + initializeStruct.range = this.property.range; PropertyCache.getInstance().collectInitializeStruct(this.structInfo.name, [initializeStruct]); if (!!this.structInfo.annotations?.reusable) { const toRecord = generateToRecord(newName, originalName); diff --git a/arkui-plugins/ui-plugins/struct-translators/factory.ts b/arkui-plugins/ui-plugins/struct-translators/factory.ts index 5901243d41b1c5e19f4042eeb56e44dd48cc7156..29dafba3ccb469662774ba991fd0441c573a2ee2 100644 --- a/arkui-plugins/ui-plugins/struct-translators/factory.ts +++ b/arkui-plugins/ui-plugins/struct-translators/factory.ts @@ -375,6 +375,7 @@ export class factory { * transform property members in custom-component class. */ static tranformPropertyMembers( + classIdent: arkts.Identifier, propertyTranslators: PropertyTranslator[], optionsTypeName: string, scope: CustomComponentScopeInfo @@ -382,10 +383,14 @@ export class factory { const propertyMembers = propertyTranslators.map((translator) => translator.translateMember()); const collections = []; if (!scope.hasInitializeStruct) { - collections.push(this.createInitializeStruct(optionsTypeName, scope)); + const initializeStruct: arkts.MethodDefinition = this.createInitializeStruct(optionsTypeName, scope); + initializeStruct.range = classIdent.range; + collections.push(initializeStruct); } if (!scope.hasUpdateStruct) { - collections.push(this.createUpdateStruct(optionsTypeName, scope)); + const updateStruct: arkts.MethodDefinition = this.createUpdateStruct(optionsTypeName, scope); + updateStruct.range = classIdent.range; + collections.push(updateStruct); } if (!!scope.annotations?.reusable) { collections.push(this.createToRecord(optionsTypeName, scope)); @@ -432,6 +437,7 @@ export class factory { definition.body.map((it) => classifyProperty(it, scope)) ); const translatedMembers: arkts.AstNode[] = this.tranformPropertyMembers( + node.definition.ident!, propertyTranslators, classOptionsName ?? getCustomComponentOptionsName(className), scope diff --git a/koala-wrapper/native/src/bridges.cc b/koala-wrapper/native/src/bridges.cc index 3cc1282ac5484d50b0fedce2e75bcdf0bc97e244..300bdf311df60052b8262612d4be2fdd51a9c789 100644 --- a/koala-wrapper/native/src/bridges.cc +++ b/koala-wrapper/native/src/bridges.cc @@ -521,6 +521,16 @@ KNativePointer impl_AstNodeRangeConst(KNativePointer context, KNativePointer nod } KOALA_INTEROP_2(AstNodeRangeConst, KNativePointer, KNativePointer, KNativePointer) +void impl_AstNodeSetRange(KNativePointer context, KNativePointer receiver, KNativePointer range) +{ + const auto _context = reinterpret_cast(context); + const auto _receiver = reinterpret_cast(receiver); + const auto _range = reinterpret_cast(range); + GetImpl()->AstNodeSetRange(_context, _receiver, _range); + return; +} +KOALA_INTEROP_V3(AstNodeSetRange, KNativePointer, KNativePointer, KNativePointer); + KNativePointer impl_SourceRangeStart(KNativePointer context, KNativePointer range) { const auto _context = reinterpret_cast(context); diff --git a/koala-wrapper/src/Es2pandaNativeModule.ts b/koala-wrapper/src/Es2pandaNativeModule.ts index 1fcdcdd4f3c5e30756d73a6a0318eb29505fbb38..e9237bd1795d3edc516e534110480d12b1e7bebd 100644 --- a/koala-wrapper/src/Es2pandaNativeModule.ts +++ b/koala-wrapper/src/Es2pandaNativeModule.ts @@ -875,6 +875,10 @@ export class Es2pandaNativeModule { throw new Error('CreateFunctionDecl was not overloaded by native module initialization'); } + _AstNodeSetRange(context: KNativePointer, node: KNativePointer, range: KNativePointer): KNativePointer { + throw new Error('Not implemented'); + } + _SourceRangeStart(context: KNativePointer, range: KNativePointer): KNativePointer { throw new Error('CreateFunctionDecl was not overloaded by native module initialization'); } diff --git a/koala-wrapper/src/arkts-api/peers/AstNode.ts b/koala-wrapper/src/arkts-api/peers/AstNode.ts index 2a8b90fa6911fb0c75dd3f1c8dd3365a0a48df66..8925917839daad7986916c4cf4630fab2ebd527a 100644 --- a/koala-wrapper/src/arkts-api/peers/AstNode.ts +++ b/koala-wrapper/src/arkts-api/peers/AstNode.ts @@ -21,6 +21,7 @@ import { Es2pandaModifierFlags } from '../../generated/Es2pandaEnums'; import { ArktsObject } from './ArktsObject'; import { Es2pandaAstNodeType } from '../../Es2pandaEnums'; import { SourcePosition } from './SourcePosition'; +import { SourceRange } from './SourceRange'; export abstract class AstNode extends ArktsObject { protected constructor(peer: KNativePointer) { @@ -153,6 +154,14 @@ export abstract class AstNode extends ArktsObject { public set endPosition(end: SourcePosition) { global.es2panda._AstNodeSetEnd(global.context, this.peer, end.peer); } + + public get range(): SourceRange { + return new SourceRange(global.es2panda._AstNodeRangeConst(global.context, this.peer)); + } + + public set range(range: SourceRange) { + global.es2panda._AstNodeSetRange(global.context, this.peer, range.peer); + } } export class UnsupportedNode extends AstNode {