@lcap/builder
Version:
lcap builder utils
201 lines (200 loc) • 8.54 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformFunc2Nasl = exports.transformVariable = exports.transformStatement = exports.transformParam2Nasl = void 0;
const utils_1 = require("./utils");
const transform_expression2nasl_1 = __importDefault(require("./transform-expression2nasl"));
const transform_tstype2nasl_1 = __importDefault(require("./transform-tstype2nasl"));
const getTypeAnnotation = (typeAnnotation) => {
if (typeAnnotation && typeAnnotation.type === 'TSTypeAnnotation') {
return (0, transform_tstype2nasl_1.default)(typeAnnotation.typeAnnotation);
}
return null;
};
const getRestElementTypeAnnotation = (param, typeNames = []) => {
if (!param.typeAnnotation || param.typeAnnotation.type !== 'TSTypeAnnotation') {
return null;
}
if (param.typeAnnotation.typeAnnotation.type === 'TSTypeReference'
&& ((param.typeAnnotation.typeAnnotation.typeName.type === 'TSQualifiedName'
&& param.typeAnnotation.typeAnnotation.typeName.right.name === 'List') || (param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier'
&& param.typeAnnotation.typeAnnotation.typeName.name === 'Array'))
&& param.typeAnnotation.typeAnnotation.typeParameters
&& param.typeAnnotation.typeAnnotation.typeParameters.params
&& param.typeAnnotation.typeAnnotation.typeParameters.params.length > 0) {
return (0, transform_tstype2nasl_1.default)(param.typeAnnotation.typeAnnotation.typeParameters.params[0], typeNames);
}
if (param.typeAnnotation.typeAnnotation.type === 'TSArrayType') {
return (0, transform_tstype2nasl_1.default)(param.typeAnnotation.typeAnnotation.elementType, typeNames);
}
return (0, transform_tstype2nasl_1.default)(param.typeAnnotation.typeAnnotation, typeNames);
};
function transformParam2Nasl(paramAST) {
switch (paramAST.type) {
case 'Identifier':
return {
concept: 'Param',
name: paramAST.name,
description: '',
typeAnnotation: getTypeAnnotation(paramAST.typeAnnotation),
};
case 'RestElement':
if (paramAST.argument.type !== 'Identifier') {
throw new Error(`解析函数参数失败,不支持该参数类型 ${(0, utils_1.getNodeCode)(paramAST)}`);
}
return {
concept: 'Param',
name: paramAST.argument.name,
description: '',
spread: true,
typeAnnotation: getRestElementTypeAnnotation(paramAST),
};
case 'AssignmentPattern':
if (paramAST.left.type !== 'Identifier') {
throw new Error(`解析函数参数失败,不支持该参数类型 ${(0, utils_1.getNodeCode)(paramAST)}`);
}
return {
concept: 'Param',
name: paramAST.left.name,
description: '',
typeAnnotation: getTypeAnnotation(paramAST.left.typeAnnotation),
defaultValue: {
concept: 'DefaultValue',
expression: (0, transform_expression2nasl_1.default)(paramAST.right),
playground: [],
},
};
default:
throw new Error(`解析函数参数失败,不支持该参数类型 ${(0, utils_1.getNodeCode)(paramAST)}`);
}
}
exports.transformParam2Nasl = transformParam2Nasl;
function transformStatement(statement) {
if (statement.type === 'BlockStatement') {
return statement.body.map(transformStatement);
}
if (statement.type === 'IfStatement') {
return {
concept: 'IfStatement',
test: (0, transform_expression2nasl_1.default)(statement.test),
consequent: (0, utils_1.normalizeArray)(transformStatement(statement.consequent)),
alternate: statement.alternate ? (0, utils_1.normalizeArray)(transformStatement(statement.alternate)) : [],
};
}
if (statement.type === 'SwitchStatement' && statement.discriminant) {
const testLeft = (0, transform_expression2nasl_1.default)(statement.discriminant);
return {
concept: 'SwitchStatement',
cases: statement.cases.map((switchCaseAST) => ({
concept: 'SwitchCase',
test: {
concept: 'BinaryExpression',
left: testLeft,
right: switchCaseAST.test ? (0, transform_expression2nasl_1.default)(switchCaseAST.test) : null,
operator: '==',
},
consequent: switchCaseAST.consequent.map((st) => transformStatement(st)).flat(),
})),
};
}
if (statement.type === 'ForInStatement') {
if (statement.left.type !== 'VariableDeclaration') {
throw new Error('解析 for in 语句失败, 左侧仅允许定义变量,例如 var xxx in list');
}
return {
concept: 'ForEachStatement',
each: (0, transform_expression2nasl_1.default)(statement.right),
item: {
concept: 'Param',
name: statement.left.declarations[0].id && statement.left.declarations[0].id.type === 'Identifier' ? statement.left.declarations[0].id.name : 'item',
description: '',
},
index: {
concept: 'Param',
name: statement.left.declarations[1] && statement.left.declarations[1].id && statement.left.declarations[1].id.type === 'Identifier' ? statement.left.declarations[1].id.name : 'index',
description: '',
},
start: {
concept: 'NumericLiteral',
value: 0,
},
body: (0, utils_1.normalizeArray)(transformStatement(statement.body)),
};
}
if (statement.type === 'WhileStatement') {
return {
concept: 'WhileStatement',
test: (0, transform_expression2nasl_1.default)(statement.test),
body: (0, utils_1.normalizeArray)(transformStatement(statement.body)),
};
}
if (statement.type === 'ExpressionStatement') {
return (0, transform_expression2nasl_1.default)(statement.expression);
}
if (statement.type === 'ReturnStatement') {
return {
concept: 'End',
};
}
throw new Error(`解析语句失败, Nasl 不支持该语法, ${(0, utils_1.getNodeCode)(statement)}`);
}
exports.transformStatement = transformStatement;
function transformVariable(ast) {
if (ast.id.type !== 'Identifier') {
throw new Error(`解析变量定义失败, ${(0, utils_1.getNodeCode)(ast)}`);
}
const variable = {
concept: 'Variable',
name: ast.id.name,
description: '',
};
if (ast.id.typeAnnotation && ast.id.typeAnnotation.type === 'TSTypeAnnotation') {
variable.typeAnnotation = (0, transform_tstype2nasl_1.default)(ast.id.typeAnnotation.typeAnnotation);
}
if (ast.init) {
variable.defaultValue = (0, transform_expression2nasl_1.default)(ast.init);
}
return variable;
}
exports.transformVariable = transformVariable;
function transformFunc2Nasl(funcAst) {
if (!funcAst.id) {
throw new Error('解析函数失败,未定义函数名称');
}
const variables = [];
const statements = funcAst.body.body.filter((s) => {
if (s.type !== 'VariableDeclaration') {
return true;
}
s.declarations.forEach((decla) => {
if (decla.id && decla.id.type === 'Identifier') {
variables.push(transformVariable(decla));
}
});
return false;
});
const Logic = {
concept: 'Logic',
name: funcAst.id.name,
variables,
params: funcAst.params.map(transformParam2Nasl),
returns: [],
playground: [],
body: [
{
concept: 'Start',
},
...statements.map(transformStatement),
],
};
if (Logic.body[Logic.body.length - 1].concept !== 'End') {
Logic.body.push({
concept: 'End',
});
}
return Logic;
}
exports.transformFunc2Nasl = transformFunc2Nasl;
exports.default = transformFunc2Nasl;