UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

101 lines 4.87 kB
"use strict"; 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