@@ -87,8 +87,6 @@ impl Crate {
87
87
) ;
88
88
}
89
89
90
- let shared_target_dir = clippy_project_root ( ) . join ( "target/lintcheck/shared_target_dir" ) ;
91
-
92
90
let cargo_home = env ! ( "CARGO_HOME" ) ;
93
91
94
92
// `src/lib.rs` -> `target/lintcheck/sources/crate-1.2.3/src/lib.rs`
@@ -132,7 +130,7 @@ impl Crate {
132
130
// The wrapper is set to `lintcheck` itself so we can force enable linting and ignore certain crates
133
131
// (see `crate::driver`)
134
132
let status = cmd
135
- . env ( "CARGO_TARGET_DIR" , shared_target_dir. join ( "recursive" ) )
133
+ . env ( "CARGO_TARGET_DIR" , shared_target_dir ( "recursive" ) )
136
134
. env ( "RUSTC_WRAPPER" , env:: current_exe ( ) . unwrap ( ) )
137
135
// Pass the absolute path so `crate::driver` can find `clippy-driver`, as it's executed in various
138
136
// different working directories
@@ -150,9 +148,10 @@ impl Crate {
150
148
cmd. arg ( "--message-format=json" ) ;
151
149
}
152
150
151
+ let shared_target_dir = shared_target_dir ( & format ! ( "_{thread_index:?}" ) ) ;
153
152
let all_output = cmd
154
153
// use the looping index to create individual target dirs
155
- . env ( "CARGO_TARGET_DIR" , shared_target_dir. join ( format ! ( "_{thread_index:?}" ) ) )
154
+ . env ( "CARGO_TARGET_DIR" , shared_target_dir. as_os_str ( ) )
156
155
// Roughly equivalent to `cargo clippy`/`cargo clippy --fix`
157
156
. env ( "RUSTC_WORKSPACE_WRAPPER" , clippy_driver_path)
158
157
. output ( )
@@ -186,7 +185,10 @@ impl Crate {
186
185
// get all clippy warnings and ICEs
187
186
let mut entries: Vec < ClippyCheckOutput > = Message :: parse_stream ( stdout. as_bytes ( ) )
188
187
. filter_map ( |msg| match msg {
189
- Ok ( Message :: CompilerMessage ( message) ) => ClippyWarning :: new ( message. message , & self . base_url ) ,
188
+ Ok ( Message :: CompilerMessage ( message) ) => ClippyWarning :: new (
189
+ normalize_diag ( message. message , shared_target_dir. to_str ( ) . unwrap ( ) ) ,
190
+ & self . base_url ,
191
+ ) ,
190
192
_ => None ,
191
193
} )
192
194
. map ( ClippyCheckOutput :: ClippyWarning )
@@ -202,6 +204,34 @@ impl Crate {
202
204
}
203
205
}
204
206
207
+ /// The target directory can sometimes be stored in the file name of spans.
208
+ /// This is problematic since the directory in constructed from the thread
209
+ /// ID and also used in our CI to determine if two lint emissions are the
210
+ /// same or not. This function simply normalizes the `_<thread_id>` to `_*`.
211
+ fn normalize_diag (
212
+ mut message : cargo_metadata:: diagnostic:: Diagnostic ,
213
+ thread_target_dir : & str ,
214
+ ) -> cargo_metadata:: diagnostic:: Diagnostic {
215
+ let mut dir_found = false ;
216
+ message
217
+ . spans
218
+ . iter_mut ( )
219
+ . filter ( |span| span. file_name . starts_with ( thread_target_dir) )
220
+ . for_each ( |span| {
221
+ dir_found = true ;
222
+ span. file_name
223
+ . replace_range ( 0 ..thread_target_dir. len ( ) , shared_target_dir ( "_*" ) . to_str ( ) . unwrap ( ) ) ;
224
+ } ) ;
225
+
226
+ if dir_found {
227
+ message
228
+ . rendered
229
+ . as_mut ( )
230
+ . map ( |rendered| * rendered = rendered. replace ( thread_target_dir, shared_target_dir ( "_*" ) . to_str ( ) . unwrap ( ) ) ) ;
231
+ }
232
+ message
233
+ }
234
+
205
235
/// Builds clippy inside the repo to make sure we have a clippy executable we can use.
206
236
fn build_clippy ( ) -> String {
207
237
let output = Command :: new ( "cargo" )
@@ -388,6 +418,15 @@ fn clippy_project_root() -> &'static Path {
388
418
Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) ) . parent ( ) . unwrap ( )
389
419
}
390
420
421
+ /// The qualifier can be used to separate different threads from another. By
422
+ /// default it should be set to `_<thread_id>`
423
+ #[ must_use]
424
+ fn shared_target_dir ( qualifier : & str ) -> PathBuf {
425
+ clippy_project_root ( )
426
+ . join ( "target/lintcheck/shared_target_dir" )
427
+ . join ( qualifier)
428
+ }
429
+
391
430
#[ test]
392
431
fn lintcheck_test ( ) {
393
432
let args = [
0 commit comments