UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

175 lines 8.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.incrementalAnnotationByCache = void 0; const nasl_concepts_1 = require("@lcap/nasl-concepts"); const nasl_utils_1 = require("@lcap/nasl-utils"); const service_1 = require("@lcap/nasl-concepts/service"); const nasl_language_server_core_1 = require("@lcap/nasl-language-server-core"); const patch_1 = require("./patch"); const types_1 = require("./types"); const utils_1 = require("./utils"); /** 增量标注 */ async function incrementalAnnotationByCache(app, server, naslCacheData, moduleGraphCache, logger = nasl_utils_1.internalLogger) { await logger.info(utils_1.LogEventName, '开始进行增量标注'); // 这里因为没有调用 OpenApp 所以必须要手动添加 app.naslServer = server; const moduleGraph = nasl_language_server_core_1.ModuleGraph.fromNaslData(app); const moduleGraphCacheMap = (0, utils_1.moduleGraphCacheToMap)(moduleGraphCache); await logger.info(utils_1.LogEventName, '生成模块图成功'); const setAnnotationNode = async (node) => { const fullTsFile = await (0, nasl_utils_1.runGeneratorAsync)(node.toEmbeddedTSFile()); // @ts-ignore node.sourceMap = fullTsFile.sourceMap; server.file2NodeMap.set(fullTsFile.filePath, node); return { fileContent: fullTsFile.code, file: fullTsFile.filePath, }; }; const getNaslNodeCache = (node) => { const { nodePath } = node; const cacheNode = (0, nasl_concepts_1.findNodeObjectByPath)(naslCacheData, nodePath); if (cacheNode?.concept === node.concept) { return cacheNode; } }; const getModuleCache = (nodePath) => { return moduleGraphCacheMap.get(nodePath); }; const isSameDependency = (dep1, dep2) => { if (dep1.length !== dep2.length) { return false; } const dep1Set = new Set(dep1); return dep2.every((key) => dep1Set.has(key)); }; const useCacheAnnotation = (mod, currentCacheNode) => { const { name: nodePath, node: currentNode } = mod; if (!currentNode || !currentCacheNode) { throw new Error(`错误的节点路径:${nodePath}`); } // TODO: 没有必要迭代所有节点,可以想办法按照 nodePath 记录模块的子树,然后想办法在最后拼起来 (0, service_1.traverseChildrenByModule)({ ...currentCacheNode, name: nodePath }, (cacheNode, cacheNodePath) => { // 类型子树跳过 if (cacheNode.concept === 'TypeAnnotation') { return true; } // 当前缓存的类型子树 const typeAnnotationData = cacheNode.typeAnnotation ?? cacheNode.__TypeAnnotation; if (!typeAnnotationData && !patch_1.patchNodeSet.has(cacheNodePath)) { return; } const current = app.findNodeByPath(cacheNodePath); // 当前节点不存在,或者当前节点本来就有类型时 if (!current || current.typeAnnotation) { return; } if (patch_1.patchNodeSet.has(cacheNode.concept)) { (0, patch_1.patch)(current, cacheNode, app, naslCacheData); } if (typeAnnotationData) { current.typeAnnotation = typeAnnotationData; } }); }; // 小于 0 时需要设置为 0 const getModifyTime = (time = 0) => { return time < 0 ? 0 : time; }; await logger.info(utils_1.LogEventName, '增量标注开始,进度 0%...'); /** 类型缓存 */ const typesMapCache = new Map(); /** 所有模块 */ const allModules = moduleGraph.getModules(); /** 总模块节点计数 */ const totalModuleCount = allModules.reduce((ans, item) => ans + item.count, 0); /** 当前模块节点技术 */ let currentModuleCount = 0; /** 写入文件等待 */ let transformAwait = Promise.resolve(); const modules = await moduleGraph.topologicalSort({ async getModulesSignature(modules, getModuleStatus) { if (modules.length === 0) { throw types_1.IncrementalErrorCode.CircularModule; } /** 待标注的节点 */ const annotationModules = []; /** 当前的 TS 文件 */ const tsFiles = []; for (const mod of modules) { const { node } = mod; const { nodePath } = node; const nodeCache = getNaslNodeCache(node); const moduleCache = nodeCache ? getModuleCache(nodePath) : undefined; const modDepModules = mod.getDependencyModules().map((item) => item.dependency); // 模块需要重新标注 if ( // 无节点缓存表示是新节点 !nodeCache || // 无模块缓存表示是新模块 !moduleCache || // 有节点缓存但最后修改时间不一致 getModifyTime(moduleCache?.lastModifyTime) !== getModifyTime(mod.lastModifyTime) || // 有模块缓存但是依赖变更 !isSameDependency(moduleCache.dependency ?? [], modDepModules.map((item) => item.name)) || // 有模块缓存,依赖也没变,但是有依赖的签名改变 modDepModules.some((dep) => getModuleStatus(dep) === nasl_language_server_core_1.ModuleStatusInTopologicalSort.VisitedWithModify)) { const data = await setAnnotationNode(node); tsFiles.push(data); annotationModules.push(mod); } // 使用缓存 else { const tsFile = mod.node.getEmbeddedFilePath(); const tsContent = moduleCache.signature; tsFiles.push({ file: tsFile, fileContent: tsContent }); mod.updateSignature(tsContent); useCacheAnnotation(mod, nodeCache); } } if (annotationModules.length > 0) { // 要等待上次写入完成 await transformAwait; await server.writeFiles(tsFiles); const types = await server.annotationFiles(annotationModules .map(({ node }) => node) .filter((node) => !(0, service_1.isIgnoreFullAnnotationFileNode)(node))); // 合并类型缓存 for (const [node, type] of types) { // 这里在 NaslServer 中似乎是种特别的兼容处理,暂时保留 if (type && 'typeAnnotation' in type && type.typeAnnotation) { typesMapCache.set(node, type.typeAnnotation); } // type 可以是 null,不可以过滤,后续要继续处理的 else { typesMapCache.set(node, type); } } // 生成标注模块的签名 annotationModules.forEach((mod) => { mod.updateSignature(mod.node.toEmbeddedDeclarationTSFile().code); }); } else { // 并行写入文件 transformAwait = transformAwait.then(() => server.writeFiles(tsFiles)); } currentModuleCount += modules.reduce((ans, item) => ans + item.count, 0); await logger.info(utils_1.LogEventName, `增量标注进度:${(currentModuleCount / totalModuleCount * 100).toFixed(2)}%...`); return annotationModules; }, }); await logger.info(utils_1.LogEventName, '增量标注完成'); await logger.info(utils_1.LogEventName, '生成标注数据开始'); const annotationJson = (0, utils_1.getFullAnnotationData)(app, server, typesMapCache); await logger.info(utils_1.LogEventName, '生成标注数据结束'); return { isFull: modules.length === allModules.length, updatedModules: modules.map((item) => item.name), moduleGraph: moduleGraph.toData(), annotationData: annotationJson, isSkipFrontendGenerator: !modules.some((mod) => (0, utils_1.isFrontendNode)(mod.node)), }; } exports.incrementalAnnotationByCache = incrementalAnnotationByCache; //# sourceMappingURL=incremental.js.map