UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

97 lines 5.11 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 identifier_1 = require("../../dataflow/environments/identifier"); const logic_1 = require("../../util/logic"); const df_helper_1 = require("../../dataflow/graph/df-helper"); /** * 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: { targets: identifier_1.Identifier.regex(...functions) } } })); }, async processSearchResult(elements, _config, _data, refineSearch = e => e) { const metadata = { totalCalls: 0, totalFunctionDefinitions: 0 }; const results = (await 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}` }; }, async requireArgumentValue(element, pool, analyzer, requireValue) { const dataflow = await analyzer.dataflow(); const identifier = df_helper_1.Dataflow.qualify(element.node.info.id, dataflow.graph, true) ?? (element.node.lexeme !== undefined ? identifier_1.Identifier.parse(element.node.lexeme) : undefined); /* if we have no additional info, we assume they always access the network */ if (identifier === undefined) { return logic_1.Ternary.Always; } // we allow our function pool to contain non-namespaced functions const info = pool.get(identifier_1.Identifier.toString(identifier)) ?? pool.get(identifier_1.Identifier.getName(identifier)); if (info === undefined) { return logic_1.Ternary.Always; } const vert = dataflow.graph.getVertex(element.node.info.id); if (vertex_1.FunctionCallVertex.is(vert)) { const args = (0, resolve_argument_1.getArgumentStringValue)(analyzer.flowrConfig.solver.variables, dataflow.graph, vert, info.argIdx, info.argName, info.resolveValue, analyzer.inspectContext()); // we obtain all values, at least one of them has to trigger for the request const argValues = args ? args.values().flatMap(s => Array.from(s)).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.includes(dependencies_query_format_1.Unknown)) { return logic_1.Ternary.Maybe; } } return logic_1.Ternary.Never; } }; //# sourceMappingURL=function-finder-util.js.map