Skip to content

Commit 42d0970

Browse files
Jacherrblyxyas
authored andcommitted
Add support for ICE reporting in lintcheck
1 parent a79db2a commit 42d0970

1 file changed

Lines changed: 69 additions & 27 deletions

File tree

‎lintcheck/src/main.rs‎

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ use std::env::consts::EXE_SUFFIX;
1919
use std::fmt::{self,Writeas _};
2020
use std::io::{self,ErrorKind};
2121
use std::path::{Path,PathBuf};
22-
use std::process::Command;
22+
use std::process::{Command,ExitStatus};
2323
use std::sync::atomic::{AtomicUsize,Ordering};
2424
use std::time::Duration;
2525
use std::{env, fs, thread};
2626

27-
use cargo_metadata::diagnostic::{Diagnostic,DiagnosticLevel};
27+
use cargo_metadata::diagnostic::Diagnostic;
2828
use cargo_metadata::Message;
2929
use rayon::prelude::*;
3030
use serde::{Deserialize,Serialize};
@@ -90,16 +90,43 @@ struct Crate {
9090
options:Option<Vec<String>>,
9191
}
9292

93+
/// A single emitted output from clippy being executed on a crate. It may either be a
94+
/// `ClippyWarning`, or a `RustcIce` caused by a panic within clippy. A crate may have many
95+
/// `ClippyWarning`s but a maximum of one `RustcIce` (at which point clippy halts execution).
96+
#[derive(Debug)]
97+
enumClippyCheckOutput{
98+
ClippyWarning(ClippyWarning),
99+
RustcIce(RustcIce),
100+
}
101+
102+
#[derive(Debug)]
103+
structRustcIce{
104+
pubcrate_name:String,
105+
pubice_content:String,
106+
}
107+
implRustcIce{
108+
pubfnfrom_stderr_and_status(crate_name:&str,status:ExitStatus,stderr:&str) -> Option<Self>{
109+
if status.code().unwrap_or(0) == 101
110+
/* ice exit status */
111+
{
112+
Some(Self{
113+
crate_name: crate_name.to_owned(),
114+
ice_content: stderr.to_owned(),
115+
})
116+
}else{
117+
None
118+
}
119+
}
120+
}
121+
93122
/// A single warning that clippy issued while checking a `Crate`
94123
#[derive(Debug)]
95124
structClippyWarning{
96-
crate_name:String,
97125
file:String,
98126
line:usize,
99127
column:usize,
100128
lint_type:String,
101129
message:String,
102-
is_ice:bool,
103130
}
104131

105132
#[allow(unused)]
@@ -124,13 +151,11 @@ impl ClippyWarning {
124151
};
125152

126153
Some(Self{
127-
crate_name: crate_name.to_owned(),
128154
file,
129155
line: span.line_start,
130156
column: span.column_start,
131157
lint_type,
132158
message: diag.message,
133-
is_ice: diag.level == DiagnosticLevel::Ice,
134159
})
135160
}
136161

@@ -311,7 +336,7 @@ impl Crate {
311336
config:&LintcheckConfig,
312337
lint_filter:&[String],
313338
server:&Option<LintcheckServer>,
314-
) -> Vec<ClippyWarning>{
339+
) -> Vec<ClippyCheckOutput>{
315340
// advance the atomic index by one
316341
let index = target_dir_index.fetch_add(1,Ordering::SeqCst);
317342
// "loop" the index within 0..thread_limit
@@ -335,9 +360,9 @@ impl Crate {
335360
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
336361

337362
letmut cargo_clippy_args = if config.fix{
338-
vec!["--fix","--"]
363+
vec!["--quiet","--fix","--"]
339364
}else{
340-
vec!["--","--message-format=json","--"]
365+
vec!["--quiet","--message-format=json","--"]
341366
};
342367

343368
letmut clippy_args = Vec::<&str>::new();
@@ -428,14 +453,21 @@ impl Crate {
428453
}
429454

430455
// get all clippy warnings and ICEs
431-
letwarnings:Vec<ClippyWarning> = Message::parse_stream(stdout.as_bytes())
456+
letmut entries:Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
432457
.filter_map(|msg| match msg {
433458
Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message,&self.name,&self.version),
434459
_ => None,
435460
})
461+
.map(ClippyCheckOutput::ClippyWarning)
436462
.collect();
437463

438-
warnings
464+
ifletSome(ice) = RustcIce::from_stderr_and_status(&self.name,*status,&stderr){
465+
entries.push(ClippyCheckOutput::RustcIce(ice));
466+
}elseif !status.success(){
467+
println!("non-ICE bad exit status for {} {}: {}",self.name,self.version, stderr);
468+
}
469+
470+
entries
439471
}
440472
}
441473

@@ -635,7 +667,7 @@ fn main() {
635667
LintcheckServer::spawn(recursive_options)
636668
});
637669

638-
letmutclippy_warnings:Vec<ClippyWarning> = crates
670+
letmutclippy_entries:Vec<ClippyCheckOutput> = crates
639671
.par_iter()
640672
.flat_map(|krate| {
641673
krate.run_clippy_lints(
@@ -651,28 +683,31 @@ fn main() {
651683
.collect();
652684

653685
ifletSome(server) = server {
654-
clippy_warnings.extend(server.warnings());
686+
let server_clippy_entries = server.warnings().map(ClippyCheckOutput::ClippyWarning);
687+
688+
clippy_entries.extend(server_clippy_entries);
655689
}
656690

657691
// if we are in --fix mode, don't change the log files, terminate here
658692
if config.fix{
659693
return;
660694
}
661695

662-
// generate some stats
663-
let(stats_formatted, new_stats) = gather_stats(&clippy_warnings);
696+
// split up warnings and ices
697+
letmut warnings:Vec<ClippyWarning> = vec![];
698+
letmut raw_ices:Vec<RustcIce> = vec![];
699+
for entry in clippy_entries {
700+
ifletClippyCheckOutput::ClippyWarning(x) = entry {
701+
warnings.push(x);
702+
}elseifletClippyCheckOutput::RustcIce(x) = entry {
703+
raw_ices.push(x);
704+
}
705+
}
664706

665-
// grab crashes/ICEs, save the crate name and the ice message
666-
let ices:Vec<(&String,&String)> = clippy_warnings
667-
.iter()
668-
.filter(|warning| warning.is_ice)
669-
.map(|w| (&w.crate_name,&w.message))
670-
.collect();
707+
// generate some stats
708+
let(stats_formatted, new_stats) = gather_stats(&warnings);
671709

672-
letmut all_msgs:Vec<String> = clippy_warnings
673-
.iter()
674-
.map(|warn| warn.to_output(config.markdown))
675-
.collect();
710+
letmut all_msgs:Vec<String> = warnings.iter().map(|warn| warn.to_output(config.markdown)).collect();
676711
all_msgs.sort();
677712
all_msgs.push("\n\n### Stats:\n\n".into());
678713
all_msgs.push(stats_formatted);
@@ -686,11 +721,18 @@ fn main() {
686721
}
687722
write!(text,"{}", all_msgs.join("")).unwrap();
688723
text.push_str("\n\n### ICEs:\n");
689-
for(cratename, msg)in&ices {
690-
let _: fmt::Result = write!(text,"{cratename}: '{msg}'");
724+
for ice in&raw_ices {
725+
let _: fmt::Result = write!(
726+
text,
727+
"{}:\n{}\n========================================\n\n",
728+
ice.crate_name, ice.ice_content
729+
);
691730
}
692731

693732
println!("Writing logs to {}", config.lintcheck_results_path.display());
733+
if !raw_ices.is_empty(){
734+
println!("WARNING: at least one ICE reported, check log file");
735+
}
694736
fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
695737
fs::write(&config.lintcheck_results_path, text).unwrap();
696738

0 commit comments

Comments
 (0)