UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

320 lines 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformUnionTypeAnnotation = exports.hasParamNameOfAnonymousFunction = exports.checkParamNameOfAnonymousFunction = exports.getAncestorExistingVarNames = exports.getAncestorExistingParamNames = exports.AnonymousFnNode = exports.replaceNode = exports.officialCustoms = exports.waitPromise = exports.clearObjectDeep = exports.clearObject = exports.throttle = exports.findClosestModule = void 0; const nasl_concepts_1 = require("@lcap/nasl-concepts"); const nasl_utils_1 = require("@lcap/nasl-utils"); // 查找最近的模块 function findClosestModule(node) { let moduleNode = node; while (moduleNode && !['App', 'Module'].includes(moduleNode.concept)) { moduleNode = moduleNode.parentNode; } return moduleNode; } exports.findClosestModule = findClosestModule; /** * 用 lodash 的 throttle 好像有点问题,先临时做个处理 * @param func * @param wait * @param options */ const throttle = (func, wait, options) => func; exports.throttle = throttle; function clearObject(obj) { Object.keys(obj).forEach((key) => { if (obj[key] === undefined || obj[key] === null) delete obj[key]; }); } exports.clearObject = clearObject; function clearObjectDeep(obj) { (0, nasl_utils_1.traverse)((current) => { Object.keys(current.node).forEach((key) => { if (current.node[key] === null) delete current.node[key]; }); }, { node: obj, stack: [] }, { mode: 'anyObject' }); } exports.clearObjectDeep = clearObjectDeep; const waitPromise = (wait) => new Promise((res) => setTimeout(() => res(wait), wait)); exports.waitPromise = waitPromise; // 官方扩展组件暂时不包含 css 文件 exports.officialCustoms = [ 'u-sider-modal', 'timer-count-down', 'u-calendar-table', 'lcap-login', 'lcap-video', 'lcap-amap-nav', 'lcap-amap-poi', 'lcap-echarts-bar', 'lcap-echarts-line', 'lcap-echarts-pie', 'lcap-report', 'lcap-wang-editor', 'lcap-clock', ]; function replaceNode(oldNode, newNode) { const { parentNode, parentKey, offsetX, offsetY, app } = oldNode; const { logic } = oldNode; if (!Array.isArray(parentNode[parentKey])) { parentNode.update({ [parentKey]: newNode, }); } else { // 虽然如果不在参数里使用属性访问没有意义,但是得兼容 app.emit('collect:start', { actionMsg: '删除属性变量', }); if (parentNode.concept === 'Logic') { if (parentKey === 'body') { const expIndex = logic.body.findIndex((item) => item === oldNode); logic.insertItemInBodyAt(newNode, expIndex); } else { const expIndex = logic.playground.findIndex((item) => item === oldNode); Object.assign(newNode, { offsetX, offsetY }); logic.insertItemInPlaygroundAt(newNode, expIndex); } } else { const expIndex = parentNode[parentKey].findIndex((item) => item === oldNode); const firstUpperText = parentKey[0].toUpperCase() + parentKey.slice(1, parentKey.length); if (parentNode[`insertItemIn${firstUpperText}At`]) parentNode[`insertItemIn${firstUpperText}At`](newNode, expIndex); else parentNode.insertItemAt(newNode, expIndex); } oldNode.delete(); app.emit('collect:end'); } } exports.replaceNode = replaceNode; class AnonymousFnNode { } exports.AnonymousFnNode = AnonymousFnNode; /** * 收集匿名函数 * @param param0 * @returns */ function collectAnonymousFn({ anonymousFnNode, cb }) { const descendantsAnonyList = cb(anonymousFnNode); const { node } = anonymousFnNode; const propertyMap = (0, nasl_concepts_1.getConceptPropertyMap)(node?.concept); if (!propertyMap) { return; } for (const property of propertyMap.keys()) { const child = node[property]; if (!child) { continue; } else if (Array.isArray(child)) { child.forEach((node) => collectAnonymousFn({ anonymousFnNode: { node, descendants: descendantsAnonyList }, cb })); } else { collectAnonymousFn({ anonymousFnNode: { node: child, descendants: descendantsAnonyList }, cb }); } } } function getAnonymousFnNodes(node) { const anonymousFnNodes = []; // 1.匿名函数可能在里层,如:ListDistinctBy // 2.存在多级匿名数据结构 collectAnonymousFn({ anonymousFnNode: { node, descendants: anonymousFnNodes }, cb: (anonymousFnNode) => { const { node, descendants } = anonymousFnNode; if (node?.concept === 'AnonymousFunction') { const newAnonymousNode = { node, descendants: [], }; descendants?.push(newAnonymousNode); return newAnonymousNode.descendants; } return descendants; } }); return anonymousFnNodes; } /** * 父链上存在的参数名字 * @returns */ function getAncestorExistingParamNames(baseNode) { let node = baseNode; const names = new Set(); while (node) { node = node.parentNode; switch (node?.concept) { case 'AnonymousFunction': node.params.forEach((param) => { names.add(param.name); }); break; case 'Logic': case 'View': const varList = [ ...(node.params || []), ]; varList?.forEach((variable) => { names.add(variable?.name); }); break; } } return names; } exports.getAncestorExistingParamNames = getAncestorExistingParamNames; /** * 父链上存在的变量名字 * @returns */ function getAncestorExistingVarNames(baseNode) { let node = baseNode; const names = new Set(); while (node) { node = node.parentNode; switch (node?.concept) { case 'AnonymousFunction': node.params.forEach((param) => { names.add(param.name); }); break; case 'ForEachStatement': names.add(node.item?.name); names.add(node.index?.name); break; case 'Logic': case 'View': const varList = [ ...(node.params || []), ...(node.returns || []), ...(node.variables || []) ]; varList?.forEach((variable) => { names.add(variable?.name); }); break; } } return names; } exports.getAncestorExistingVarNames = getAncestorExistingVarNames; /** * 确保匿名函数的参数名称都是不重复的,且更新内部的引用关系 * @param param0 */ function ensureAnonymousFnsParamName({ ancestorParamNames, anonymousFnNodes, }) { const paramInfoMapList = []; anonymousFnNodes.forEach((anonymousFnNode) => { const { node: anonymousFn, descendants } = anonymousFnNode || {}; const tempParamInfoMap = anonymousFn?.ensureParamName(ancestorParamNames); paramInfoMapList.push(tempParamInfoMap); if (Array.isArray(descendants)) { const paramNames = new Set([...ancestorParamNames]); tempParamInfoMap.forEach((value) => { paramNames.add(value.newName); }); const descendantTempParamInfoMap = ensureAnonymousFnsParamName({ ancestorParamNames: paramNames, anonymousFnNodes: descendants, }); paramInfoMapList.push(...descendantTempParamInfoMap); } }); return paramInfoMapList; } /** * 校验匿名函数的局部变量是否重名 */ function checkParamNameOfAnonymousFunction(node) { const anonymousFnNodes = getAnonymousFnNodes(node); // 从外到里计算更改的name const paramInfoMapList = ensureAnonymousFnsParamName({ ancestorParamNames: getAncestorExistingVarNames(node), anonymousFnNodes }); paramInfoMapList?.forEach((paramInfoMap) => { paramInfoMap.forEach((paramInfo) => { const { newName, param, identifiers } = paramInfo || {}; param?.update({ name: newName, }); if (Array.isArray(identifiers)) { identifiers.forEach((identifier) => { identifier?.update({ name: newName, }); }); } }); }); } exports.checkParamNameOfAnonymousFunction = checkParamNameOfAnonymousFunction; // 获取内部匿名函数的局部变量 function collectAnonymousFnNodesParams(node) { const paramNames = new Set(); const anonymousFnNodes = getAnonymousFnNodes(node); if (Array.isArray(anonymousFnNodes)) { anonymousFnNodes.forEach((anonymousFnNode) => { const { node: anonymousFn, descendants } = anonymousFnNode || {}; anonymousFn.params.forEach((param) => { paramNames.add(param.name); }); if (Array.isArray(descendants)) { descendants.forEach(({ node: descendantNode }) => { const descendantParamNames = collectAnonymousFnNodesParams(descendantNode); descendantParamNames.forEach((descendantParamName) => { paramNames.add(descendantParamName); }); }); } }); } return paramNames; } /** * 新的参数名是否存在同名 * @param param0 */ function hasParamNameOfAnonymousFunction({ node, newName, }) { const ancestorParamNames = getAncestorExistingVarNames(node); const anonymousFnNodesParams = collectAnonymousFnNodesParams(node); const paramNames = new Set([...ancestorParamNames.values(), ...anonymousFnNodesParams.values()]); return paramNames.has(newName); } exports.hasParamNameOfAnonymousFunction = hasParamNameOfAnonymousFunction; function transformUnionTypeAnnotation(expTypeAnnotation, app) { // 针对union类型,typeAnntatation拿不到app数据,暂时先在这里处理 if (expTypeAnnotation?.typeKind === 'union' && expTypeAnnotation?.typeArguments?.length) { expTypeAnnotation?.typeArguments?.forEach((typeArg) => { if (typeArg.typeNamespace?.endsWith('.metadataTypes')) { const referenceNode = app?.findNodeByCompleteName(typeArg.typeNamespace + '.' + typeArg.typeName)?.typeAnnotation || {}; typeArg.typeName = referenceNode.typeName; typeArg.typeKind = referenceNode.typeKind; typeArg.typeNamespace = referenceNode.typeNamespace; } }); } } exports.transformUnionTypeAnnotation = transformUnionTypeAnnotation; //# sourceMappingURL=node.js.map