UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

352 lines 13.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformExpression2Nasl = void 0; const generator_1 = __importDefault(require("@babel/generator")); const utils_1 = require("./utils"); const transform_func2nasl_1 = require("./transform-func2nasl"); const transform_tstype2nasl_1 = __importDefault(require("./transform-tstype2nasl")); const concepts_1 = require("@lcap/nasl/concepts"); const natural_1 = require("../../../natural"); const getNamespace = (ast) => { if (ast.object && ast.object.name === 'nasl' && ast.property && ast.property.name) { return `nasl.${ast.property.name}`; } return ''; }; function transformObjectExpression2Nasl(ast) { const newMap = { concept: 'NewMap', keys: [], values: [], }; ast.properties.forEach((property) => { if (property.type === 'ObjectMethod' || property.type === 'SpreadElement' || property.key.type === 'PrivateName') { throw new Error(`解析Expression失败,nasl未支持该表达式, ${(0, utils_1.getNodeCode)(ast)}`); } newMap.keys.push(transformExpression2Nasl(property.key)); newMap.values.push(transformExpression2Nasl(property.value)); }); return newMap; } function getCallName(code) { let namespace = ''; let name = ''; const arr = code.split('.'); if (code.startsWith('$refs.')) { arr[0] = 'elements'; arr.splice(arr.length - 1, 0, 'logics'); } namespace = arr.slice(0, arr.length - 1).join('.'); name = arr[arr.length - 1]; const Entity = 'Entity'; if (namespace.endsWith(Entity)) { namespace = `${namespace.substring(0, namespace.lastIndexOf(Entity))}.logics`; } return { namespace, name }; } // 注:一键生成流程申请和审批页时的特殊处理,不确保通用 function transform2NewExpression(calleeName, ast) { const properties = []; const rights = []; const assignmentLines = []; const newProperties = ast?.arguments?.[0]?.properties?.filter((arg) => arg?.value?.type !== 'ConditionalExpression'); newProperties?.forEach((property, index) => { properties.push(transformExpression2Nasl(property.key)); if (property.value.type === 'MemberExpression') { let targetSelectMembers = rights?.[0]; if (!targetSelectMembers) { const newNode = { concept: 'SelectMembers', hideMembers: false, expression: { concept: 'Identifier', name: 'current', }, members: [ { concept: 'MemberExpression', object: { concept: 'Identifier', name: 'current', }, property: { concept: 'Identifier', name: 'item', }, }, ], }; targetSelectMembers = newNode; rights.push(targetSelectMembers); } const newMember = transformExpression2Nasl(property.value); newMember && targetSelectMembers.members.push(newMember); assignmentLines.push({ concept: 'AssignmentLine', leftIndex: [0, index], rightIndex: [0, targetSelectMembers.members.length - 1], }); } }); const parameters = ast?.typeParameters?.params?.[0]; if (parameters && parameters?.type === 'TSTypeReference' && parameters?.typeName?.type === 'TSQualifiedName') { const { left, right } = parameters?.typeName || {}; const typeNamespace = (0, generator_1.default)(left)?.code; const typeName = right?.name; let typeAnnotation; if (typeName?.includes('IDENTIFIER')) { typeAnnotation = undefined; } else { typeAnnotation = { concept: 'TypeAnnotation', typeKind: 'reference', typeNamespace, typeName, }; } return { concept: 'NewComposite', typeAnnotation, properties, rights, assignmentLines, }; } } // 注:一键生成流程申请和审批页时的特殊处理,不确保通用 function transformCallFunction2Nasl(calleeName, ast) { return { concept: 'CallFunction', calleeNamespace: 'nasl.util', calleeName, arguments: [ { concept: 'Argument', keyword: 'list', expression: ast?.arguments?.[0] && transformExpression2Nasl(ast.arguments[0]), }, { concept: 'Argument', keyword: 'item', expression: ast?.arguments?.[1] && transformExpression2Nasl(ast.arguments[1]), }, ], }; } function transformCallExpress2Nasl(ast) { if (ast.callee.type === 'Super' || ast.callee.type === 'V8IntrinsicIdentifier') { throw new Error(`解析CallExpression 失败,${(0, utils_1.getNodeCode)(ast)}`); } const code = (0, utils_1.getNodeCode)(ast.callee); const { namespace, name } = getCallName(code); const args = ast.arguments.map((arg) => { if (arg.type === 'JSXNamespacedName' || arg.type === 'SpreadElement' || arg.type === 'ArgumentPlaceholder') { throw new Error(`解析CallExpression 失败,不支持参数类型,${(0, utils_1.getNodeCode)(ast)}`); } return { concept: 'Argument', keyword: '', expression: transformExpression2Nasl(arg), }; }); const SHORTCUT_NAMES = ['consoleLog', 'jsonSerialize', 'jsonDeserialize']; if (namespace === 'nasl.util') { if (['Add', 'Remove'].includes(name)) return transformCallFunction2Nasl(name, ast); // list内置函数的特殊处理 if (['NewEntity'].includes(name)) return transform2NewExpression(name, ast); // 新建实体的特殊处理 return { concept: 'CallFunction', calleeNamespace: namespace, calleeName: name, shortcut: SHORTCUT_NAMES.indexOf(name) !== -1, arguments: args, typeArguments: ast.typeParameters ? ast.typeParameters.params.map((tsType) => (0, transform_tstype2nasl_1.default)(tsType)) : [], }; } if (namespace === 'nasl.processV2') { return transformCallLogic2ProcessV2(ast, namespace, name); } if (name === 'gotoLink') { return { concept: 'ExternalDestination', link: ast.arguments?.[0] ? transformExpression2Nasl(ast.arguments?.[0]) : undefined, target: ast.arguments?.[1] ? ast.arguments?.[1]?.value : '_self', }; } if (code === 'nasl.js.block') { const code = (0, generator_1.default)(ast.arguments[0]).code.trim().slice(1, -1); return { concept: 'JSBlock', code, }; } return { concept: 'CallLogic', arguments: args, calleeNamespace: namespace, calleeName: name, shortcut: namespace === 'nasl.ui', }; } function transformCallLogic2ProcessV2(ast, namespace, name) { const processV2Logics = (0, concepts_1.getStdlibNamespace)().findChild('processV2').logics || []; const logicDefinition = processV2Logics.find((item) => item.name === name); const argsList = logicDefinition?.params?.map((param, index) => ({ concept: 'Argument', expression: ast.arguments?.[index] ? transformExpression2Nasl(ast.arguments?.[index]) : undefined, keyword: param.name, })) ?? []; return { concept: 'CallLogic', calleeNamespace: namespace, calleeName: name, arguments: argsList, }; } function transformArrowFunctionExpression(ast) { if (ast.body.type === 'BlockStatement') { throw new Error(`解析Expression失败,箭头函数仅支持表达式, ${(0, utils_1.getNodeCode)(ast)}`); } return { concept: 'AnonymousFunction', params: ast.params.map((p) => (0, transform_func2nasl_1.transformParam2Nasl)(p)), body: transformExpression2Nasl(ast.body), }; } function transformExpression2Nasl(ast, namespace = '') { switch (ast.type) { case 'MemberExpression': // eslint-disable-next-line no-case-declarations const ns = getNamespace(ast.object); if (ast.property.type === 'PrivateName') { throw new Error(`Expression 解析失败,不支持 PrivateName, ${(0, utils_1.getNodeCode)(ast)}`); } // object如果返回字符串,则将它当成namespace处理 if (ns) { return transformExpression2Nasl(ast.property, ns); } return { concept: 'MemberExpression', name: '', kind: 'Expression', object: transformExpression2Nasl(ast.object), property: transformExpression2Nasl(ast.property), }; case 'Identifier': if (ast.name === 'undefined') return void 0; return { concept: 'Identifier', namespace, name: ast.name, kind: 'Expression', }; case 'TemplateLiteral': return { concept: 'StringInterpolation', kind: 'Expression', name: '', expressions: [...(ast.quasis || []), ...(ast.expressions || [])] .sort((node1, node2) => { return node1.start - node2.start; }) .map((n) => { if (n.type === 'TemplateElement') { return { concept: 'StringLiteral', kind: 'Expression', name: '', value: n.value.raw, }; } return transformExpression2Nasl(n); }), }; case 'StringLiteral': return { concept: 'StringLiteral', kind: 'Expression', name: '', value: ast.value, }; case 'NumericLiteral': return { concept: 'NumericLiteral', value: String(ast.value), typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'primitive', typeName: String(ast.value).includes('.') ? 'Decimal' : 'Long', typeNamespace: 'nasl.core', inferred: false, ruleMap: new Map(), }, }; case 'NullLiteral': return { concept: 'NullLiteral', }; case 'BooleanLiteral': return { concept: 'BooleanLiteral', value: String(ast.value), }; case 'UnaryExpression': if (ast.argument.type === 'NumericLiteral') { return { concept: 'NumericLiteral', value: ast.operator + ast.argument.value, }; } return { concept: 'UnaryExpression', kind: 'Expression', name: '', operator: ast.operator, argument: transformExpression2Nasl(ast.argument), }; case 'LogicalExpression': case 'BinaryExpression': if (ast.left.type === 'PrivateName') { throw new Error(`Expression 解析失败,不支持 PrivateName, ${(0, utils_1.getNodeCode)(ast)}`); } const options = { transformType: 'attr' }; return (0, natural_1.transformNode2Expression)(ast, options); case 'ArrayExpression': return { concept: 'NewList', items: ast.elements.map((e) => { if (!e || e.type === 'SpreadElement') { throw new Error('解析Expression失败,数组中不允许出现 null, 或者 ...'); } return transformExpression2Nasl(e); }), }; case 'ObjectExpression': return transformObjectExpression2Nasl(ast); case 'AssignmentExpression': return { concept: 'Assignment', left: transformExpression2Nasl(ast.left), right: transformExpression2Nasl(ast.right), }; case 'ArrowFunctionExpression': return transformArrowFunctionExpression(ast); case 'CallExpression': return transformCallExpress2Nasl(ast); default: throw new Error(`解析Expression失败,nasl未支持该表达式, ${(0, utils_1.getNodeCode)(ast)}`); } } exports.transformExpression2Nasl = transformExpression2Nasl; exports.default = transformExpression2Nasl; //# sourceMappingURL=transform-expression2nasl.js.map