@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
101 lines • 4.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Enrichments = exports.Enrichment = void 0;
exports.enrichmentContent = enrichmentContent;
exports.enrich = enrich;
const vertex_1 = require("../../dataflow/graph/vertex");
const identify_link_to_last_call_relation_1 = require("../../queries/catalog/call-context-query/identify-link-to-last-call-relation");
const assert_1 = require("../../util/assert");
const extract_cfg_1 = require("../../control-flow/extract-cfg");
const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
/**
* An enumeration that stores the names of the available enrichments that can be applied to a set of search elements.
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
*/
var Enrichment;
(function (Enrichment) {
Enrichment["CallTargets"] = "call-targets";
Enrichment["LastCall"] = "last-call";
})(Enrichment || (exports.Enrichment = Enrichment = {}));
/**
* The registry of enrichments that are currently supported by the search.
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
*/
exports.Enrichments = {
[Enrichment.CallTargets]: {
enrich: (e, data) => {
// we don't resolve aliases here yet!
const content = { targets: [] };
const callVertex = data.dataflow.graph.getVertex(e.node.info.id);
if (callVertex?.tag === vertex_1.VertexType.FunctionCall) {
const origins = (0, dfg_get_origin_1.getOriginInDfg)(data.dataflow.graph, callVertex.id);
if (!origins || origins.length === 0) {
content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
return content;
}
// find call targets in user code (which have ids!)
content.targets = content.targets.concat(origins.map(o => {
switch (o.type) {
case 2 /* OriginType.FunctionCallOrigin */:
return {
node: data.normalize.idMap.get(o.id),
};
case 3 /* OriginType.BuiltInFunctionOrigin */:
return o.fn.name;
default:
return undefined;
}
}).filter(assert_1.isNotUndefined));
if (content.targets.length === 0) {
content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
}
}
return content;
},
// as built-in call target enrichments are not nodes, we don't return them as part of the mapper!
mapper: ({ targets }) => targets.map(t => t).filter(t => t.node !== undefined)
},
[Enrichment.LastCall]: {
enrich: (e, data, args) => {
(0, assert_1.guard)(args && args.length, `${Enrichment.LastCall} enrichment requires at least one argument`);
const content = { linkedIds: [] };
const vertex = data.dataflow.graph.get(e.node.info.id);
if (vertex !== undefined && vertex[0].tag === vertex_1.VertexType.FunctionCall) {
const cfg = (0, extract_cfg_1.extractSimpleCfg)(data.normalize);
for (const arg of args) {
const lastCalls = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(vertex[0].id, cfg.graph, data.dataflow.graph, {
...arg,
callName: new RegExp(arg.callName),
type: 'link-to-last-call',
});
for (const lastCall of lastCalls) {
content.linkedIds.push({ node: data.normalize.idMap.get(lastCall) });
}
}
}
return content;
},
mapper: ({ linkedIds }) => linkedIds
},
};
/**
* Returns the content of the given enrichment type from a {@link FlowrSearchElement}.
* If the search element is not enriched with the given enrichment, `undefined` is returned.
* @param e - The search element whose enrichment content should be retrieved.
* @param enrichment - The enrichment content, if present, else `undefined`.
*/
function enrichmentContent(e, enrichment) {
return e?.enrichments?.[enrichment];
}
function enrich(e, data, enrichment, args) {
const enrichmentData = exports.Enrichments[enrichment];
return {
...e,
enrichments: {
...e?.enrichments ?? {},
[enrichment]: enrichmentData.enrich(e, data, args)
}
};
}
//# sourceMappingURL=search-enrichers.js.map