@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
87 lines • 4.46 kB
JavaScript
;
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