@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
73 lines • 3.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.STOP_WITH_CALL_ARG = void 0;
const linter_format_1 = require("../linter-format");
const range_1 = require("../../util/range");
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
const linter_tags_1 = require("../linter-tags");
const assert_1 = require("../../util/assert");
const vertex_1 = require("../../dataflow/graph/vertex");
const linker_1 = require("../../dataflow/internal/linker");
const general_1 = require("../../dataflow/eval/values/general");
const resolve_helper_1 = require("../../dataflow/environments/resolve-helper");
const df_helper_1 = require("../../dataflow/graph/df-helper");
exports.STOP_WITH_CALL_ARG = {
createSearch: () => flowr_search_builder_1.Q.var('stop').filter(vertex_1.VertexType.FunctionCall),
processSearchResult: async (elements, _config, data) => {
const dataflow = await data.dataflow();
const meta = {
consideredNodes: 0
};
return {
results: elements.getElements()
.filter(element => {
//only built-in functions
const origins = df_helper_1.Dataflow.origin(dataflow.graph, element.node.info.id);
if ((0, assert_1.isNotUndefined)(origins)) {
const builtIn = origins.every(e => e.type === 3 /* OriginType.BuiltInFunctionOrigin */);
if (!builtIn) {
return false;
}
}
const fCall = dataflow.graph.getVertex(element.node.info.id);
//filter out function calls with argument "call." set to false
const stopParamMap = {
'...': '...',
'call.': 'call.',
'domain': 'domain'
};
const mapping = (0, linker_1.pMatch)(fCall.args, stopParamMap);
const mappedToStop = mapping.get('call.') ?? [];
for (const argId of mappedToStop) {
const res = resolve_helper_1.Resolve.toValue(argId, { graph: dataflow.graph, environment: fCall.environment, ctx: data.inspectContext() });
const values = (0, general_1.valueSetGuard)(res);
if (values?.type === 'set' && values.elements.length !== 0) {
if (values.elements[0].type === 'logical') {
return values.elements[0].value;
}
}
}
return true;
})
.map(element => ({
certainty: linter_format_1.LintingResultCertainty.Uncertain,
involvedId: element.node.info.id,
loc: range_1.SourceLocation.fromNode(element.node)
}))
.filter(element => (0, assert_1.isNotUndefined)(element.loc)),
'.meta': meta
};
},
prettyPrint: {
[linter_format_1.LintingPrettyPrintContext.Query]: result => `\`stop()\` without \`call. = FALSE\` at ${range_1.SourceLocation.format(result.loc)}`,
[linter_format_1.LintingPrettyPrintContext.Full]: result => `\`stop()\` at ${range_1.SourceLocation.format(result.loc)} is called without \`call. = FALSE\`; the originating call is then appended to the error message, which is usually not intended - pass \`call. = FALSE\` to suppress it`,
},
info: {
name: 'Stop without call.=False argument',
tags: [linter_tags_1.LintingRuleTag.Smell],
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
description: 'Checks whether stop calls without call. argument set to FALSE are used.',
defaultConfig: {}
}
};
//# sourceMappingURL=stop-with-call-arg.js.map