UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

102 lines 4.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DoesCallQueryDefinition = void 0; const ansi_1 = require("../../../util/text/ansi"); const joi_1 = __importDefault(require("joi")); const does_call_query_executor_1 = require("./does-call-query-executor"); const args_1 = require("../../../util/text/args"); const strings_1 = require("../../../util/text/strings"); const range_1 = require("../../../util/range"); const FormatError = 'Invalid constraint format, expected format "(left:$id/"regex")"'; /** * Parses a constraint from a string argument. * Returns the constraint or an error message. */ function constraintParser(argument) { if (!argument?.startsWith('(') || !argument.includes(')')) { return FormatError + ` (got: "${argument}")`; } const endBracket = argument.indexOf(')'); const constrPart = argument.slice(1, endBracket); const args = (0, args_1.splitAtEscapeSensitive)(constrPart, true, ':'); if (args.length !== 2) { return FormatError + ` (got ${args.length} parts: ${args.join(', ')})`; } const [criteria, ...rhs] = args; const rhsStr = rhs.join(' '); if (rhsStr.startsWith('$')) { return { call: criteria, constraint: { type: 'calls-id', id: rhsStr.slice(1), } }; } else { const isExact = (0, strings_1.startAndEndsWith)(rhsStr, '"'); const name = isExact ? rhsStr.slice(1, -1) : rhsStr; return { call: criteria, constraint: { type: 'name', name: name, nameExact: isExact ? true : undefined, } }; } } function doesCallQueryLineParser(output, line, _config) { const constraint = constraintParser(line[0]); if (!constraint || typeof constraint === 'string') { output.stderr(output.formatter.format(`Invalid does-call query format:\n ${constraint}`, { color: 1 /* Colors.Red */, effect: ansi_1.ColorEffect.Foreground, style: 1 /* FontStyles.Bold */ })); return { query: [] }; } return { query: [ { type: 'does-call', queryId: constraint.call + ' (shorthand)', call: constraint.call, calls: constraint.constraint, } ], rCode: line[1] }; } exports.DoesCallQueryDefinition = { executor: does_call_query_executor_1.executeDoesCallQuery, asciiSummarizer: async (formatter, processed, queryResults, result) => { const out = queryResults; result.push(`Query: ${(0, ansi_1.bold)('does-call', formatter)} (${out['.meta'].timing.toFixed(0)}ms)`); for (const [r, v] of Object.entries(out.results)) { const idMap = (await processed.normalize()).idMap; result.push(` - ${(0, ansi_1.bold)(r, formatter)} found:`); if (v === false) { result.push(' - Does not call any matching functions.'); } else { const loc = idMap.get(v.call)?.location ?? undefined; result.push(` - Call with id ${(0, ansi_1.bold)(String(v.call), formatter)} (${range_1.SourceRange.format(loc)})`); } } return true; }, fromLine: doesCallQueryLineParser, schema: joi_1.default.object({ type: joi_1.default.string().valid('does-call').required().description('The type of the query.'), queryId: joi_1.default.string().optional().description('An optional unique identifier for this query, to identify it in the output.'), call: joi_1.default.string().description('The function from which calls are being made. This is a slicing criterion that resolves to a function definition node.'), calls: joi_1.default.object().required().description('The constraints on which functions are being called. This can be a combination of name-based or id-based constraints, combined with logical operators (and, or, one-of).') }).description('Either returns all function definitions alongside whether they are recursive, or just those matching the filters.'), flattenInvolvedNodes: (queryResults) => { const out = queryResults; return Object.entries(out.results).flatMap(([, v]) => { return v !== false ? v.call : []; }); } }; //# sourceMappingURL=does-call-query-format.js.map