@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
66 lines • 2.68 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 built_in_proc_name_1 = require("../environments/built-in-proc-name");
const vertex_1 = require("../graph/vertex");
const graph_1 = require("../graph/graph");
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 (vertex_1.FunctionDefinitionVertex.is(vtx)) {
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 (vertex_1.FunctionCallVertex.is(vtx) && 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) ?? graph_1.NoEdges;
for (const [out] of outEdges) {
if (!visited.has(out)) {
toVisit.push(out);
}
}
}
collectedExceptions[id] = mine;
return collectedExceptions;
}
//# sourceMappingURL=exceptions-of-function.js.map