diff --git a/arkui-plugins/memo-plugins/index.ts b/arkui-plugins/memo-plugins/index.ts index aa5c2de65a05c30a87710b35e2cb346098076e43..72c2b577dd2f3aa67e5e0253ee06712ac919e064 100644 --- a/arkui-plugins/memo-plugins/index.ts +++ b/arkui-plugins/memo-plugins/index.ts @@ -27,77 +27,78 @@ import { SignatureTransformer } from './signature-transformer'; export function unmemoizeTransform(): Plugins { return { name: 'memo-plugin', - checked(this: PluginContext) { - console.log('[MEMO PLUGIN] AFTER CHECKED ENTER'); - const contextPtr = this.getContextPtr() ?? arkts.arktsGlobal.compilerContext?.peer; - if (!!contextPtr) { - let program = arkts.getOrUpdateGlobalContext(contextPtr).program; - let script = program.astNode; - - debugLog('[BEFORE MEMO SCRIPT] script: ', script.dumpSrc()); - const cachePath: string | undefined = this.getProjectConfig()?.cachePath; - debugDump( - script.dumpSrc(), - getDumpFileName(0, 'SRC', 5, 'MEMO_AfterCheck_Begin'), - true, - cachePath, - program.fileNameWithExtension - ); - - arkts.Performance.getInstance().createEvent('memo-checked'); - - const positionalIdTracker = new PositionalIdTracker(arkts.getFileName(), false); - const parameterTransformer = new ParameterTransformer({ - positionalIdTracker, - }); - const returnTransformer = new ReturnTransformer(); - const signatureTransformer = new SignatureTransformer(); - const functionTransformer = new FunctionTransformer({ - positionalIdTracker, - parameterTransformer, - returnTransformer, - signatureTransformer, - }); - - const programVisitor = new ProgramVisitor({ - pluginName: unmemoizeTransform.name, - state: arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, - visitors: [functionTransformer], - skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, - pluginContext: this, - }); - - program = programVisitor.programVisitor(program); - script = program.astNode; - - arkts.Performance.getInstance().stopEvent('memo-checked', false); - - debugLog('[AFTER MEMO SCRIPT] script: ', script.dumpSrc()); - debugDump( - script.dumpSrc(), - getDumpFileName(0, 'SRC', 6, 'MEMO_AfterCheck_End'), - true, - cachePath, - program.fileNameWithExtension - ); - - arkts.Performance.getInstance().createEvent('memo-recheck'); - arkts.recheckSubtree(script); - arkts.Performance.getInstance().stopEvent('memo-recheck', false); - - arkts.Performance.getInstance().clearAllEvents(true); - arkts.Performance.getInstance().visualizeEvents(true); - arkts.Performance.getInstance().clearHistory(); - arkts.Performance.getInstance().clearTotalDuration(); - - this.setArkTSAst(script); - console.log('[MEMO PLUGIN] AFTER CHECKED EXIT'); - return script; - } - console.log('[MEMO PLUGIN] AFTER CHECKED EXIT WITH NO TRANSFORM'); - }, + checked: checkedTransform, clean() { arkts.arktsGlobal.clearContext(); }, }; } + +function checkedTransform(this: PluginContext): arkts.EtsScript | undefined { + console.log('[MEMO PLUGIN] AFTER CHECKED ENTER'); + const contextPtr = this.getContextPtr() ?? arkts.arktsGlobal.compilerContext?.peer; + if (!!contextPtr) { + let program = arkts.getOrUpdateGlobalContext(contextPtr).program; + let script = program.astNode; + debugLog('[BEFORE MEMO SCRIPT] script: ', script.dumpSrc()); + const cachePath: string | undefined = this.getProjectConfig()?.cachePath; + debugDump( + script.dumpSrc(), + getDumpFileName(0, 'SRC', 5, 'MEMO_AfterCheck_Begin'), + true, + cachePath, + program.fileNameWithExtension + ); + arkts.Performance.getInstance().createEvent('memo-checked'); + program = checkedProgramVisit(program, this); + script = program.astNode; + arkts.Performance.getInstance().stopEvent('memo-checked', false); + debugLog('[AFTER MEMO SCRIPT] script: ', script.dumpSrc()); + debugDump( + script.dumpSrc(), + getDumpFileName(0, 'SRC', 6, 'MEMO_AfterCheck_End'), + true, + cachePath, + program.fileNameWithExtension + ); + arkts.Performance.getInstance().createEvent('memo-recheck'); + arkts.recheckSubtree(script); + arkts.Performance.getInstance().stopEvent('memo-recheck', false); + arkts.Performance.getInstance().clearAllEvents(false); + arkts.Performance.getInstance().visualizeEvents(true); + arkts.Performance.getInstance().clearHistory(); + arkts.Performance.getInstance().clearTotalDuration(); + this.setArkTSAst(script); + console.log('[MEMO PLUGIN] AFTER CHECKED EXIT'); + return script; + } + console.log('[MEMO PLUGIN] AFTER CHECKED EXIT WITH NO TRANSFORM'); + return undefined; +} + +function checkedProgramVisit(program: arkts.Program, context: PluginContext): arkts.Program { + if (program.canSkipPhases()) { + debugLog('[SKIP PHASE] phase: memo-checked, moduleName: ', program.moduleName); + } else { + debugLog('[CANT SKIP PHASE] phase: memo-checked, moduleName: ', program.moduleName); + const positionalIdTracker = new PositionalIdTracker(arkts.getFileName(), false); + const parameterTransformer = new ParameterTransformer({ positionalIdTracker }); + const returnTransformer = new ReturnTransformer(); + const signatureTransformer = new SignatureTransformer(); + const functionTransformer = new FunctionTransformer({ + positionalIdTracker, + parameterTransformer, + returnTransformer, + signatureTransformer, + }); + const programVisitor = new ProgramVisitor({ + pluginName: unmemoizeTransform.name, + state: arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, + visitors: [functionTransformer], + skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, + pluginContext: context, + }); + program = programVisitor.programVisitor(program); + } + return program; +} diff --git a/arkui-plugins/ui-plugins/index.ts b/arkui-plugins/ui-plugins/index.ts index a50014ecfaaa4482de0f3059feb2b273b93a3327..e1131f9469b07db5ae9b4bed03af42299e69bea7 100644 --- a/arkui-plugins/ui-plugins/index.ts +++ b/arkui-plugins/ui-plugins/index.ts @@ -50,16 +50,7 @@ function parsedTransform(this: PluginContext): arkts.EtsScript | undefined { program.fileNameWithExtension ); arkts.Performance.getInstance().createEvent('ui-parsed'); - const componentTransformer = new ComponentTransformer(); - const preprocessorTransformer = new PreprocessorTransformer(); - const programVisitor = new ProgramVisitor({ - pluginName: uiTransform.name, - state: arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, - visitors: [componentTransformer, preprocessorTransformer], - skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, - pluginContext: this, - }); - program = programVisitor.programVisitor(program); + program = parsedProgramVisit(program, this); script = program.astNode; arkts.Performance.getInstance().stopEvent('ui-parsed', false); debugLog('[AFTER PARSED SCRIPT] script: ', script.dumpSrc()); @@ -78,6 +69,25 @@ function parsedTransform(this: PluginContext): arkts.EtsScript | undefined { return script; } +function parsedProgramVisit(program: arkts.Program, context: PluginContext): arkts.Program { + if (program.canSkipPhases()) { + debugLog('[SKIP PHASE] phase: ui-parsed, moduleName: ', program.moduleName); + } else { + debugLog('[CANT SKIP PHASE] phase: ui-parsed, moduleName: ', program.moduleName); + const componentTransformer = new ComponentTransformer(); + const preprocessorTransformer = new PreprocessorTransformer(); + const programVisitor = new ProgramVisitor({ + pluginName: uiTransform.name, + state: arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, + visitors: [componentTransformer, preprocessorTransformer], + skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, + pluginContext: context, + }); + program = programVisitor.programVisitor(program); + } + return program; +} + function checkedTransform(this: PluginContext): arkts.EtsScript | undefined { let script: arkts.EtsScript | undefined; console.log('[UI PLUGIN] AFTER CHECKED ENTER'); @@ -95,15 +105,7 @@ function checkedTransform(this: PluginContext): arkts.EtsScript | undefined { program.fileNameWithExtension ); arkts.Performance.getInstance().createEvent('ui-checked'); - const checkedTransformer = new CheckedTransformer(this.getProjectConfig()); - const programVisitor = new ProgramVisitor({ - pluginName: uiTransform.name, - state: arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, - visitors: [checkedTransformer], - skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, - pluginContext: this, - }); - program = programVisitor.programVisitor(program); + program = checkedProgramVisit(program, this); script = program.astNode; arkts.Performance.getInstance().stopEvent('ui-checked', false); debugLog('[AFTER STRUCT SCRIPT] script: ', script.dumpSrc()); @@ -128,3 +130,21 @@ function checkedTransform(this: PluginContext): arkts.EtsScript | undefined { console.log('[UI PLUGIN] AFTER CHECKED EXIT WITH NO TRANSFORM'); return script; } + +function checkedProgramVisit(program: arkts.Program, context: PluginContext): arkts.Program { + if (program.canSkipPhases()) { + debugLog('[SKIP PHASE] phase: ui-checked, moduleName: ', program.moduleName); + } else { + debugLog('[CANT SKIP PHASE] phase: ui-checked, moduleName: ', program.moduleName); + const checkedTransformer = new CheckedTransformer(context.getProjectConfig()); + const programVisitor = new ProgramVisitor({ + pluginName: uiTransform.name, + state: arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, + visitors: [checkedTransformer], + skipPrefixNames: EXTERNAL_SOURCE_PREFIX_NAMES, + pluginContext: context, + }); + program = programVisitor.programVisitor(program); + } + return program; +} diff --git a/koala-wrapper/native/src/common.cc b/koala-wrapper/native/src/common.cc index 553a1079b72f7767f317fe0025f0a384f66bb1b7..123c028dc551434d55849ee4c35dfd4c8821a86f 100644 --- a/koala-wrapper/native/src/common.cc +++ b/koala-wrapper/native/src/common.cc @@ -40,6 +40,10 @@ static es2panda_Impl *impl = nullptr; #endif const char* LIB_ES2PANDA_PUBLIC = LIB_PREFIX "es2panda_public" LIB_SUFFIX; +constexpr const char* IS_UI_FLAG = "IS_UI_FLAG"; +constexpr const char* NOT_UI_FLAG = "NOT_UI_FLAG"; +const string MODULE_SUFFIX = ".d.ets"; +const string ARKUI = "arkui"; #ifdef KOALA_WINDOWS const char *SEPARATOR = "\\"; @@ -297,6 +301,43 @@ KNativePointer impl_AstNodeChildren( } KOALA_INTEROP_2(AstNodeChildren, KNativePointer, KNativePointer, KNativePointer) +static bool isUIHeaderFile(es2panda_Context* context, es2panda_Program* program) +{ + auto result = GetImpl()->ProgramFileNameWithExtensionConst(context, program); + string fileNameWithExtension(result); + result = GetImpl()->ProgramModuleNameConst(context, program); + string moduleName(result); + + return fileNameWithExtension.length() >= MODULE_SUFFIX.length() + && fileNameWithExtension.substr(fileNameWithExtension.length() - MODULE_SUFFIX.length()) == MODULE_SUFFIX + && moduleName.find(ARKUI) != std::string::npos; +} + +KBoolean impl_ProgramCanSkipPhases(KNativePointer context, KNativePointer program) +{ + KStringPtr isUiFlag(IS_UI_FLAG); + KStringPtr notUiFlag(NOT_UI_FLAG); + const auto _context = reinterpret_cast(context); + const auto _program = reinterpret_cast(program); + if (isUIHeaderFile(_context, _program)) { + return false; + } + std::size_t sourceLen; + const auto externalSources = reinterpret_cast + (GetImpl()->ProgramExternalSources(_context, _program, &sourceLen)); + for (std::size_t i = 0; i < sourceLen; ++i) { + std::size_t programLen; + auto programs = GetImpl()->ExternalSourcePrograms(externalSources[i], &programLen); + for (std::size_t j = 0; j < programLen; ++j) { + if (isUIHeaderFile(_context, programs[j])) { + return false; + } + } + } + return true; +} +KOALA_INTEROP_2(ProgramCanSkipPhases, KBoolean, KNativePointer, KNativePointer) + /* ----------------------------------------------------------------------------------------------------------------------------- */ diff --git a/koala-wrapper/src/Es2pandaEnums.ts b/koala-wrapper/src/Es2pandaEnums.ts index bf2ce0783871630fbd77266c141a40a831a094df..6a16486a7bb965c1989e4a0bf594bb8710969746 100644 --- a/koala-wrapper/src/Es2pandaEnums.ts +++ b/koala-wrapper/src/Es2pandaEnums.ts @@ -181,7 +181,7 @@ export enum Es2pandaAstNodeType { AST_NODE_TYPE_OBJECT_PATTERN, AST_NODE_TYPE_SPREAD_ELEMENT, AST_NODE_TYPE_REST_ELEMENT, -} +}; export enum Es2pandaImportFlags { IMPORT_FLAGS_NONE, diff --git a/koala-wrapper/src/Es2pandaNativeModule.ts b/koala-wrapper/src/Es2pandaNativeModule.ts index 6c5b48e7d330356d41d068180c0b263f13838de7..99942dce5aa63f75dfeb0163f0bf34daa940dc77 100644 --- a/koala-wrapper/src/Es2pandaNativeModule.ts +++ b/koala-wrapper/src/Es2pandaNativeModule.ts @@ -750,6 +750,10 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } + _ProgramCanSkipPhases(context: KNativePointer, program: KNativePointer): boolean { + throw new Error('Not implemented'); + } + _GenerateTsDeclarationsFromContext( config: KPtr, outputDeclEts: String, diff --git a/koala-wrapper/src/arkts-api/peers/Program.ts b/koala-wrapper/src/arkts-api/peers/Program.ts index 5734dc4a49c3cd7ea1d897d1f00920d5dd032ab5..5a1099473210b4ccbb95a313cbf58b69208dfdea 100644 --- a/koala-wrapper/src/arkts-api/peers/Program.ts +++ b/koala-wrapper/src/arkts-api/peers/Program.ts @@ -19,9 +19,18 @@ import { acceptNativeObjectArrayResult, unpackString } from "../utilities/privat import { KNativePointer } from "@koalaui/interop" import { EtsScript } from "../types" +enum SkipPhaseResult { + NOT_COMPUTED, + CAN_SKIP, + CANNOT_SKIP, +} + export class Program extends ArktsObject { + private canSkipPhaseResult: SkipPhaseResult; + constructor(peer: KNativePointer) { super(peer); + this.canSkipPhaseResult = SkipPhaseResult.NOT_COMPUTED; } get astNode(): EtsScript { @@ -61,6 +70,21 @@ export class Program extends ArktsObject { isASTLowered(): boolean { return global.es2panda._ProgramIsASTLoweredConst(global.context, this.peer); } + + canSkipPhases(): boolean { + if (this.canSkipPhaseResult === SkipPhaseResult.CAN_SKIP) { + return true; + } else if (this.canSkipPhaseResult === SkipPhaseResult.CANNOT_SKIP) { + return false; + } + if (global.es2panda._ProgramCanSkipPhases(global.context, this.peer)) { + this.canSkipPhaseResult = SkipPhaseResult.CAN_SKIP; + return true; + } else { + this.canSkipPhaseResult = SkipPhaseResult.CANNOT_SKIP; + return false; + } + } } export class ExternalSource extends ArktsObject { diff --git a/koala-wrapper/src/arkts-api/utilities/public.ts b/koala-wrapper/src/arkts-api/utilities/public.ts index d7e2dfc3353ad0cd4acf5f2d4ea5013c493a8653..04ac973fe2a3f115265fd256ed11f74d7d1e5c9c 100644 --- a/koala-wrapper/src/arkts-api/utilities/public.ts +++ b/koala-wrapper/src/arkts-api/utilities/public.ts @@ -39,7 +39,7 @@ import { type AnnotationUsage, } from '../../generated'; import { Program } from '../peers/Program'; -import { clearNodeCache } from '../class-by-peer'; +import { clearNodeCache, nodeByType } from '../class-by-peer'; import { SourcePosition } from '../peers/SourcePosition'; import { MemberExpression } from '../to-be-generated/MemberExpression';