UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

407 lines 13.8 kB
"use strict"; 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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.pickDecoratorObject = exports.checkOQLCalleeNameOrder = exports.fetchFromComments = exports.handleListSort = exports.upgradeListSort = exports.replaceCallFunctionMap = exports.callFunctionMap = exports.tryParseTS = exports.throwWarning = exports.throwError = exports.ParseNaturalTSError = exports.parseNaturalTSErrorMap = exports.DEBUG = exports.generate = exports.naslTypes = exports.babelTypes = void 0; const babel = __importStar(require("@babel/core")); const babelTypes = __importStar(require("@babel/types")); exports.babelTypes = babelTypes; const naslTypes = __importStar(require("../../concepts")); exports.naslTypes = naslTypes; const generator_1 = __importDefault(require("@babel/generator")); exports.generate = generator_1.default; // Dynamic DEBUG function to allow runtime environment variable changes function DEBUG() { return process.env.NATURAL_TS_THROW_ERROR === 'true'; } exports.DEBUG = DEBUG; exports.parseNaturalTSErrorMap = {}; class ParseNaturalTSError extends Error { constructor(message) { super(message); this.name = 'ParseNaturalTSError'; } } exports.ParseNaturalTSError = ParseNaturalTSError; /** * 抛出错误 * @param message 错误信息 * @param babelNode babel节点,用于便捷生成代码片段信息 * @param babelNode2 babel节点,用于便捷生成代码片段信息 */ function throwError(state, message, babelNode, babelNode2) { if (state.nodeNamespace) { let namespaceAndName = `${state.nodeNamespace}.${state.nodeName ? state.nodeName : '*'}`; if (state.nodeName && state.appendExtName) { namespaceAndName += state.nodeNamespace.includes('.views.') ? '.tsx' : '.ts'; } message += '\n**可能的位置**: ' + namespaceAndName; } if (babelNode) { let code = typeof babelNode === 'string' ? babelNode : (0, generator_1.default)(babelNode).code; message += '\n**相关代码片段**: ' + code.slice(0, 1000); } if (babelNode2) { let code = typeof babelNode2 === 'string' ? babelNode2 : (0, generator_1.default)(babelNode2).code; message += '\n**更多代码片段**: ' + code.slice(0, 1000); } if (!state.parsingId) { throw new ParseNaturalTSError(message); } else { const keys = Object.keys(exports.parseNaturalTSErrorMap).map(Number).sort(); keys.forEach((key) => { if (state.parsingId - key > 1000 * 60 * 60) delete exports.parseNaturalTSErrorMap[key]; }); const errors = exports.parseNaturalTSErrorMap[state.parsingId] = exports.parseNaturalTSErrorMap[state.parsingId] || []; errors.push(message); } } exports.throwError = throwError; /** * 抛出警告,在 DEBUG 模式下不抛出这类错误 * @param message 错误信息 * @param babelNode babel节点,用于便捷生成代码片段信息 * @param babelNode2 babel节点,用于便捷生成代码片段信息 */ function throwWarning(message, babelNode, babelNode2) { if (DEBUG()) return; if (babelNode) { let code = typeof babelNode === 'string' ? babelNode : (0, generator_1.default)(babelNode).code; message += ':' + code.slice(0, 1000); } if (babelNode2) { let code = typeof babelNode2 === 'string' ? babelNode2 : (0, generator_1.default)(babelNode2).code; message += '\n' + code.slice(0, 1000); } throw new Error(message); } exports.throwWarning = throwWarning; function tryParseTS(tsCode) { try { const root = babel.parseSync(tsCode, { filename: 'result.ts', presets: [require('@babel/preset-typescript')], }); // console.log((root as any).program.body[0].body.body.map((item) => item.trailingComments)); return root; } catch (e) { return null; } } exports.tryParseTS = tryParseTS; exports.callFunctionMap = [ 'Convert', 'FormatNumber', 'FormatDateTime', 'FormatDate', 'FromString', 'ToString', 'Length', 'IndexOf', 'Join', 'LastIndexOf', 'Replace', 'Split', 'SubString', 'ToLower', 'ToUpper', 'Trim', 'CurrDate', 'CurrDateTime', 'CurrTime', 'DateDiff', 'AlterDateTime', 'GetDateCount', 'GetSpecificDaysOfWeek', 'ListAdd', 'ListAddAll', 'ListContains', 'ListInsert', 'ListDistinct', 'ListDistinctBy', 'ListFilter', 'ListFind', 'ListFindIndex', 'ListFlatten', 'ListGroupBy', 'ListHead', 'ListLast', 'ListMax', 'ListMin', 'ListReverse', 'ListSlice', 'ListSort', 'ListSum', 'ListToMap', 'ListTransform', 'ListGet', 'ListRemove', 'ListRemoveAt', 'ListSet', 'ListRange', 'ListRepeat', 'MapContains', 'MapGet', 'MapPut', 'MapKeys', 'MapRemove', 'MapValues', 'EnumToList', 'EnumItemToText', 'Round', 'Clear', 'Clone', 'HasValue', 'RandomInt', 'NewList', 'NewMap', 'NewEntity', 'NewStructure', 'NewAnonymousStructure', 'jsonSerialize', 'jsonDeserialize', "Add", "AddAll", "Contains", "Insert", "Get", "Remove", "RemoveAt", "Set", "Ceil", "Floor", "Trunc", "TruncDivide", "Abs", "Pow", "Sqrt", "Cbrt", "Log", "PadStart", "PadEnd", "TrimStart", "TrimEnd", ]; exports.replaceCallFunctionMap = { "ListAdd": "Add", "ListAddAll": "AddAll", "ListContains": "Contains", "ListInsert": "Insert", "ListGet": "Get", "ListRemove": "Remove", "ListRemoveAt": "RemoveAt", "ListSet": "Set", "COUNTD": "COUNT", }; function upgradeListSort(node) { const asc = node?.arguments?.[2]?.expression; const by = node?.arguments?.[1]?.expression; const newArgument = [ { ...node.arguments[0] }, { concept: 'Argument', keyword: 'fn1', expression: { concept: 'AnonymousFunction', body: { concept: 'NewComposite', typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'anonymousStructure', properties: [ { concept: 'StructureProperty', name: 'asc', typeAnnotation: { concept: 'TypeAnnotation', typeKind: 'primitive', typeNamespace: 'nasl.core', typeName: 'Boolean' } }, { concept: 'StructureProperty', name: 'by', typeAnnotation: null } ] }, properties: [ { concept: 'Identifier', name: 'asc', folded: false, typeAnnotation: null }, { concept: 'Identifier', name: 'by', folded: false, typeAnnotation: null } ], rights: [ { concept: 'SelectMembers', hideMembers: false, expression: asc, members: [] } ], assignmentLines: [ { concept: 'AssignmentLine', leftIndex: [0, 0], rightIndex: [0] } ] }, params: by?.params } } ]; if (by?.body) { newArgument[1].expression.body.rights.push({ concept: 'SelectMembers', hideMembers: false, expression: by.body, members: [] }); newArgument[1].expression.body.assignmentLines.push({ concept: 'AssignmentLine', leftIndex: [0, 1], rightIndex: [1] }); } node.arguments = newArgument; return node; } exports.upgradeListSort = upgradeListSort; function handleListSort(node, parseState) { const args = node?.arguments; if (args?.[args?.length - 1]?.expression?.concept === 'BooleanLiteral') { if (DEBUG) return throwError(parseState, '调用 ListSort 函数需要使用最新的写法'); // 老的 ListSort 结构'nasl.util.ListSort(variable1, (item) => item, true)',要升级成新的 return upgradeListSort(node); } else { args?.forEach((arg, index) => { // 新的 ListSort: nasl.util.ListSort(list, (item) => ({ asc: true, by: item.name})) if (index !== 0) { const argExpression = arg?.expression; if (argExpression?.concept === 'AnonymousFunction' && argExpression?.body?.concept === 'NewComposite') { // 做下特殊处理 if (argExpression?.body?.rights[1] && argExpression?.body?.rights[1]?.members[0]) { argExpression.body.rights[1].expression = argExpression?.body?.rights[1]?.members[0]; argExpression.body.rights[1].members = []; argExpression.body.assignmentLines[1].rightIndex = [1]; } if (!argExpression?.params?.length) { argExpression.params = [ { concept: 'Param', name: 'item', typeAnnotation: null } ]; } } } }); return node; } } exports.handleListSort = handleListSort; function fetchFromComments(comments) { if (!comments || comments.length === 0) return; return comments[0].value.trim(); } exports.fetchFromComments = fetchFromComments; const expectedOrder = [ "FROM", "JOIN", "WHERE", "GROUP_BY", "SELECT", "HAVING", "ORDER_BY", ]; function checkOQLCalleeNameOrder(calleeNames) { let currentIndex = -1; for (const name of calleeNames) { const expectedIndex = expectedOrder.findIndex((item) => name?.includes(item)); if (expectedIndex === -1) { // 如果名称不在期望顺序中,返回 false return false; } if (expectedIndex < currentIndex) { // 如果当前名称的索引小于前一个名称的索引,返回 false return false; } currentIndex = expectedIndex; } return true; } exports.checkOQLCalleeNameOrder = checkOQLCalleeNameOrder; function pickDecoratorObject(objectExpression, keys, parseState) { const result = {}; objectExpression.properties.forEach((item) => { if (item.type === 'ObjectProperty' && item.key.type === 'Identifier' && keys.has(item.key.name)) { let value; if (item.value.type === 'NullLiteral') { value = null; } else if (item.value.type === 'BooleanLiteral') { value = item.value.value; } else if (item.value.type === 'StringLiteral') { value = item.value.value; } else if (item.value.type === 'NumericLiteral') { value = item.value.value; } else { return throwError(parseState, '不支持的装饰器对象属性值:' + (0, generator_1.default)(item).code); } result[item.key.name] = value; } else { return throwError(parseState, '不支持的装饰器对象属性:' + (0, generator_1.default)(item).code); } }); return result; } exports.pickDecoratorObject = pickDecoratorObject; //# sourceMappingURL=utils.js.map