2023-07-17 03:19:29 -05:00
|
|
|
use clippy_utils::diagnostics::span_lint_and_note;
|
|
|
|
use clippy_utils::{is_in_cfg_test, is_in_test_function};
|
|
|
|
use rustc_hir::intravisit::FnKind;
|
|
|
|
use rustc_hir::{Body, FnDecl};
|
2023-04-11 08:31:08 -05:00
|
|
|
use rustc_lint::{LateContext, LateLintPass};
|
|
|
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
2023-07-17 03:19:29 -05:00
|
|
|
use rustc_span::def_id::LocalDefId;
|
|
|
|
use rustc_span::Span;
|
2023-04-11 08:31:08 -05:00
|
|
|
|
|
|
|
declare_clippy_lint! {
|
|
|
|
/// ### What it does
|
|
|
|
/// Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module
|
|
|
|
/// (marked with `#[cfg(test)]`).
|
|
|
|
/// ### Why is this bad?
|
|
|
|
/// The idiomatic (and more performant) way of writing tests is inside a testing module (flagged with `#[cfg(test)]`),
|
|
|
|
/// having test functions outside of this module is confusing and may lead to them being "hidden".
|
|
|
|
/// ### Example
|
2023-11-02 11:35:56 -05:00
|
|
|
/// ```no_run
|
2023-04-11 08:31:08 -05:00
|
|
|
/// #[test]
|
|
|
|
/// fn my_cool_test() {
|
|
|
|
/// // [...]
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[cfg(test)]
|
|
|
|
/// mod tests {
|
|
|
|
/// // [...]
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// Use instead:
|
2023-11-02 11:35:56 -05:00
|
|
|
/// ```no_run
|
2023-04-11 08:31:08 -05:00
|
|
|
/// #[cfg(test)]
|
|
|
|
/// mod tests {
|
|
|
|
/// #[test]
|
|
|
|
/// fn my_cool_test() {
|
|
|
|
/// // [...]
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[clippy::version = "1.70.0"]
|
|
|
|
pub TESTS_OUTSIDE_TEST_MODULE,
|
|
|
|
restriction,
|
|
|
|
"A test function is outside the testing module."
|
|
|
|
}
|
|
|
|
|
|
|
|
declare_lint_pass!(TestsOutsideTestModule => [TESTS_OUTSIDE_TEST_MODULE]);
|
|
|
|
|
|
|
|
impl LateLintPass<'_> for TestsOutsideTestModule {
|
|
|
|
fn check_fn(
|
|
|
|
&mut self,
|
|
|
|
cx: &LateContext<'_>,
|
|
|
|
kind: FnKind<'_>,
|
|
|
|
_: &FnDecl<'_>,
|
|
|
|
body: &Body<'_>,
|
|
|
|
sp: Span,
|
|
|
|
_: LocalDefId,
|
|
|
|
) {
|
2023-11-16 12:13:24 -06:00
|
|
|
if !matches!(kind, FnKind::Closure)
|
|
|
|
&& is_in_test_function(cx.tcx, body.id().hir_id)
|
|
|
|
&& !is_in_cfg_test(cx.tcx, body.id().hir_id)
|
|
|
|
{
|
|
|
|
span_lint_and_note(
|
|
|
|
cx,
|
|
|
|
TESTS_OUTSIDE_TEST_MODULE,
|
|
|
|
sp,
|
|
|
|
"this function marked with #[test] is outside a #[cfg(test)] module",
|
|
|
|
None,
|
|
|
|
"move it to a testing module marked with #[cfg(test)]",
|
|
|
|
);
|
2023-04-11 08:31:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|