From 9f3906209604b79399f052db8483a99ad6e08ed0 Mon Sep 17 00:00:00 2001 From: Igor Loginov Date: Wed, 21 May 2025 14:49:01 +0300 Subject: [PATCH] part 1 --- ui2abc/libarkts/.gitlab-ci.yml | 1 - .../node-utilities/ETSImportDeclaration.ts | 41 +++++++++++++----- ui2abc/libarkts/src/arkts-api/visitor.ts | 1 - .../test/arkts-api/general/recheck.test.ts | 25 ++++++++--- .../imports/add-same-file/dump-src/main.ts | 2 +- .../recheck/imports/add-same-file/index.ts | 15 +++---- .../add-use-same-file/dump-src/main.ts | 2 +- .../imports/add-use-same-file/index.ts | 13 +++--- .../test/golden/HQ/arrow-assignment.ets | 2 +- ui2abc/memo-plugin/test/golden/test.ets | 2 +- .../src/builder-lambda-transformer.ts | 43 ++++++++++++++++--- 11 files changed, 100 insertions(+), 47 deletions(-) diff --git a/ui2abc/libarkts/.gitlab-ci.yml b/ui2abc/libarkts/.gitlab-ci.yml index acf29f5cd2..41dd274d57 100644 --- a/ui2abc/libarkts/.gitlab-ci.yml +++ b/ui2abc/libarkts/.gitlab-ci.yml @@ -61,7 +61,6 @@ test plugin-api: - install node modules (arkoala-arkts) - install node modules (incremental) - install node modules (interop) - - regenerate plugin-api test example arkts-plugin: interruptible: true diff --git a/ui2abc/libarkts/src/arkts-api/node-utilities/ETSImportDeclaration.ts b/ui2abc/libarkts/src/arkts-api/node-utilities/ETSImportDeclaration.ts index 05a6d3bbcc..e2c54d327a 100644 --- a/ui2abc/libarkts/src/arkts-api/node-utilities/ETSImportDeclaration.ts +++ b/ui2abc/libarkts/src/arkts-api/node-utilities/ETSImportDeclaration.ts @@ -17,7 +17,7 @@ import { ETSImportDeclaration, StringLiteral } from "../../generated" import { isSameNativeObject } from "../peers/ArktsObject" import { passNode, passNodeArray, unpackNonNullableNode, updateNodeByNode } from "../utilities/private" import { AstNode } from "../peers/AstNode" -import { Es2pandaImportFlags, Es2pandaImportKinds } from "../../generated/Es2pandaEnums" +import { Es2pandaContextState, Es2pandaImportFlags, Es2pandaImportKinds } from "../../generated/Es2pandaEnums" import { global } from "../static/global" import { Program } from "../peers/Program" @@ -27,8 +27,7 @@ export function createETSImportDeclaration( importKind: Es2pandaImportKinds, program: Program, flags: Es2pandaImportFlags -): ETSImportDeclaration { - // TODO: check that plugin is on parsed stage +) { const res = unpackNonNullableNode( global.es2panda._ETSParserBuildImportDeclaration( global.context, @@ -41,24 +40,44 @@ export function createETSImportDeclaration( ) ) global.es2panda._InsertETSImportDeclarationAndParse(global.context, program.peer, res.peer) - return new ETSImportDeclaration(res.peer) + // TODO: what if new files got added to external sources and they should be processed by plugin? + + // Actually this new import got added to AST by compiler, so we should not modify AST by plugin } +// TODO: It seems that this function currently updates AST not in proper way, so the old import declaration should be removed export function updateETSImportDeclaration( original: ETSImportDeclaration, - source: StringLiteral | undefined, specifiers: readonly AstNode[], - importKind: Es2pandaImportKinds -): ETSImportDeclaration { - if (isSameNativeObject(source, original.source) - && isSameNativeObject(specifiers, original.specifiers) + importKind: Es2pandaImportKinds, + program: Program = global.compilerContext.program, // TODO: pass program from plugin here (or maybe it should be main program actually?), + flags: Es2pandaImportFlags = Es2pandaImportFlags.IMPORT_FLAGS_NONE, +) { + if (isSameNativeObject(specifiers, original.specifiers) /* no getter for importKind */ ) { /* TODO: probably should set importMetadata, but no getter provided yet */ return original } + const res = unpackNonNullableNode( + global.es2panda._ETSParserBuildImportDeclaration( + global.context, + importKind, + passNodeArray(specifiers), + specifiers.length, + passNode(original.source), + program.peer, + flags + ) + ) + global.es2panda._InsertETSImportDeclarationAndParse(global.context, program.peer, res.peer) + // Actually this new import got added to AST by compiler, so return forgotten old import to continue traversal return updateNodeByNode( - ETSImportDeclaration.createETSImportDeclaration(source, specifiers, importKind), - original + ETSImportDeclaration.createETSImportDeclaration( + StringLiteral.create1StringLiteral(original.source?.str ?? ""), + [], // Compiler doesn't like this actually (possibly only in restart solution?) + importKind, + ), + original, ) } diff --git a/ui2abc/libarkts/src/arkts-api/visitor.ts b/ui2abc/libarkts/src/arkts-api/visitor.ts index 6d106ede3f..486bec7bbe 100644 --- a/ui2abc/libarkts/src/arkts-api/visitor.ts +++ b/ui2abc/libarkts/src/arkts-api/visitor.ts @@ -519,7 +519,6 @@ export function visitEachChild( if (isETSImportDeclaration(node)) { return factory.updateETSImportDeclaration( node, - nodeVisitor(node.source, visitor), nodesVisitor(node.specifiers, visitor), Es2pandaImportKinds.IMPORT_KINDS_ALL ) diff --git a/ui2abc/libarkts/test/arkts-api/general/recheck.test.ts b/ui2abc/libarkts/test/arkts-api/general/recheck.test.ts index ccde6f39fd..eaff410895 100644 --- a/ui2abc/libarkts/test/arkts-api/general/recheck.test.ts +++ b/ui2abc/libarkts/test/arkts-api/general/recheck.test.ts @@ -98,7 +98,7 @@ console.log("test"); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED) }) - test.skip("change function name in main program and in dependency", function() { + test("change function name in main program and in dependency", function() { createConfig() const code = @@ -117,13 +117,13 @@ console.log("test"); if (!it.getName().includes("library")) return it.programs.forEach(program => { new RenameTestFunction().visitor(program.astNode) + arkts.arktsGlobal.es2panda._AstNodeUpdateAll(arkts.arktsGlobal.context, program.astNode.peer) }) }) - arkts.factory.createETSImportDeclaration( - arkts.factory.createStringLiteral( - './library' - ), + const statements = [...module.statements] // save statements + statements[0] = arkts.factory.updateETSImportDeclaration( + statements[0] as arkts.ETSImportDeclaration, [ arkts.factory.createImportSpecifier( arkts.factory.createIdentifier( @@ -139,6 +139,14 @@ console.log("test"); arkts.Es2pandaImportFlags.IMPORT_FLAGS_NONE ) + arkts.updateETSModuleByStatements( + module, + [ + ...module.statements.slice(0, 1), // this is added by compiler + ...statements.slice(1), // updated statements from the ones saved before + ] + ) + new RenameTestFunction().visitor(module) arkts.arktsGlobal.es2panda._AstNodeUpdateAll(arkts.arktsGlobal.context, module.peer) @@ -146,7 +154,12 @@ console.log("test"); util.assert.equal( module.dumpSrc(), ` -testFunctionChanged() +import { testFunctionChanged as testFunctionChanged } from "./library"; + +function main() {} + +testFunctionChanged(); + `, `invalid result: ${module.dumpSrc()}`) diff --git a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/dump-src/main.ts b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/dump-src/main.ts index 51d2896e43..7c84ccdd5e 100644 --- a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/dump-src/main.ts +++ b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/dump-src/main.ts @@ -1,5 +1,5 @@ -import { testFunction as testFunction } from "./library"; +import { anotherFunction as anotherFunction, testFunction as testFunction } from "./library"; import { anotherFunction as anotherFunction } from "./library"; diff --git a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/index.ts b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/index.ts index 5f77f7fb3b..1e4e8618e3 100644 --- a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/index.ts +++ b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-same-file/index.ts @@ -2,23 +2,20 @@ import * as arkts from "../../../../../src/arkts-api" export function addImportSameFile(program: arkts.Program, options: arkts.CompilationOptions) { if (options.isMainProgram) { - arkts.factory.createETSImportDeclaration( - arkts.factory.createStringLiteral( - './library' - ), + arkts.factory.updateETSImportDeclaration( + (program.astNode.statements[0] as arkts.ETSImportDeclaration), [ + ...(program.astNode.statements[0] as arkts.ETSImportDeclaration).specifiers, arkts.factory.createImportSpecifier( arkts.factory.createIdentifier( 'testFunction' ), arkts.factory.createIdentifier( 'testFunction' - ) - ) + ), + ), ], - arkts.Es2pandaImportKinds.IMPORT_KINDS_ALL, - arkts.arktsGlobal.compilerContext.program, - arkts.Es2pandaImportFlags.IMPORT_FLAGS_NONE + arkts.Es2pandaImportKinds.IMPORT_KINDS_ALL ) } return program diff --git a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/dump-src/main.ts b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/dump-src/main.ts index d6401c4526..d27c5a0a26 100644 --- a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/dump-src/main.ts +++ b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/dump-src/main.ts @@ -1,5 +1,5 @@ -import { testFunction as testFunction } from "./library"; +import { anotherFunction as anotherFunction, testFunction as testFunction } from "./library"; import { anotherFunction as anotherFunction } from "./library"; diff --git a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/index.ts b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/index.ts index 6da984d08a..e2b3d0684a 100644 --- a/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/index.ts +++ b/ui2abc/libarkts/test/arkts-api/recheck/imports/add-use-same-file/index.ts @@ -16,23 +16,20 @@ export function addUseImportSameFile(program: arkts.Program, options: arkts.Comp ) ] ) - arkts.factory.createETSImportDeclaration( - arkts.factory.createStringLiteral( - './library' - ), + arkts.factory.updateETSImportDeclaration( + (program.astNode.statements[0] as arkts.ETSImportDeclaration), [ + ...(program.astNode.statements[0] as arkts.ETSImportDeclaration).specifiers, arkts.factory.createImportSpecifier( arkts.factory.createIdentifier( 'testFunction' ), arkts.factory.createIdentifier( 'testFunction' - ) - ) + ), + ), ], arkts.Es2pandaImportKinds.IMPORT_KINDS_ALL, - arkts.arktsGlobal.compilerContext.program, - arkts.Es2pandaImportFlags.IMPORT_FLAGS_NONE ) } return program diff --git a/ui2abc/memo-plugin/test/golden/HQ/arrow-assignment.ets b/ui2abc/memo-plugin/test/golden/HQ/arrow-assignment.ets index f84f771c44..2640e146b3 100644 --- a/ui2abc/memo-plugin/test/golden/HQ/arrow-assignment.ets +++ b/ui2abc/memo-plugin/test/golden/HQ/arrow-assignment.ets @@ -27,7 +27,7 @@ class Test { if (__memo_scope.unchanged) { return __memo_scope.cached; } - return __memo_scope.recache(((123) + (x))); + return __memo_scope.recache(((123) + (__memo_parameter_x.value))); }); const h = @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type): number => { const __memo_scope = __memo_context.scope(((__memo_id) + (__hash("id__arrow-assignment.ets"))), 0); diff --git a/ui2abc/memo-plugin/test/golden/test.ets b/ui2abc/memo-plugin/test/golden/test.ets index 264235366b..4fd8fc81e4 100644 --- a/ui2abc/memo-plugin/test/golden/test.ets +++ b/ui2abc/memo-plugin/test/golden/test.ets @@ -286,7 +286,7 @@ class Test { if (__memo_scope.unchanged) { return __memo_scope.cached; } - return __memo_scope.recache(((123) + (x))); + return __memo_scope.recache(((123) + (__memo_parameter_x.value))); }); const h = @memo() ((__memo_context: __memo_context_type, __memo_id: __memo_id_type): number => { const __memo_scope = __memo_context.scope(((__memo_id) + (__hash("id__@test.test.ets"))), 0); diff --git a/ui2abc/ui-plugins/src/builder-lambda-transformer.ts b/ui2abc/ui-plugins/src/builder-lambda-transformer.ts index b90cf1bbca..77329bc8de 100644 --- a/ui2abc/ui-plugins/src/builder-lambda-transformer.ts +++ b/ui2abc/ui-plugins/src/builder-lambda-transformer.ts @@ -169,7 +169,7 @@ function transformBuilderLambdaCall(node: arkts.CallExpression): arkts.CallExpre // in theory we don't add new files to import here, // only the new names from the same file, // to it should be okay. -function transformETSImportDeclaration(node: arkts.ETSImportDeclaration): arkts.ETSImportDeclaration { +function transformETSImportDeclaration(node: arkts.ETSImportDeclaration): boolean { const additionalNames: string[] = [] node.specifiers.forEach(it => { const name = (it as arkts.ImportSpecifier).imported @@ -185,12 +185,12 @@ function transformETSImportDeclaration(node: arkts.ETSImportDeclaration): arkts. } } }) - if (additionalNames.length == 0) return node + if (additionalNames.length == 0) return false - return arkts.factory.updateETSImportDeclaration( + arkts.factory.updateETSImportDeclaration( node, - node.source, - [ ...node.specifiers, + [ + ...node.specifiers, ...additionalNames.map(it => arkts.factory.createImportSpecifier( arkts.factory.createIdentifier(it), arkts.factory.createIdentifier(it) @@ -198,6 +198,7 @@ function transformETSImportDeclaration(node: arkts.ETSImportDeclaration): arkts. ], node.isTypeKind ? arkts.Es2pandaImportKinds.IMPORT_KINDS_TYPES : arkts.Es2pandaImportKinds.IMPORT_KINDS_ALL ) + return true } @@ -208,8 +209,36 @@ export class BuilderLambdaTransformer extends arkts.AbstractVisitor { if (arkts.isCallExpression(node)) { return transformBuilderLambdaCall(node) } - if (arkts.isETSImportDeclaration(node)) { - return transformETSImportDeclaration(node) + + if (arkts.isETSModule(node)) { + const statements = node.statements + const newStatements: arkts.Statement[] = [] + let createdImports = 0 + /* + Updated imports are added to the beginning of statements by node.statements by compiler, but not added to newStatements by plugin + Non-updated imports and other statements are added to newStatements + Then ETSModule is updated by proper joining of node.statement and newStatements + TODO: maybe move all import inserting logic to libarkts, not keep in plugins? + */ + for (const statement of statements) { + if (arkts.isETSImportDeclaration(statement)) { + const updated = transformETSImportDeclaration(statement) + if (!updated) { + newStatements.push(statement) + } else { + createdImports++ + } + } else { + newStatements.push(statement) + } + } + return arkts.updateETSModuleByStatements( + node, + [ + ...node.statements.slice(0, createdImports), + ...newStatements, + ] + ) } return node -- Gitee