@lcap/nasl
Version:
NetEase Application Specific Language
1,113 lines • 116 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformCall2CallViewLogic = exports.transformCall2Extension = exports.transformCall2Connector = exports.transformCall2Interface = exports.transformAlert2ShowMessage = exports.transformForEach2ForEachStatement = exports.transformForOf2ForEachStatement = exports.transform2ForEachStatement = exports.transformMap2ListTransform = exports.transform2UIFunction = exports.transformCall2CallFunction = exports.transform2CallFunction = exports.transformCall2JSONFunctions = exports.transformCall2Logging = exports.transformCall2ConsoleLog = exports.transformCall2CallDataSourceLogic = exports.transformCall2CallEntityLogic = exports.transformCall2CallViewElementLogic = exports.transformCallFunctionExpression2Match = exports.transformMemberExpression = exports.transformNewExpression = exports.transform2PartialNewComposite = exports.transform2Comment = exports.transform2StringInterpolation = exports.transformReturnStatement2AssignmentOrEnd = exports.transform2NullLiteral = exports.transform2NumericLiteral = exports.transform2DirectiveLiteral = exports.transform2StringLiteral = exports.transform2BooleanLiteral = exports.transformUpdateExpression2Assignment = exports.transform2Assignment = exports.transform2AnonymousFunction = exports.transformIdentifier = exports.transformSwitchStatement2Match = exports.transform2WhileStatement = exports.transform2Break = exports.transform2Continue = exports.transform2IfStatement = exports.transform2BinaryExpression = exports.transformCallExpressionToBinaryExpression = exports.transform2Param = exports.fixLogicNode = exports.flatIfStatementForMatch = exports.flatMatchPatternsExpression = exports.getSelectMembers = exports.unflatMemberExpression = exports.flatMemberExpression = exports.fixExpression = exports.TransformManager = void 0;
exports.transform2LogicItem = exports.transformCall2Paginate = exports.transformCall2LogicWithAuth = exports.transformCall2Logic = void 0;
const utils_1 = require("./utils");
const transform2TypeAnnotation_1 = require("./transform2TypeAnnotation");
const utils_2 = require("../../utils");
const server_1 = __importDefault(require("../../server"));
;
class TransformManager {
constructor() {
this.transforms = [];
this.transformCallExpressions = [];
}
register(type, transform) {
this.transforms.push([type, transform]);
}
registerCallExpression(type, transform) {
this.transformCallExpressions.push([type, transform]);
}
apply(node, options) {
if (node.type === 'CallExpression') {
if (node.callee.type === 'CallExpression')
(0, utils_1.throwError)('不支持连续调用!', node.callee);
const callee = flatMemberExpression(node.callee);
if (callee[0]
&& callee[0].type === 'CallExpression'
&& callee[0].callee.type === 'MemberExpression'
&& callee[0].callee.property.type === 'Identifier'
&& callee[0].callee.property.name === 'connect') {
const headCallee = flatMemberExpression(callee[0].callee);
callee.unshift(...headCallee.slice(0, -1));
}
else {
for (const calleeItem of callee) {
if (calleeItem.type !== 'Identifier' && !(calleeItem.type === 'FunctionExpression' && calleeItem.id?.name === 'match')) {
(0, utils_1.throwError)('不支持连续调用!', node.callee);
}
}
}
const calleeName = (0, utils_1.generate)(node.callee).code;
for (const [type, transform] of this.transformCallExpressions) {
if (typeof type === 'function' ? type(node, calleeName, callee) : type === calleeName) {
return transform(node, calleeName, callee, options);
}
}
(0, utils_1.throwError)(`Unhandled node ${callee.map((item) => item.name).join('.')}`, node.type, node);
}
else {
for (const [type, transform] of this.transforms) {
if (typeof type === 'function' ? type(node) : type === node.type) {
return transform(node, options);
}
}
(0, utils_1.throwError)('Unhandled node', node.type, node);
}
}
}
exports.TransformManager = TransformManager;
function transformTSCode2SubLogic(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const logic = new utils_1.naslTypes.SubLogic();
logic.name = options.transformType === 'logic' && options.logic?.getSubLogicUniqueName ? options.logic.getSubLogicUniqueName() : `subLogic_${(0, utils_2.uuidv4)().slice(0, 2)}`;
logic.body = logic.body.slice(0, 1);
let parameters = [];
let statements = [];
if (node.type === 'ArrowFunctionExpression') {
parameters = node.params;
const body = node.body;
statements = [...body?.directives, ...body?.body];
}
if (node.type === 'FunctionExpression') {
parameters = node.params;
statements = [...node?.body?.directives, ...node?.body?.body];
}
parameters.forEach((node) => {
const param = transform2Param(node);
param && logic.addParam(param);
});
const newStatements = [];
statements.forEach((node, index) => {
if (node?.leadingComments?.length) {
newStatements.push(...node?.leadingComments);
}
if (node?.trailingComments?.length && index === statements.length - 1) {
newStatements.push(...node?.trailingComments);
}
newStatements.push(node);
});
statements = newStatements;
const body = statements.map((node) => transformNodeFunction(node, {
...options,
logic,
})).filter((item) => !!item);
body.forEach((item) => logic.addItemInBody(item.toJSON()));
const lastItem = logic.body[logic.body.length - 1];
if (lastItem && lastItem.concept !== 'End') {
logic.addItemInBody(new utils_1.naslTypes.End());
}
if (logic.returns[0]?.name) {
const index = logic.variables.findIndex((variable) => variable.name === logic.returns[0].name);
if (index >= 0)
logic.variables.splice(index, 1);
}
if (logic?.variables?.length) {
const oldVariables = [...logic.variables];
logic.variables = [];
oldVariables.forEach((variable) => {
logic.addVariable(variable);
});
}
if (logic?.returns?.length) {
const oldReturns = [...logic.returns];
logic.returns = [];
oldReturns.forEach((ret) => {
logic.addReturn(ret);
});
}
return logic;
}
function assertAssignmentRightIsNotAnonymousFunction(expression) {
if (expression?.concept === 'AnonymousFunction')
(0, utils_1.throwError)('Anonymous function is not allowed in assignment', expression.toNaturalTS());
return expression;
}
function fixExpression(arg, options, supportSubLogic = false) {
let expression;
if (options.transformType === 'logic' && supportSubLogic &&
(arg?.type === 'FunctionExpression' || (arg?.type === 'ArrowFunctionExpression'))) {
if (arg?.body?.type === 'BlockStatement') {
expression = transformTSCode2SubLogic(arg, options);
}
else {
const babelReturnStatement = utils_1.babelTypes.returnStatement(arg.body);
arg.body = utils_1.babelTypes.blockStatement([babelReturnStatement]);
expression = transformTSCode2SubLogic(arg, options);
}
}
else {
if (arg?.body?.type === 'ReturnStatement') {
arg.body = arg?.body?.argument;
}
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
expression = transformNodeFunction(arg, options);
if (expression?.concept === 'Identifier' && expression?.name === 'undefined') {
expression = undefined;
}
}
return expression;
}
exports.fixExpression = fixExpression;
/**
* 铺平点选表达式
*/
function flatMemberExpression(node) {
if (node.type === 'MemberExpression')
return [...flatMemberExpression(node.object), node.property];
return [node];
}
exports.flatMemberExpression = flatMemberExpression;
/**
* 将铺平的点选表达式列表转换回 MemberExpression
*/
function unflatMemberExpression(nodes, options, memberExpression, namespace) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
// 如果 nodes 为空,直接返回当前的 memberExpression
if (nodes.length === 0) {
return memberExpression;
}
let newMemberExpression = null;
let remainingNodes = null;
// 首次调用时,如果 namespace 存在,构建一个 MemberExpression
if (namespace) {
const object = nodes[0];
const property = nodes[1];
newMemberExpression = new utils_1.naslTypes.MemberExpression({
object: new utils_1.naslTypes.Identifier({
namespace, // 只有第一个 Identifier 带上 namespace
name: object.name,
}),
property: transformNodeFunction(property, options),
});
remainingNodes = nodes.slice(2); // 跳过前两个节点
}
else {
// 后续递归调用时,逐个添加剩余的节点
const property = nodes[0];
newMemberExpression = new utils_1.naslTypes.MemberExpression({
object: memberExpression, // 使用当前的 memberExpression 作为 object
property: transformNodeFunction(property, options),
});
remainingNodes = nodes.slice(1); // 跳过当前节点
}
// 如果还有剩余的节点,递归处理
if (remainingNodes.length > 0) {
return unflatMemberExpression(remainingNodes, options, newMemberExpression);
}
// 返回最终的 MemberExpression
return newMemberExpression;
}
exports.unflatMemberExpression = unflatMemberExpression;
/**
* 铺平链式调用表达式
*/
function flatChainCallExpression(node) {
if (node.callee.type === 'MemberExpression') {
if (node.callee.object.type === 'CallExpression' && node.callee.property.type === 'Identifier')
return [...flatChainCallExpression(node.callee.object), utils_1.babelTypes.callExpression(node.callee.property, node.arguments)];
else if (node.callee.object.type === 'Identifier' && node.callee.property.type === 'Identifier')
return [utils_1.babelTypes.callExpression(node.callee.property, node.arguments)];
}
return [node];
}
function getSelectMembers(node) {
if (node.concept === 'MemberExpression')
return [...getSelectMembers(node.object), node];
else
return [];
}
exports.getSelectMembers = getSelectMembers;
function flatMatchPatternsExpression(node) {
if (node.concept === 'BinaryExpression') {
if (node.operator === '||') {
return [...flatMatchPatternsExpression(node.left), ...flatMatchPatternsExpression(node.right)];
}
if (node.operator === '==') {
return [node.right];
}
return [node];
}
return [node];
}
exports.flatMatchPatternsExpression = flatMatchPatternsExpression;
function flatIfStatementForMatch(node) {
if (node.alternate.type === 'IfStatement') {
return [node, ...flatIfStatementForMatch(node.alternate)];
}
return [node, {
type: 'IfStatement',
test: null,
consequent: node.alternate,
alternate: node.alternate,
}];
}
exports.flatIfStatementForMatch = flatIfStatementForMatch;
/**
* 这个函数是修复 AI 翻译出错的情况,与正常的 transform 做个区分
* @param node
* @returns
*/
function fixLogicNode(node) {
if (node?.type === 'CallExpression') {
const calleeName = (0, utils_1.generate)(node.callee).code;
if (calleeName === 'nasl.util.ForEach') {
const callee = flatMemberExpression(node.callee);
node.callee = callee[2];
}
}
}
exports.fixLogicNode = fixLogicNode;
function transform2Param(node) {
const exclude = ['event'];
if (node.type === 'ObjectProperty') {
const typeAnnotation = node?.value?.name ? utils_1.naslTypes.TypeAnnotation.createPrimitive((node?.value).name) : null;
const name = node.key.name;
if (exclude.includes(name))
return null;
let defaultValueExpression = node.key.optional ? { type: 'NullLiteral' } : undefined;
return new utils_1.naslTypes.Param({
name,
typeAnnotation,
defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({
expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }),
}),
});
}
else if (node.type === 'TSPropertySignature') {
const typeAnnotation = node.typeAnnotation?.typeAnnotation;
const name = node.key.name;
if (exclude.includes(name))
return null;
let defaultValueExpression = node.optional ? { type: 'NullLiteral' } : undefined;
return new utils_1.naslTypes.Param({
name,
typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null,
defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({
expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }),
}),
});
}
else if (node.type === 'Identifier') {
const typeAnnotation = node.typeAnnotation?.typeAnnotation;
const name = node.name;
if (exclude.includes(name))
return null;
let defaultValueExpression = node.optional ? { type: 'NullLiteral' } : undefined;
return new utils_1.naslTypes.Param({
name,
required: !node.optional,
typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null,
defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({
expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }),
}),
});
}
else if (node.type === 'AssignmentPattern') {
const identifier = node.left;
const typeAnnotation = identifier.typeAnnotation?.typeAnnotation;
let defaultValueExpression;
if (node.type === 'AssignmentPattern') {
if (node.right)
defaultValueExpression = node.right;
else if (identifier.optional) {
defaultValueExpression = { type: 'NullLiteral' };
}
}
const exclude = ['event'];
const name = identifier.name;
if (exclude.includes(name))
return null;
return new utils_1.naslTypes.Param({
name,
typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null,
defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({
expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }),
}),
});
}
else {
(0, utils_1.throwError)('Unhandled node', node);
}
}
exports.transform2Param = transform2Param;
function transformCallExpressionToBinaryExpression(node, calleeName, callee, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const argument = node?.arguments;
const map = {
plus: '+',
minus: '-',
multiply: '*',
divide: '/',
remainder: '%',
STARTS_WITH: 'startwith',
ENDS_WITH: 'endwith',
LIKE: 'like',
IN: 'in',
IS_NULL: 'isNull',
};
if (calleeName === 'IS_NULL') {
return new utils_1.naslTypes.UnaryExpression({
operator: 'isNull',
argument: transformNodeFunction(argument?.[0], options),
});
}
return new utils_1.naslTypes.BinaryExpression({
operator: map[calleeName],
left: transformNodeFunction(argument?.[0], options),
right: transformNodeFunction(argument?.[1], options),
});
}
exports.transformCallExpressionToBinaryExpression = transformCallExpressionToBinaryExpression;
function transform2BinaryExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (node.operator === '===')
node.operator = '==';
if (node.operator === '!==')
node.operator = '!=';
if (node.operator === '==' && node.right?.type === 'NullLiteral' && options?.inCallQueryComponentField) {
return new utils_1.naslTypes.UnaryExpression({
operator: 'isNull',
argument: transformNodeFunction(node.left, options),
});
}
if (node.operator === '!=' && node.right?.type === 'NullLiteral' && options?.inCallQueryComponentField) {
return new utils_1.naslTypes.UnaryExpression({
operator: '!',
argument: new utils_1.naslTypes.UnaryExpression({
operator: 'isNull',
argument: transformNodeFunction(node.left, options),
}),
});
}
if (['+', '-', '*', '/', '//', '%', '==', '!=', '>', '<', '>=', '<=', '&&', '||', 'startwith', 'endwith', 'like', 'in', 'isNull'].includes(node.operator)) {
if ((node?.left?.name) === '_value' && node?.right?.type === 'BooleanLiteral') {
return transformNodeFunction(node.right, options);
}
return new utils_1.naslTypes.BinaryExpression({
operator: node.operator,
left: transformNodeFunction(node.left, options),
right: transformNodeFunction(node.right, options),
});
}
(0, utils_1.throwError)('Unhandled node', node.type, node);
}
exports.transform2BinaryExpression = transform2BinaryExpression;
function transformDefaultExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
return transformNodeFunction(node.left, options);
}
function transformLogicalExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const expression = new utils_1.naslTypes.CallFunction({
calleeNamespace: 'nasl.util',
calleeName: 'Convert',
arguments: [
new utils_1.naslTypes.Argument({
expression: transformNodeFunction(node.left, options),
}),
],
typeArguments: [utils_1.naslTypes.TypeAnnotation.createPrimitive('Boolean')],
});
return new utils_1.naslTypes.Match({
expression,
isExpression: true,
cases: [
new utils_1.naslTypes.MatchCase({
patterns: [new utils_1.naslTypes.BooleanLiteral({ value: 'true' })],
body: [transformNodeFunction(node.left, options)],
isMatchedTypeEnumable: true,
}),
new utils_1.naslTypes.MatchCase({
patterns: [transformNodeFunction(node.right, options)],
body: [transformNodeFunction(node.right, options)],
}),
],
});
}
function transformConditionalExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (options?.inCallQueryComponentField) {
const expr = (0, utils_1.generate)(node.test)?.code;
const then_expr = (0, utils_1.generate)(node.consequent)?.code;
const else_expr = (0, utils_1.generate)(node.alternate)?.code;
(0, utils_1.throwError)(`数据查询中不支持条件表达式!${(0, utils_1.generate)(node)?.code}, 请使用 SQL函数 IF(${expr} == null, ${then_expr}, ${else_expr})`);
}
const test = transformNodeFunction(node.test, options);
const consequent = transformNodeFunction(node.consequent, options);
const alternate = transformNodeFunction(node.alternate, options);
const variables = options.transformType === 'logic' ? [...options?.logic?.variables, ...options?.logic?.returns, ...options?.logic?.params] : [];
const testType = variables?.find((item) => item?.name === test?.name)?.typeAnnotation;
const expression = testType?.typeName === 'Boolean' || test?.concept === 'BinaryExpression' ? test :
new utils_1.naslTypes.CallFunction({
calleeNamespace: 'nasl.util',
calleeName: 'Convert',
arguments: [
new utils_1.naslTypes.Argument({
expression: test,
}),
],
typeArguments: [utils_1.naslTypes.TypeAnnotation.createPrimitive('Boolean')],
});
return new utils_1.naslTypes.Match({
expression,
isExpression: true,
cases: [
new utils_1.naslTypes.MatchCase({
patterns: [new utils_1.naslTypes.BooleanLiteral({ value: 'true' })],
body: [consequent],
isMatchedTypeEnumable: true,
}),
new utils_1.naslTypes.MatchCase({
patterns: [alternate],
body: [alternate],
}),
],
});
}
function transformArrayExpression(node, options) {
let typeAnnotation = options.typeAnnotation;
delete options.typeAnnotation;
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
return new utils_1.naslTypes.NewList({
typeAnnotation,
items: node?.elements?.map((arg) => transformNodeFunction(arg, { ...options, typeAnnotation: undefined })),
});
}
function transform2NewAnonymousStructure(node, options) {
const newComposite = transform2PartialNewComposite(node, options);
const newProperties = node.properties.filter((prop) => prop.type === 'ObjectProperty' && prop.value.type !== 'ConditionalExpression');
const structureProperties = [];
newProperties.forEach((arg, index) => {
structureProperties.push(new utils_1.naslTypes.StructureProperty({
name: arg.key.name,
typeAnnotation: null
}));
});
newComposite.typeAnnotation = utils_1.naslTypes.TypeAnnotation.createTypeAnonymousStructure(structureProperties);
return newComposite;
}
function transform2NewStructure(namespaceAndName, objectExpression, options) {
const newComposite = transform2PartialNewComposite(objectExpression, options);
const arr = namespaceAndName.split('.');
newComposite.typeAnnotation = utils_1.naslTypes.TypeAnnotation.createReference(arr[arr.length - 1], {
typeNamespace: arr.slice(0, -1).join('.')?.replace(/connectors\./, 'connector.'),
});
return newComposite;
}
function transform2NewExpression(calleeName, node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (calleeName === 'NewList') {
let typeAnnotation;
if (node?.typeParameters?.params?.[0]?.typeName?.name === '__IDENTIFIER__') {
typeAnnotation = undefined;
}
else {
typeAnnotation = utils_1.naslTypes.TypeAnnotation.createGeneric('List', {
typeArguments: node?.typeParameters?.params.map(transform2TypeAnnotation_1.transform2TypeAnnotation),
});
}
if (node?.arguments && node?.arguments?.[0]?.type !== 'ArrayExpression') {
(0, utils_1.throwError)('Not allowed code in NewList', node);
}
return new utils_1.naslTypes.NewList({
typeAnnotation: node?.typeParameters ? typeAnnotation : undefined,
items: node?.arguments?.[0]?.elements?.map((arg) => transformNodeFunction(arg, options)),
});
}
if (calleeName === 'NewMap') {
const keys = [];
const values = [];
node?.arguments?.[0]?.properties?.forEach((arg) => {
keys.push(transformNodeFunction(arg.key, options));
values.push(transformNodeFunction(arg.value, options));
});
let typeAnnotation;
if (node?.typeParameters?.params?.[0]?.typeName?.name === '__IDENTIFIER__') {
typeAnnotation = undefined;
}
else {
typeAnnotation = utils_1.naslTypes.TypeAnnotation.createGeneric('Map', {
typeArguments: node?.typeParameters?.params.map(transform2TypeAnnotation_1.transform2TypeAnnotation),
});
}
return new utils_1.naslTypes.NewMap({
typeAnnotation: node?.typeParameters ? typeAnnotation : undefined,
keys,
values,
});
}
if (calleeName === 'NewEntity' || calleeName === 'NewStructure') {
const typeParam = node.typeParameters?.params[0];
const typeNamespaceAndName = typeParam ? (0, utils_1.generate)(typeParam).code : '';
if (!typeNamespaceAndName)
(0, utils_1.throwError)('Not allowed empty namespace in NewEntity', node);
return transform2NewStructure(typeNamespaceAndName, node.arguments[0], options);
}
if (calleeName === 'NewAnonymousStructure') {
return transform2NewAnonymousStructure(node.arguments[0], options);
}
(0, utils_1.throwError)('Unhandled ArrowFunctionExpression node', node.type, node);
}
function pushElseIf(ifNode, switchStatement, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const consequent = !ifNode?.consequent ? [] : flatCommentWithNode(ifNode.consequent);
switchStatement.cases.push(new utils_1.naslTypes.SwitchCase({
test: transformNodeFunction(ifNode.test, options),
consequent: transformBlockBody(consequent, options),
}));
if (ifNode.alternate && ifNode.alternate.type === 'IfStatement') {
pushElseIf(ifNode.alternate, switchStatement, options);
}
else {
const consequent = !ifNode?.alternate ? [] : flatCommentWithNode(ifNode.alternate);
switchStatement.cases.push(new utils_1.naslTypes.SwitchCase({
test: undefined,
consequent: transformBlockBody(consequent, options),
}));
}
}
function transformBlockBody(body, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (!body)
return undefined;
return body.flatMap((item) => {
const logicItem = transformNodeFunction(item, options);
if (!logicItem) {
console.log('item in block:', item);
return [];
}
return item?.type === 'ReturnStatement' && item?.argument && logicItem.concept !== 'End' ? [logicItem, new utils_1.naslTypes.End()] : [logicItem];
}).filter((item) => !!item);
}
function transform2ArrayPattern(decl, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
let logicItems = [];
let getVariableNode;
if (decl?.init?.type === 'Identifier') {
getVariableNode = transformNodeFunction(decl.init, options);
}
else {
getVariableNode = new utils_1.naslTypes.Identifier({
name: `temp_${(0, utils_2.uuidv4)().slice(0, 4)}`,
});
logicItems.push(new utils_1.naslTypes.Assignment({
left: getVariableNode,
right: transformNodeFunction(decl.init, options),
}));
}
// 判断一下是否已存在
if (options.transformType === 'logic') {
const hasVariable = options?.logic?.variables?.find((item) => item?.name === getVariableNode?.name);
if (!hasVariable) {
options.logic.variables.push(new utils_1.naslTypes.Variable({
name: getVariableNode.name,
typeAnnotation: undefined,
}));
}
}
decl?.id?.elements?.map((element, index) => {
if (element.type === 'Identifier') {
const varTypeAnnotation = element.typeAnnotation?.typeAnnotation;
if (options.transformType === 'logic') {
options.logic.variables.push(new utils_1.naslTypes.Variable({
name: element.name,
typeAnnotation: varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation),
}));
}
}
const logicItem = new utils_1.naslTypes.Assignment({
left: transformNodeFunction(element, options),
right: new utils_1.naslTypes.CallFunction({
calleeNamespace: 'nasl.util',
calleeName: 'Get',
arguments: [
new utils_1.naslTypes.Argument({
expression: getVariableNode,
}),
new utils_1.naslTypes.Argument({
expression: new utils_1.naslTypes.NumericLiteral({
value: String(index),
}),
}),
],
}),
});
logicItems.push(logicItem);
});
return new utils_1.naslTypes.Block({
folded: false,
logicItems,
});
}
function transform2VariableAndAddAssignment(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const declList = node?.declarations || [];
let newNode;
declList.forEach((decl) => {
const variableName = decl.id.name;
const isArrayPattern = decl.id?.type === 'ArrayPattern';
if (isArrayPattern && decl.init) {
// 取出init中的,get
newNode = transform2ArrayPattern(decl, options);
return newNode;
}
let typeAnnotation;
if (options.transformType === 'logic' && ![...options.logic.variables, ...options.logic.returns].some((variable) => variable.name === variableName)) {
const varTypeAnnotation = decl.id.typeAnnotation?.typeAnnotation;
typeAnnotation = varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation);
options.logic.variables.push(new utils_1.naslTypes.Variable({
name: variableName,
typeAnnotation,
}));
}
if (decl.init) {
const calleeName = (0, utils_1.generate)(decl?.init?.callee).code;
const varTypeAnnotation = decl?.id?.typeAnnotation?.typeAnnotation;
typeAnnotation = varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation);
if (calleeName === 'nasl.oql.query' && varTypeAnnotation) {
decl.init.typeAnnotations = varTypeAnnotation;
}
options.typeAnnotation = typeAnnotation;
newNode = new utils_1.naslTypes.Assignment({
left: transformNodeFunction(decl.id, options),
right: assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(decl.init, { ...options, typeAnnotation })),
});
}
});
if (newNode)
return newNode;
}
function flatCommentWithNode(node) {
let newNodeList = [];
if (node?.innerComments?.length) {
newNodeList = [...node?.innerComments];
}
if (node?.body?.length) {
node?.body.forEach((item, index) => {
if (item?.leadingComments?.length) {
newNodeList.push(...item?.leadingComments);
}
if (item?.trailingComments?.length && index === node?.body.length - 1) {
newNodeList.push(...item?.trailingComments);
}
newNodeList.push(item);
});
}
return newNodeList;
}
function transform2IfStatement(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (node.alternate && node.alternate.type === 'IfStatement') {
const switchStatement = new utils_1.naslTypes.SwitchStatement({
cases: [],
});
pushElseIf(node, switchStatement, options);
// 如果 cases 中每一个 case 都有 End,去掉最后一个 case 的 End
if (switchStatement.cases.every((caseItem) => caseItem.consequent?.[caseItem.consequent.length - 1]?.concept === 'End')) {
switchStatement.cases[switchStatement.cases.length - 1].consequent.pop();
}
return switchStatement;
}
const consequent = !node?.consequent ? [] : flatCommentWithNode(node.consequent);
const alternate = !node?.alternate ? [] : flatCommentWithNode(node.alternate);
const naslNode = new utils_1.naslTypes.IfStatement({
test: transformNodeFunction(node.test, options),
consequent: transformBlockBody(consequent, options),
alternate: transformBlockBody(alternate, options),
});
// consequent 和 alternate 都有 End 就去掉一个(不然发布时java编译会报错)
if (naslNode.consequent?.[naslNode.consequent.length - 1]?.concept === 'End' && naslNode.alternate?.[naslNode.alternate.length - 1]?.concept === 'End') {
naslNode.alternate.pop();
}
return naslNode;
}
exports.transform2IfStatement = transform2IfStatement;
function transform2Continue() {
return new utils_1.naslTypes.Continue();
}
exports.transform2Continue = transform2Continue;
function transform2Break() {
return new utils_1.naslTypes.Break();
}
exports.transform2Break = transform2Break;
function transform2WhileStatement(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const body = !node?.body ? [] : flatCommentWithNode(node.body);
return new utils_1.naslTypes.WhileStatement({
test: transformNodeFunction(node.test, options),
body: transformBlockBody(body, options),
});
}
exports.transform2WhileStatement = transform2WhileStatement;
function transformSwitchStatement2Match(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const match = new utils_1.naslTypes.Match({
expression: transformNodeFunction(node.discriminant, options),
isExpression: options.transformType !== 'logic',
cases: node.cases.map((_case) => new utils_1.naslTypes.MatchCase({
patterns: !_case.test ? [] : [transformNodeFunction(_case.test, options)],
body: transformBlockBody(_case.consequent.filter((item) => item.type !== 'BreakStatement'), options),
})),
});
if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) {
match.cases.push(new utils_1.naslTypes.MatchCase({
patterns: [],
body: [],
}));
}
match.cases.forEach((case_) => {
if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) {
case_.isMatchedTypeEnumable = true;
}
if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') {
case_.isMatchedTypeEnumable = true;
case_.patterns[0].object.namespace = 'app.enums';
}
});
return match;
}
exports.transformSwitchStatement2Match = transformSwitchStatement2Match;
function transformIdentifier(node, options) {
if (options.transformType === 'logic' && options.entityAsNames?.includes(node.name)) {
return new utils_1.naslTypes.QueryFieldExpression({
isDotStar: false,
asName: undefined,
entityAsName: node.name,
propertyName: '',
});
}
const placeholderMap = ['__IDENTIFIER__', '__LEFT__', '__RIGHT__', '__RIGHT', '__LEFT', '__IDENTIFIER', 'undefined'];
if (placeholderMap.includes(node.name)) {
return new utils_1.naslTypes.Identifier({});
}
if (node.name === '$self') {
return new utils_1.naslTypes.MemberExpression({
object: new utils_1.naslTypes.Identifier({
name: 'elements',
}),
property: new utils_1.naslTypes.Identifier({
name: '$ce',
}),
});
}
return new utils_1.naslTypes.Identifier({
name: node.name,
});
}
exports.transformIdentifier = transformIdentifier;
function transform2SelectQueryFieldExpression(node, options) {
let expression = node.value;
let asNameNode = node.key;
if (expression.type === 'Identifier') {
return new utils_1.naslTypes.QueryFieldExpression({
isDotStar: true,
asName: (0, utils_2.firstUpperCase)(asNameNode.name) === expression.name ? undefined : asNameNode.name,
entityAsName: expression.name,
propertyName: '',
});
}
else if (expression.type === 'MemberExpression') {
return new utils_1.naslTypes.QueryFieldExpression({
isDotStar: false,
asName: (0, utils_2.firstUpperCase)(asNameNode.name) === expression.property.name ? undefined : asNameNode.name,
entityAsName: expression.object.name,
propertyName: expression.property.name,
});
}
else if (expression.type === 'ObjectExpression') {
// @TODO
}
else {
(0, utils_1.throwError)('Unsupported expression type for QueryFieldExpression', expression.type, expression);
}
}
function transform2QueryAggregateExpression(node, options) {
const callExpression = node.value;
let asNameNode = node.key;
const arg = callExpression.arguments[0];
if (arg.type !== 'MemberExpression') {
const code = (0, utils_1.generate)(arg).code;
(0, utils_1.throwError)(`聚合函数的输入只能是表字段(实体.属性),但AVG(${code})中的${code}不是表字段`);
}
if (callExpression.arguments?.length > 1) {
(0, utils_1.throwError)(`聚合函数${callExpression.callee.name}只支持一个参数`);
}
return new utils_1.naslTypes.QueryAggregateExpression({
asName: asNameNode.name,
aggregateName: callExpression.callee.name,
aggregateParam: (arg.type === 'MemberExpression' ? transformMemberExpression(arg, options) : transformIdentifier(arg, options)),
});
}
function transform2AnonymousFunction(node, options) {
if (node.body.type === 'BlockStatement')
(0, utils_1.throwError)('Anonymous function with block statement is not supported', node);
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
return new utils_1.naslTypes.AnonymousFunction({
params: node.params.map((param) => transform2Param(param)),
body: transformNodeFunction(node.body, options),
});
}
exports.transform2AnonymousFunction = transform2AnonymousFunction;
function transform2Assignment(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (node.operator === '+=' || node.operator === '-=') {
if (options.transformType === 'logic') {
return new utils_1.naslTypes.Assignment({
left: transformNodeFunction(node.left, options),
right: new utils_1.naslTypes.BinaryExpression({
operator: node.operator[0],
left: transformNodeFunction(node.left, options),
right: transformNodeFunction(node.right, options),
}),
});
}
return new utils_1.naslTypes.BinaryExpression({
operator: node.operator[0],
left: transformNodeFunction(node.left, options),
right: transformNodeFunction(node.right, options),
});
}
if (options.transformType !== 'logic') {
return transformNodeFunction(node.right, options);
}
return new utils_1.naslTypes.Assignment({
left: transformNodeFunction(node.left, options),
right: assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(node.right, options)),
});
}
exports.transform2Assignment = transform2Assignment;
function transformUpdateExpression2Assignment(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (node.operator === '++' || node.operator === '--') {
return new utils_1.naslTypes.Assignment({
left: transformNodeFunction(node.argument, options),
right: new utils_1.naslTypes.BinaryExpression({
operator: node.operator[0],
left: transformNodeFunction(node.argument, options),
right: new utils_1.naslTypes.NumericLiteral({
value: '1',
typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive('Long'),
}),
}),
});
}
}
exports.transformUpdateExpression2Assignment = transformUpdateExpression2Assignment;
function transform2BooleanLiteral(node, options) {
return new utils_1.naslTypes.BooleanLiteral({
value: String(node.value),
});
}
exports.transform2BooleanLiteral = transform2BooleanLiteral;
function transform2StringLiteral(node, options) {
return new utils_1.naslTypes.StringLiteral({
value: node.value,
});
}
exports.transform2StringLiteral = transform2StringLiteral;
function transform2DirectiveLiteral(node, options) {
return new utils_1.naslTypes.StringLiteral({
value: node.value?.value,
});
}
exports.transform2DirectiveLiteral = transform2DirectiveLiteral;
function transform2NumericLiteral(node, options) {
const value = node.extra?.raw || String(node.value);
const literal = new utils_1.naslTypes.NumericLiteral({
value,
typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive('Integer'),
});
literal.typeAnnotation.typeName = literal.changeType(value);
if (options.typeAnnotation && ['Integer', 'Long', 'Decimal'].includes(options.typeAnnotation.typeName)) {
literal.typeAnnotation = options.typeAnnotation;
delete options.typeAnnotation;
}
return literal;
}
exports.transform2NumericLiteral = transform2NumericLiteral;
function transform2NullLiteral(node, options) {
return new utils_1.naslTypes.NullLiteral();
}
exports.transform2NullLiteral = transform2NullLiteral;
function transformReturnStatement2AssignmentOrEnd(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (!node.argument) {
return new utils_1.naslTypes.End();
}
if (options.transformType !== 'logic')
return new utils_1.naslTypes.End();
const { logic } = options;
const argument = node?.argument?.type === 'TSAsExpression' ? node?.argument?.expression : node?.argument;
if (argument?.type === 'Identifier') {
if (!logic.returns.length) {
const curVariable = logic?.variables?.find((item) => item.name === argument?.name);
if (curVariable) {
logic.variables = logic?.variables?.filter((item) => item.name !== argument?.name);
logic.addReturn(curVariable);
return new utils_1.naslTypes.End();
}
}
}
if (!logic.returns.length) {
const typeAnnotation = node?.argument?.type === 'TSAsExpression' ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(node?.argument?.typeAnnotation) : undefined;
logic.returns.push(new utils_1.naslTypes.Return({
name: 'result',
typeAnnotation
}));
}
const leftName = logic.returns[0].name;
const right = assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(argument, options));
if (right.concept === 'Identifier' && right.name === leftName) {
return new utils_1.naslTypes.End();
}
else {
return new utils_1.naslTypes.Assignment({
left: new utils_1.naslTypes.Identifier({ name: leftName }),
right,
});
}
}
exports.transformReturnStatement2AssignmentOrEnd = transformReturnStatement2AssignmentOrEnd;
function transform2StringInterpolation(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const expressions = [...node.expressions, ...node.quasis.map((element) => ({
type: 'StringLiteral',
value: element.value.raw,
start: element.start,
end: element.end,
}))];
expressions.sort((a, b) => a.start - b.start);
return new utils_1.naslTypes.StringInterpolation({
expressions: expressions.map((item) => transformNodeFunction(item, options))?.filter(Boolean),
});
}
exports.transform2StringInterpolation = transform2StringInterpolation;
function transform2Comment(node, options) {
if (node.type === 'EmptyStatement') {
if (node?.leadingComments) {
const newValue = node?.leadingComments?.[0]?.value?.replace(/\n/g, '<br>');
return new utils_1.naslTypes.Comment({
value: String(newValue),
});
}
}
const newValue = node?.value?.replace(/\n/g, '<br>');
return new utils_1.naslTypes.Comment({
value: String(newValue || ''),
});
}
exports.transform2Comment = transform2Comment;
function transformBlockStatement(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
return transformNodeFunction(node?.body?.[0], options);
}
function transform2PartialNewComposite(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const properties = [];
const rights = [];
const structureProperties = [];
const assignmentLines = [];
const newProperties = (node?.properties || node?.arguments?.[0]?.properties);
let idx = 0;
newProperties?.forEach((arg, index) => {
properties.push(transformNodeFunction(arg.key, options));
const calleeName = (0, utils_1.generate)(arg.value).code;
let sliceMembers = false;
if (arg.value.type === 'MemberExpression') {
const expression = flatMemberExpression(arg.value);
let members = getSelectMembers(transformNodeFunction(arg.value, options));
if (/app\.enums\./.test(calleeName || '')) {
rights.push(new utils_1.naslTypes.SelectMembers({
expression: members[0]?.object,
members,
}));
}
else if (/^(app\..+?)\.variables\.(.+)$|nasl\.auth\./.test(calleeName)) {
let expression = members[0]?.object;
if (!members.length) {
sliceMembers = true;
expression = transformNodeFunction(arg?.value, options);
}
rights.push(new utils_1.naslTypes.SelectMembers({
expression,
members,
}));
}
else {
let expressionNode = expression[0];
if (members[0] && members[0].object.concept !== 'Identifier') {
expressionNode = arg.value;
members = [];
}
const newExpression = transformNodeFunction(expressionNode, options);
if (!members.length) {
sliceMembers = true;
}
rights.push(new utils_1.naslTypes.SelectMembers({
expression: newExpression,
members,
}));
}
if (arg?.value) {
let rightIndex = [index - idx, members.length - 1];
if (sliceMembers) {
rightIndex = [index - idx];
}
assignmentLines.push(new utils_1.naslTypes.AssignmentLine({
leftIndex: [0, index],
rightIndex,
}));
}
}
else {
if (arg.value && arg.value?.name !== 'undefined') {
rights.push(new utils_1.naslTypes.SelectMembers({
expression: transformNodeFunction(arg.value, options)
}));
if (arg?.value) {
assignmentLines.push(new utils_1.naslTypes.AssignmentLine({
leftIndex: [0, index],
rightIndex: [index - idx],
}));
}
}
else {
idx += 1;
}
}
structureProperties.push(new utils_1.naslTypes.StructureProperty({
name: arg?.key?.name,
typeAnnotation: null
}));
});
return new utils_1.naslTypes.NewComposite({
typeAnnotation: utils_1.naslTypes.TypeAnnotation.createTypeAnonymousStructure(structureProperties),
properties,
rights,
assignmentLines
});
}
exports.transform2PartialNewComposite = transform2PartialNewComposite;
function transformNewExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
const calleeName = (0, utils_1.generate)(node.callee).code;
if (['Boolean', 'Integer', 'Double', 'Decimal', 'Long'].includes(calleeName)) {
return transformNodeFunction(node.arguments[0], {
...options,
typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive(calleeName),
});
}
else if (calleeName.includes('.entities.') || calleeName.includes('.structures.')) {
return transform2NewStructure(calleeName, node.arguments[0], options);
}
(0, utils_1.throwError)('Unhandled node', node.type, node);
}
exports.transformNewExpression = transformNewExpression;
function transformMemberExpression(node, options) {
const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem;
if (options.transformType === 'logic' && options.entityAsNames?.includes(node.object.name)) {
return new utils_1.naslTypes.QueryFi