@lcap/nasl
Version:
NetEase Application Specific Language
557 lines • 26.3 kB
JavaScript
;
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