@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
97 lines • 5.11 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 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