Skip to content

Commit d6fca46

Browse files
committed
Update lintcheck output to use tables and add markdown support
1 parent e42f79c commit d6fca46

File tree

1 file changed

+70
-28
lines changed

1 file changed

+70
-28
lines changed

lintcheck/src/main.rs

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::process::Command;
1212
use std::sync::atomic::{AtomicUsize, Ordering};
1313
use std::{collections::HashMap, io::ErrorKind};
1414
use std::{
15-
env, fmt,
15+
env,
1616
fs::write,
1717
path::{Path, PathBuf},
1818
thread,
@@ -101,13 +101,28 @@ struct ClippyWarning {
101101
is_ice: bool,
102102
}
103103

104-
impl std::fmt::Display for ClippyWarning {
105-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106-
writeln!(
107-
f,
108-
r#"target/lintcheck/sources/{}-{}/{}:{}:{} {} "{}""#,
109-
&self.crate_name, &self.crate_version, &self.file, &self.line, &self.column, &self.linttype, &self.message
110-
)
104+
#[allow(unused)]
105+
impl ClippyWarning {
106+
fn to_output(&self, markdown: bool) -> String {
107+
let file = format!("{}-{}/{}", &self.crate_name, &self.crate_version, &self.file);
108+
let file_with_pos = format!("{}:{}:{}", &file, &self.line, &self.column);
109+
if markdown {
110+
let lint = format!("`{}`", self.linttype);
111+
112+
let mut output = String::from("| ");
113+
output.push_str(&format!(
114+
"[`{}`](../target/lintcheck/sources/{}#L{})",
115+
file_with_pos, file, self.line
116+
));
117+
output.push_str(&format!(r#" | {:<50} | "{}" |"#, lint, self.message));
118+
output.push('\n');
119+
output
120+
} else {
121+
format!(
122+
"target/lintcheck/sources/{} {} \"{}\"\n",
123+
file_with_pos, self.linttype, self.message
124+
)
125+
}
111126
}
112127
}
113128

@@ -378,6 +393,8 @@ struct LintcheckConfig {
378393
fix: bool,
379394
/// A list of lint that this lintcheck run shound focus on
380395
lint_filter: Vec<String>,
396+
/// Indicate if the output should support markdown syntax
397+
markdown: bool,
381398
}
382399

383400
impl LintcheckConfig {
@@ -393,12 +410,17 @@ impl LintcheckConfig {
393410
.to_string()
394411
});
395412

413+
let markdown = clap_config.is_present("markdown");
396414
let sources_toml_path = PathBuf::from(sources_toml);
397415

398416
// for the path where we save the lint results, get the filename without extension (so for
399417
// wasd.toml, use "wasd"...)
400418
let filename: PathBuf = sources_toml_path.file_stem().unwrap().into();
401-
let lintcheck_results_path = PathBuf::from(format!("lintcheck-logs/{}_logs.txt", filename.display()));
419+
let lintcheck_results_path = PathBuf::from(format!(
420+
"lintcheck-logs/{}_logs.{}",
421+
filename.display(),
422+
if markdown { "md" } else { "txt" }
423+
));
402424

403425
// look at the --threads arg, if 0 is passed, ask rayon rayon how many threads it would spawn and
404426
// use half of that for the physical core count
@@ -440,6 +462,7 @@ impl LintcheckConfig {
440462
lintcheck_results_path,
441463
fix,
442464
lint_filter,
465+
markdown,
443466
}
444467
}
445468
}
@@ -601,10 +624,15 @@ fn gather_stats(clippy_warnings: &[ClippyWarning]) -> (String, HashMap<&String,
601624
// to not have a lint with 200 and 2 warnings take the same spot
602625
stats.sort_by_key(|(lint, count)| format!("{:0>4}, {}", count, lint));
603626

627+
let mut header = String::from("| lint | count |\n");
628+
header.push_str("| -------------------------------------------------- | ----- |\n");
604629
let stats_string = stats
605630
.iter()
606-
.map(|(lint, count)| format!("{} {}\n", lint, count))
607-
.collect::<String>();
631+
.map(|(lint, count)| format!("| {:<50} | {:>4} |\n", lint, count))
632+
.fold(header, |mut table, line| {
633+
table.push_str(&line);
634+
table
635+
});
608636

609637
(stats_string, counter)
610638
}
@@ -802,15 +830,23 @@ pub fn main() {
802830
.map(|w| (&w.crate_name, &w.message))
803831
.collect();
804832

805-
let mut all_msgs: Vec<String> = clippy_warnings.iter().map(ToString::to_string).collect();
833+
let mut all_msgs: Vec<String> = clippy_warnings
834+
.iter()
835+
.map(|warn| warn.to_output(config.markdown))
836+
.collect();
806837
all_msgs.sort();
807-
all_msgs.push("\n\n\n\nStats:\n".into());
838+
all_msgs.push("\n\n### Stats:\n\n".into());
808839
all_msgs.push(stats_formatted);
809840

810841
// save the text into lintcheck-logs/logs.txt
811842
let mut text = clippy_ver; // clippy version number on top
812-
text.push_str(&format!("\n{}", all_msgs.join("")));
813-
text.push_str("ICEs:\n");
843+
text.push_str("\n### Reports\n\n");
844+
if config.markdown {
845+
text.push_str("| file | lint | message |\n");
846+
text.push_str("| --- | --- | --- |\n");
847+
}
848+
text.push_str(&format!("{}", all_msgs.join("")));
849+
text.push_str("\n\n### ICEs:\n");
814850
ices.iter()
815851
.for_each(|(cratename, msg)| text.push_str(&format!("{}: '{}'", cratename, msg)));
816852

@@ -832,20 +868,21 @@ fn read_stats_from_file(file_path: &Path) -> HashMap<String, usize> {
832868

833869
let lines: Vec<String> = file_content.lines().map(ToString::to_string).collect();
834870

835-
// search for the beginning "Stats:" and the end "ICEs:" of the section we want
836-
let start = lines.iter().position(|line| line == "Stats:").unwrap();
837-
let end = lines.iter().position(|line| line == "ICEs:").unwrap();
838-
839-
let stats_lines = &lines[start + 1..end];
840-
841-
stats_lines
871+
lines
842872
.iter()
843-
.map(|line| {
844-
let mut spl = line.split(' ');
845-
(
846-
spl.next().unwrap().to_string(),
847-
spl.next().unwrap().parse::<usize>().unwrap(),
848-
)
873+
.skip_while(|line| line.as_str() != "### Stats:")
874+
// Skipping the table header and the `Stats:` label
875+
.skip(4)
876+
.take_while(|line| line.starts_with("| "))
877+
.filter_map(|line| {
878+
let mut spl = line.split('|');
879+
// Skip the first `|` symbol
880+
spl.next();
881+
if let (Some(lint), Some(count)) = (spl.next(), spl.next()) {
882+
Some((lint.trim().to_string(), count.trim().parse::<usize>().unwrap()))
883+
} else {
884+
None
885+
}
849886
})
850887
.collect::<HashMap<String, usize>>()
851888
}
@@ -957,6 +994,11 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
957994
.value_name("clippy_lint_name")
958995
.help("apply a filter to only collect specified lints, this also overrides `allow` attributes"),
959996
)
997+
.arg(
998+
Arg::with_name("markdown")
999+
.long("--markdown")
1000+
.help("change the reports table to use markdown links"),
1001+
)
9601002
.get_matches()
9611003
}
9621004

0 commit comments

Comments
 (0)