New lint: redundant_test_prefix (#13710)
This PR has started as an effort to proceed from the feedback in rust-lang/rust-clippy#12861. - Checks test functions (functions marked with `#[test]` annotation) for redundant "test_" prefix. - Auto-fix is supported (and handles collisions gracefully, see below). - If removing "test_" prefix from, say, `test_foo()` results in a name collision (either because function `foo()` is already defined within the current scope, or because the `foo()` call exists within function -- thus creating an unwanted recursion), lint suggests function rename, warning the user that a simple trimming of `test_` prefix will result in a name collision. - If removing "test_" prefix results in invalid identifier (consider `test_const`, `test_`, `test_42`), then again no auto-fix is suggested, user is asked to rename function, with a note that a simple prefix trimming will result in an invalid function name. (`Applicability::HasPlaceholders` is used and user is suggested to: drop `test_` prefix + add `_works` suffix, i.e. `test_foo` becomes `foo_works` -- but again, user has to apply those changes manually). - If trimmed version of the function name is a valid identifier, doesn't result in name collision or unwanted recursion, then user is able to run auto-fix. fixes rust-lang/rust-clippy#8931 changelog: new lint: [`redundant_test_prefix`]
This commit is contained in:
commit
8eed35023f
10 changed files with 1151 additions and 1 deletions
|
|
@ -2641,7 +2641,9 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
|
|||
|
||||
static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalModDefId, Vec<Symbol>>>> = OnceLock::new();
|
||||
|
||||
fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
|
||||
/// Apply `f()` to the set of test item names.
|
||||
/// The names are sorted using the default `Symbol` ordering.
|
||||
fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(&[Symbol]) -> bool) -> bool {
|
||||
let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
|
||||
let mut map: MutexGuard<'_, FxHashMap<LocalModDefId, Vec<Symbol>>> = cache.lock().unwrap();
|
||||
let value = map.entry(module);
|
||||
|
|
@ -2695,6 +2697,25 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
|||
})
|
||||
}
|
||||
|
||||
/// Checks if `fn_def_id` has a `#[test]` attribute applied
|
||||
///
|
||||
/// This only checks directly applied attributes. To see if a node has a parent function marked with
|
||||
/// `#[test]` use [`is_in_test_function`].
|
||||
///
|
||||
/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
|
||||
pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool {
|
||||
let id = tcx.local_def_id_to_hir_id(fn_def_id);
|
||||
if let Node::Item(item) = tcx.hir_node(id)
|
||||
&& let ItemKind::Fn { ident, .. } = item.kind
|
||||
{
|
||||
with_test_item_names(tcx, tcx.parent_module(id), |names| {
|
||||
names.binary_search(&ident.name).is_ok()
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `id` has a `#[cfg(test)]` attribute applied
|
||||
///
|
||||
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue