@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
85 lines • 6.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEPRECATED_FUNCTIONS = void 0;
const vertex_1 = require("../../dataflow/graph/vertex");
const df_helper_1 = require("../../dataflow/graph/df-helper");
const identifier_1 = require("../../dataflow/environments/identifier");
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
const range_1 = require("../../util/range");
const linter_format_1 = require("../linter-format");
const linter_tags_1 = require("../linter-tags");
const function_finder_util_1 = require("./function-finder-util");
exports.DEPRECATED_FUNCTIONS = {
// unlike functionFinderUtil.createSearch(config.fns), this does not pre-filter to the hardcoded list: the
// sigdb-driven pass below needs every resolved call, so the `fns` filtering happens in processSearchResult instead
createSearch: (_config) => flowr_search_builder_1.Q.all().filter(vertex_1.VertexType.FunctionCall).with(search_enrichers_1.Enrichment.CallTargets, {
onlyBuiltin: true,
qualifyNames: false // we don't use qualified names for this rule yet
}),
processSearchResult: async (elements, config, data) => {
const matchesConfiguredFns = identifier_1.Identifier.regex(...config.fns);
const hardcoded = await function_finder_util_1.functionFinderUtil.processSearchResult(elements, config, data, es => es.filter(e => (0, search_enrichers_1.enrichmentContent)(e, search_enrichers_1.Enrichment.CallTargets)?.targets
.some(t => typeof t === 'string' && matchesConfiguredFns.test(t))));
const deps = data.inspectContext().deps;
if (deps.signatureSources().length === 0) {
return hardcoded;
}
// sigdb-driven detection: flag any resolved call whose signature-database entry marks it deprecated,
// even when it is not part of the hardcoded `fns` list above
const graph = (await data.dataflow()).graph;
const alreadyFlagged = new Set(hardcoded.results.map(r => r.involvedId));
const deprecatedByName = new Map();
const sigdbFlagged = [];
for (const element of elements.getElements()) {
const id = element.node.info.id;
if (alreadyFlagged.has(id)) {
continue;
}
const qualified = df_helper_1.Dataflow.qualify(id, graph);
if (qualified === undefined) {
continue;
}
const name = identifier_1.Identifier.toString(qualified);
let deprecated = deprecatedByName.get(name);
if (deprecated === undefined) {
deprecated = deps.signatureOf(qualified)?.props.includes('deprecated') === true;
deprecatedByName.set(name, deprecated);
}
if (!deprecated) {
continue;
}
const loc = range_1.SourceLocation.fromNode(element.node);
if (loc === undefined) {
continue;
}
alreadyFlagged.add(id);
sigdbFlagged.push({
certainty: linter_format_1.LintingResultCertainty.Certain,
involvedId: id,
function: name,
loc
});
}
return {
results: [...hardcoded.results, ...sigdbFlagged],
'.meta': {
totalCalls: hardcoded['.meta'].totalCalls + sigdbFlagged.length,
totalFunctionDefinitions: hardcoded['.meta'].totalFunctionDefinitions + sigdbFlagged.length
}
};
},
prettyPrint: function_finder_util_1.functionFinderUtil.prettyPrint('deprecated'),
info: {
name: 'Deprecated Functions',
tags: [linter_tags_1.LintingRuleTag.Deprecated, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
// the hardcoded `fns` list ensures every reported hit is real, but the list is pre-crawled and hence
// incomplete; the signature-database pass above adds recall for whichever packages are resolved
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
description: 'Marks deprecated functions that should not be used anymore.',
defaultConfig: {
fns: ['all_equal', 'arrange_all', 'distinct_all', 'filter_all', 'group_by_all', 'summarise_all', 'mutate_all', 'select_all', 'vars', 'all_vars', 'id', 'failwith', 'select_vars', 'rename_vars', 'select_var', 'current_vars', 'bench_tbls', 'compare_tbls', 'compare_tbls2', 'eval_tbls', 'eval_tbls2', 'location', 'changes', 'combine', 'do', 'funs', 'add_count_', 'add_tally_', 'arrange_', 'count_', 'distinct_', 'do_', 'filter_', 'funs_', 'group_by_', 'group_indices_', 'mutate_', 'tally_', 'transmute_', 'rename_', 'rename_vars_', 'select_', 'select_vars_', 'slice_', 'summarise_', 'summarize_', 'summarise_each', 'src_local', 'tbl_df', 'add_rownames', 'group_nest', 'group_split', 'with_groups', 'nest_by', 'progress_estimated', 'recode', 'sample_n', 'top_n', 'transmute', 'fct_explicit_na', 'aes_', 'aes_auto', 'annotation_logticks', 'is.Coord', 'coord_flip', 'coord_map', 'is.facet', 'fortify', 'is.ggproto', 'guide_train', 'is.ggplot', 'qplot', 'is.theme', 'gg_dep', 'liply', 'isplit2', 'list_along', 'cross', 'invoke', 'at_depth', 'prepend', 'rerun', 'splice', '`%@%`', 'rbernoulli', 'rdunif', 'when', 'update_list', 'map_raw', 'accumulate', 'reduce_right', 'flatten', 'map_dfr', 'as_vector', 'transpose', 'melt_delim', 'melt_fwf', 'melt_table', 'read_table2', 'str_interp', 'as_tibble', 'data_frame', 'tibble_', 'data_frame_', 'lst_', 'as_data_frame', 'as.tibble', 'frame_data', 'trunc_mat', 'is.tibble', 'tidy_names', 'set_tidy_names', 'repair_names', 'extract_numeric', 'complete_', 'drop_na_', 'expand_', 'crossing_', 'nesting_', 'extract_', 'fill_', 'gather_', 'nest_', 'separate_rows_', 'separate_', 'spread_', 'unite_', 'unnest_', 'extract', 'gather', 'nest_legacy', 'separate_rows', 'separate', 'spread']
}
}
};
//# sourceMappingURL=deprecated-functions.js.map