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