UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

87 lines 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.functionFinderUtil = void 0; const flowr_search_builder_1 = require("../../search/flowr-search-builder"); const flowr_search_filters_1 = require("../../search/flowr-search-filters"); const search_enrichers_1 = require("../../search/search-executor/search-enrichers"); const range_1 = require("../../util/range"); const linter_format_1 = require("../linter-format"); const assert_1 = require("../../util/assert"); const resolve_argument_1 = require("../../dataflow/eval/resolve/resolve-argument"); const vertex_1 = require("../../dataflow/graph/vertex"); const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format"); const logic_1 = require("../../util/logic"); /** * This helper object collects utility functions used to create linting rules that search for specific functions. */ exports.functionFinderUtil = { createSearch: (functions) => { return (flowr_search_builder_1.Q.all().filter(vertex_1.VertexType.FunctionCall) .with(search_enrichers_1.Enrichment.CallTargets, { onlyBuiltin: true }) .filter({ name: flowr_search_filters_1.FlowrFilter.MatchesEnrichment, args: { enrichment: search_enrichers_1.Enrichment.CallTargets, test: (0, flowr_search_filters_1.testFunctionsIgnoringPackage)(functions) } })); }, processSearchResult: (elements, _config, _data, refineSearch = e => e) => { const metadata = { totalCalls: 0, totalFunctionDefinitions: 0 }; const results = refineSearch(elements.getElements()) .flatMap(element => { metadata.totalCalls++; return (0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.CallTargets).targets.map(target => { metadata.totalFunctionDefinitions++; return { node: element.node, loc: range_1.SourceLocation.fromNode(element.node), target: target, certainty: element.certainty }; }); }); return { results: results.map(element => ({ certainty: element.certainty ?? linter_format_1.LintingResultCertainty.Certain, involvedId: element.node.info.id, function: element.target, loc: element.loc })).filter(e => (0, assert_1.isNotUndefined)(e.loc)), '.meta': metadata }; }, prettyPrint: (functionType) => { return { [linter_format_1.LintingPrettyPrintContext.Query]: (result) => `Function \`${result.function}\` at ${range_1.SourceLocation.format(result.loc)}`, [linter_format_1.LintingPrettyPrintContext.Full]: (result) => `Function \`${result.function}\` called at ${range_1.SourceLocation.format(result.loc)} is related to ${functionType}` }; }, requireArgumentValue(element, pool, data, requireValue) { const info = pool.find(f => f.name === element.node.lexeme); /* if we have no additional info, we assume they always access the network */ if (info === undefined) { return logic_1.Ternary.Always; } const vert = data.dataflow.graph.getVertex(element.node.info.id); if ((0, vertex_1.isFunctionCallVertex)(vert)) { const args = (0, resolve_argument_1.getArgumentStringValue)(data.analyzer.flowrConfig.solver.variables, data.dataflow.graph, vert, info.argIdx, info.argName, info.resolveValue, data.analyzer.inspectContext()); // we obtain all values, at least one of them has to trigger for the request const argValues = args ? args.values().flatMap(v => [...v]).filter(assert_1.isNotUndefined).toArray() : []; if (argValues.length === 0) { return logic_1.Ternary.Maybe; } else if (argValues.some(v => requireValue instanceof RegExp ? requireValue.test(v) : v === requireValue)) { return logic_1.Ternary.Always; } else if (argValues.some(v => v === dependencies_query_format_1.Unknown)) { return logic_1.Ternary.Maybe; } } return logic_1.Ternary.Never; } }; //# sourceMappingURL=function-finder-util.js.map