@@ -5,7 +5,9 @@ use rustc_hir::{Body, FnDecl};
5
5
use rustc_lint:: { LateContext , LateLintPass } ;
6
6
use rustc_session:: declare_lint_pass;
7
7
use rustc_span:: def_id:: LocalDefId ;
8
- use rustc_span:: Span ;
8
+ use rustc_span:: source_map:: SourceMap ;
9
+ use rustc_span:: { FileName , RealFileName , Span } ;
10
+ use std:: path:: Component ;
9
11
10
12
declare_clippy_lint ! {
11
13
/// ### What it does
@@ -15,6 +17,7 @@ declare_clippy_lint! {
15
17
/// ### Why restrict this?
16
18
/// The idiomatic (and more performant) way of writing tests is inside a testing module (flagged with `#[cfg(test)]`),
17
19
/// having test functions outside of this module is confusing and may lead to them being "hidden".
20
+ /// This does not apply to integration tests though, and this lint will ignore those.
18
21
///
19
22
/// ### Example
20
23
/// ```no_run
@@ -59,6 +62,7 @@ impl LateLintPass<'_> for TestsOutsideTestModule {
59
62
) {
60
63
if !matches ! ( kind, FnKind :: Closure )
61
64
&& is_in_test_function ( cx. tcx , body. id ( ) . hir_id )
65
+ && !is_integration_test ( cx. tcx . sess . source_map ( ) , sp)
62
66
&& !is_in_cfg_test ( cx. tcx , body. id ( ) . hir_id )
63
67
{
64
68
#[ expect( clippy:: collapsible_span_lint_calls, reason = "rust-clippy#7797" ) ]
@@ -74,3 +78,12 @@ impl LateLintPass<'_> for TestsOutsideTestModule {
74
78
}
75
79
}
76
80
}
81
+
82
+ fn is_integration_test ( sm : & SourceMap , sp : Span ) -> bool {
83
+ match sm. span_to_filename ( sp) {
84
+ FileName :: Real ( RealFileName :: LocalPath ( name) ) => {
85
+ name. components ( ) . next ( ) == Some ( Component :: Normal ( "tests" . as_ref ( ) ) )
86
+ } ,
87
+ _ => false ,
88
+ }
89
+ }
0 commit comments