UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

557 lines 26.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.upgrade = exports.push = void 0; const nasl = __importStar(require("@lcap/nasl")); const clearObject = (obj) => { Object.keys(obj).forEach((key) => { delete obj[key]; }); }; const cloneDeep = (obj) => JSON.parse(JSON.stringify(obj)); const excludedKeySet = new Set([ 'parentNode', 'sourceMap', 'storageJSON', 'tsErrorDetail', 'NaslAnnotatedJSON', 'calledFrom', '_events', '_collectingList', '_historyList', ]); // export function replace(script) { // return script // .replace(/_set\([a-zA-Z0-9_]+?, "typeNamespace", t_Structure_Load[a-zA-Z0-9_]+?Structure_\d+\.getNamespace\(\).+updatedObj; \}\);/g, '') // .replace(/_set\([a-zA-Z0-9_]+?, "typeName", t_Structure_Load[a-zA-Z0-9_]+?Structure_\d+\.name.+updatedObj; \}\);/g, ''); // } function push(parent, key, item, virtualApp) { if (item.concept === 'Structure' && item.origin === 'CallQueryComponent' || /^Load[a-zA-Z0-9_]+Structure\d*$/.test(item.name)) { item.parentNode = virtualApp; item.parentKey = key; return false; } } exports.push = push; /** * 升级要点: * - 去除 CallQueryComponent 产生的 Structure * - 替换流程名称 * - 修复流程 Identifier 的错误 * - 去除流程中 PageOf 的相关赋值 * - 替换 CallQueryComponent 产生 Structure 的类型标注 * - 替换 PageOf 到匿名数据结构 * - 去除页面和逻辑的 PageOf 类型 * - PageOf 的属性分析 * - CreatePageOf -> CreateListPage * - ListSliceToPageOf -> SliceToListPage * - scope -> current * - ScopeOf -> Current * - 事件逻辑收集 * - 事件逻辑处理 * @param json 升级前的 JSON * @returns 升级后的 JSON */ function upgrade(json) { const aStructureMap = {}; for (let i = 0; i < json.structures.length; i++) { const item = json.structures[i]; if (item.origin === 'CallQueryComponent' || /^Load[a-zA-Z0-9_]+Structure\d*$/.test(item.name)) { aStructureMap[item.name] = { concept: 'TypeAnnotation', typeKind: 'anonymousStructure', properties: cloneDeep(item.properties), }; // console.log(item.name); json.structures.splice(i, 1); i--; } } let viewPageOfMap = {}; let logicPageOfMap = {}; const replaceMap = { scope: 'params', TaskList: 'taskList', ProcessInstance: 'processInstance', MiddleInstance: 'middleInstance', PorcessIdIn: 'processIdIn', StartByPorcessInstanceList: 'startByProcessInstanceList', ProcessList: 'processList', }; nasl.utils.traverse((current) => { const { node, parent, stack } = current; { // Process PageOf if (node.name === 'loadMylaunchProcess') { node.name = 'loadMyLaunchProcess'; } if (node.concept === 'Logic' && (node.name === 'loadMyTaskList' || node.name === 'loadMyLaunchProcess')) { nasl.utils.traverse((current2) => { if (current2.node.concept === 'Identifier' && current2.node.name.includes('.')) { const arr = current2.node.name.split('.'); delete current2.node.name; if (arr.length === 2) { Object.assign(current2.node, { concept: 'MemberExpression', folded: false, object: { concept: 'Identifier', name: arr[0], folded: false, }, property: { concept: 'Identifier', name: arr[1], folded: false, }, }); } else if (arr.length === 3) { Object.assign(current2.node, { concept: 'MemberExpression', folded: false, object: { concept: 'MemberExpression', folded: false, object: { concept: 'Identifier', name: arr[0], folded: false, }, property: { concept: 'Identifier', name: arr[1], folded: false, }, }, property: { concept: 'Identifier', name: arr[2], folded: false, }, }); } else { console.log(arr, arr.length); } } if (replaceMap[current2.node.name]) current2.node.name = replaceMap[current2.node.name]; }, { node }, { mode: 'anyObject', depthFirst: true, excludedKeySet }); const result = node.returns[0]; const assignment = { concept: 'Assignment', label: '赋值', folded: false, left: { concept: 'Identifier', name: 'result', folded: false, }, right: { concept: 'CallFunction', label: '内置函数', folded: false, calleeNamespace: 'nasl.util', calleeName: 'CreateListPage', typeArguments: [], arguments: [ { concept: 'Argument', folded: false, keyword: 'list', expression: { concept: 'CallFunction', label: '内置函数', folded: false, offsetX: 305, offsetY: 2040, calleeNamespace: 'nasl.util', calleeName: 'New', typeArguments: [ { concept: 'TypeAnnotation', branchName: null, workingCopy: null, branch: null, typeKind: 'generic', typeNamespace: 'nasl.collection', typeName: 'List', typeArguments: cloneDeep(result.typeAnnotation.typeArguments), inferred: null, properties: null, ruleMap: null, }, ], arguments: [], }, }, { concept: 'Argument', folded: false, keyword: 'total', expression: { concept: 'MemberExpression', folded: false, object: { concept: 'Identifier', name: node.name === 'loadMyTaskList' ? 'taskList' : 'processList', folded: false, }, property: { concept: 'Identifier', name: 'total', folded: false, }, }, }, ], }, }; node.body.splice(node.name === 'loadMyTaskList' ? 3 : 2, 8, assignment); } } { // PageOf if (node.concept === 'TypeAnnotation' && node.typeKind === 'generic' && node.typeName === 'PageOf') { Object.assign(node, { typeKind: 'anonymousStructure', typeNamespace: null, typeName: null, typeArguments: [], inferred: false, ruleMap: null, properties: [{ concept: 'StructureProperty', name: 'list', label: null, description: null, typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'generic', typeNamespace: 'nasl.collection', typeName: 'List', typeArguments: cloneDeep(node.typeArguments), inferred: null, }, required: null, defaultValue: null, }, { concept: 'StructureProperty', name: 'total', label: null, description: null, typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'primitive', typeNamespace: 'nasl.core', typeName: 'Integer', typeArguments: null, inferred: null, }, required: null, defaultValue: null, }], }); } else if (node.concept === 'TypeAnnotation' && aStructureMap[node.typeName]) { Object.assign(node, { typeKind: 'anonymousStructure', typeNamespace: null, typeName: null, typeArguments: [], inferred: false, ruleMap: null, properties: cloneDeep(aStructureMap[node.typeName].properties), }); } if (node.concept === 'View') { viewPageOfMap = {}; node.params.forEach((item) => { if (item.typeAnnotation.typeKind === 'generic' && item.typeAnnotation.typeName === 'PageOf') { viewPageOfMap[item.name] = true; item.typeAnnotation = null; console.log(`Warning: param ${item.name} 的类型是 PageOf`); } }); node.variables.forEach((item) => { if (item.typeAnnotation.typeKind === 'generic' && item.typeAnnotation.typeName === 'PageOf') { viewPageOfMap[item.name] = true; item.typeAnnotation = null; } }); } if (node.concept === 'Logic') { logicPageOfMap = {}; node.params.forEach((item) => { if (item.typeAnnotation.typeKind === 'generic' && item.typeAnnotation.typeName === 'PageOf') { logicPageOfMap[item.name] = true; item.typeAnnotation = null; console.log(`Warning: param ${item.name} 的类型是 PageOf`); } }); [...node.returns, ...node.variables].forEach((item) => { if (item.typeAnnotation.typeKind === 'generic' && item.typeAnnotation.typeName === 'PageOf') { logicPageOfMap[item.name] = true; item.typeAnnotation = null; // xxx = some() 就没问题 // xxx.content = xxx 的时候会有问题 } }); } if (node.concept === 'MemberExpression' && node.object.concept === 'Identifier' && (logicPageOfMap[node.object.name] || viewPageOfMap[node.object.name])) { const reversedStack = stack.reverse(); const logic = reversedStack.find((item) => item.concept === 'Logic'); const view = reversedStack.find((item) => item.concept === 'View'); if (!logic && logicPageOfMap[node.object.name]) return; if (node.property.name === 'content') node.property.name = 'list'; else if (node.property.name === 'totalElements') node.property.name = 'total'; else if (node.property.name === 'empty') { // 用来判断空的 const memberObject = node.object; clearObject(node); Object.assign(node, { concept: 'BinaryExpression', folded: false, left: { concept: 'MemberExpression', folded: false, object: memberObject, property: { concept: 'Identifier', name: 'total', folded: false, }, }, right: { concept: 'NumericLiteral', folded: false, value: '0', typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'primitive', typeNamespace: 'nasl.core', typeName: 'Integer', typeArguments: null, properties: null, }, }, operator: '==', }); } else if (node.property.name === 'total' || node.property.name === 'list') { // } else { console.log(`Error: 使用了超范围的 PageOf 属性 ${node.property.name}`); // content: nasl.collection.List<T>; // number: nasl.core.Integer; // size: nasl.core.Integer; // numberOfElements: nasl.core.Integer; // last: nasl.core.Boolean; // totalPages: nasl.core.Integer; // first: nasl.core.Boolean; // empty: nasl.core.Boolean; // totalElements: nasl.core.Integer; } } } { if (node.concept === 'CallFunction') { if (node.calleeName === 'CreatePageOf') { node.calleeName = 'CreateListPage'; node.arguments = [node.arguments[0], node.arguments[3]]; } if (node.calleeName === 'ListSliceToPageOf') { node.calleeName = 'SliceToListPage'; } if (node.calleeName === 'ListFindAll') { node.calleeName = 'ListFilter'; if (node.arguments[1]) { const func = node.arguments[1].expression; func.concept = 'AnonymousFunction'; delete func.typeParams; delete func.returns; delete func.variables; func.body = func.returnExpression; delete func.returnExpression; } } } } { // 事件逻辑 // 根据 calleeName 的次数 if (!node.calleeNamespace && node.calleeName) { const reversedStack = stack.slice().reverse(); const view = reversedStack.find((item) => item.concept === 'View'); const bindEvent = reversedStack.find((item) => item.concept === 'BindEvent'); if (view) { const logic = view.logics.find((logic) => logic.name === node.calleeName); if (!logic) { console.log(node.calleeName, view.name, reversedStack.map((a) => `${a.concept}:${a.name}`)); } else { logic.calledFrom = logic.calledFrom || []; logic.calledFrom.push({ node, parent, bindEvent, }); } } } if (node.concept === 'BindAttribute' && node.name === 'data-source' && node.expression && node.expression.concept === 'Identifier') { const reversedStack = stack.slice().reverse(); const view = reversedStack.find((item) => item.concept === 'View'); if (view) { const logic = view.logics.find((logic) => logic.name === node.expression.name); if (!logic) { // 好多是变量 // console.log(node.expression.name, view.name, reversedStack.map((a) => `${a.concept}:${a.name}`)); } else { logic.calledFrom = logic.calledFrom || []; logic.calledFrom.push({ node, parent, dataSource: true, }); } } } } { // ScopeOf if (node.concept === 'Identifier' && /^scope(\d*)$/g.test(node.name) && (parent.object === node || parent.expression === node)) { node.name = node.name.replace(/^scope(\d*)$/g, (m, $1) => 'current' + $1); } if (node.concept === 'Param' && /^scope(\d*)$/g.test(node.name)) { node.name = node.name.replace(/^scope(\d*)$/g, (m, $1) => 'current' + $1); } if (node.concept === 'ViewElement' && /^scope(\d*)$/g.test(node.slotScope)) { node.slotScope = node.slotScope.replace(/^scope(\d*)$/g, (m, $1) => 'current' + $1); } if (node.concept === 'TypeAnnotation' && node.typeKind === 'generic' && node.typeName === 'ScopeOf') { node.typeName = 'Current'; } if (node.concept === 'Unparsed' && /scope(\d*)\./g.test(node.code)) { node.code = node.code.replace(/scope(\d*)\./g, (m, $1) => 'current' + $1 + '.'); } } }, { node: json }, { mode: 'anyObject', depthFirst: true, excludedKeySet }); nasl.utils.traverse((current) => { const { node, parent, stack } = current; if (node.concept !== 'View') return; for (let i = 0; i < node.logics.length; i++) { const logic = node.logics[i]; const hasCurrent = logic.params.find((param) => param.name.startsWith('current')); if (logic.calledFrom) { if (!logic.calledFrom[0].dataSource // 不在数据源中使用 && (logic.calledFrom.length < 2 && !!logic.calledFrom[0].bindEvent // 没有被复用且在事件逻辑中被调用了 || logic.params[0] && logic.params[0].name === 'event' // 或者第一个为 event || hasCurrent // 或者后面包含了 current )) { const calledFrom = logic.calledFrom; calledFrom.forEach(({ node: callLogic, parent: eventLogic }) => { if (eventLogic.concept !== 'Logic') { console.log('eventLogic.concept', eventLogic.concept); return; } const index = eventLogic.body.indexOf(callLogic); if (~index) { eventLogic.body.splice(index, 1, ...logic.body.slice(1, -1)); eventLogic.variables.push(...logic.variables); } }); node.logics.splice(i, 1); i--; } // else if (hasCurrent) { // node.logics.splice(i, 1); // i--; // } } delete logic.calledFrom; } }, { node: { children: json.views } }, { mode: 'onlyChildren', depthFirst: true, excludedKeySet }); nasl.utils.traverse((current) => { const { node, parent, key, stack } = current; if (node.concept === 'CallQueryComponent' && !node.ideVersion) { const groupByLength = node.groupBy.filter((item) => item.groupElement?.propertyName).length; const aggregateLength = node.select.selectElements.filter((item) => item.concept === 'QueryAggregateExpression' && item.aggregateName).length; if (!groupByLength && (aggregateLength === 0 || aggregateLength > 1)) { node.ideVersion = '2.11'; if (node.typeAnnotation.properties && (node.typeAnnotation.properties.length !== 2 || node.typeAnnotation.properties[0].name !== 'list')) { node.typeAnnotation = { concept: 'TypeAnnotation', typeKind: 'anonymousStructure', typeNamespace: null, typeName: null, typeArguments: [], inferred: false, ruleMap: null, properties: [{ concept: 'StructureProperty', name: 'list', label: null, description: null, typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'generic', typeNamespace: 'nasl.collection', typeName: 'List', typeArguments: [cloneDeep(node.typeAnnotation)], inferred: null, }, required: null, defaultValue: null, }, { concept: 'StructureProperty', name: 'total', label: null, description: null, typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'primitive', typeNamespace: 'nasl.core', typeName: 'Integer', typeArguments: null, inferred: null, }, required: null, defaultValue: null, }], }; } } else { node.ideVersion = '2.10'; } } }, { node: json }, { mode: 'anyObject', depthFirst: true, excludedKeySet }); return json; } exports.upgrade = upgrade; //# sourceMappingURL=2.17.js.map