@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
65 lines • 2.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateExceptionsOfFunction = calculateExceptionsOfFunction;
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
const vertex_1 = require("../graph/vertex");
const built_in_proc_name_1 = require("../environments/built-in-proc-name");
const CatchHandlers = new Set([built_in_proc_name_1.BuiltInProcName.Try]);
/**
* Collect exception sources of a function in the call graph.
* This returns the `NodeId`s of functions that may throw exceptions when called by the given function.
* Please be aware, that these are restricted to functions known by flowR.
* With `knownThrower` you can provide additional functions that are known to throw exceptions.
* @returns A record mapping all `NodeId`s of functions that may throw exceptions to their exception points.
*/
function calculateExceptionsOfFunction(id, graph, knownThrower = {}) {
const collectedExceptions = {};
const mine = [];
const visited = new Set();
const toVisit = [id];
while (toVisit.length > 0) {
const currentId = toVisit.pop();
if (visited.has(currentId)) {
continue;
}
visited.add(currentId);
const kt = knownThrower[currentId];
if (kt) {
for (const e of kt) {
if (!mine.includes(e)) {
mine.push(e);
}
}
continue;
}
const vtx = graph.getVertex(currentId);
if (!vtx) {
continue;
}
if (node_id_1.NodeId.isBuiltIn(currentId)) {
continue;
}
if (vtx.tag === vertex_1.VertexType.FunctionDefinition) {
const es = vtx.exitPoints.filter(e => e.type === 4 /* ExitPointType.Error */).map(e => ({ id: e.nodeId, cds: e.cds }));
for (const e of es) {
if (!mine.includes(e)) {
mine.push(e);
}
}
collectedExceptions[vtx.id] = es;
}
else if (vtx.tag === vertex_1.VertexType.FunctionCall && vtx.origin !== 'unnamed' && vtx.origin.some(c => CatchHandlers.has(c))) {
// skip the try-catch handlers as they catch all exceptions within their body
continue;
}
const outEdges = graph.outgoingEdges(currentId) ?? [];
for (const [out] of outEdges) {
if (!visited.has(out)) {
toVisit.push(out);
}
}
}
collectedExceptions[id] = mine;
return collectedExceptions;
}
//# sourceMappingURL=exceptions-of-function.js.map