Improve performance of statistics (#3751)

This commit is contained in:
Jonathan Plasse 2023-03-27 00:46:44 +02:00 committed by GitHub
parent 6ed6da3e82
commit 2326335f5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -63,10 +63,10 @@ struct ExpandedMessage<'a> {
} }
#[derive(Serialize)] #[derive(Serialize)]
struct ExpandedStatistics { struct ExpandedStatistics<'a> {
code: SerializeRuleAsCode,
message: &'a str,
count: usize, count: usize,
code: String,
message: String,
fixable: bool, fixable: bool,
} }
@ -81,6 +81,12 @@ impl Serialize for SerializeRuleAsCode {
} }
} }
impl Display for SerializeRuleAsCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.noqa_code())
}
}
impl From<Rule> for SerializeRuleAsCode { impl From<Rule> for SerializeRuleAsCode {
fn from(rule: Rule) -> Self { fn from(rule: Rule) -> Self {
Self(rule) Self(rule)
@ -472,41 +478,40 @@ impl Printer {
} }
pub fn write_statistics(&self, diagnostics: &Diagnostics) -> Result<()> { pub fn write_statistics(&self, diagnostics: &Diagnostics) -> Result<()> {
let violations: Vec<Rule> = diagnostics let statistics: Vec<ExpandedStatistics> = diagnostics
.messages .messages
.iter() .iter()
.map(|message| message.kind.rule()) .map(|message| {
(
message.kind.rule(),
&message.kind.body,
message.kind.fixable,
)
})
.sorted() .sorted()
.dedup() .fold(vec![], |mut acc, (rule, body, fixable)| {
.collect(); if let Some((prev_rule, _, _, count)) = acc.last_mut() {
if violations.is_empty() { if *prev_rule == rule {
return Ok(()); *count += 1;
return acc;
} }
}
let statistics = violations acc.push((rule, body, fixable, 1));
acc
})
.iter() .iter()
.map(|rule| ExpandedStatistics { .map(|(rule, message, fixable, count)| ExpandedStatistics {
code: rule.noqa_code().to_string(), code: (*rule).into(),
count: diagnostics count: *count,
.messages message,
.iter() fixable: *fixable,
.filter(|message| message.kind.rule() == *rule)
.count(),
message: diagnostics
.messages
.iter()
.find(|message| message.kind.rule() == *rule)
.map(|message| message.kind.body.clone())
.unwrap(),
fixable: diagnostics
.messages
.iter()
.find(|message| message.kind.rule() == *rule)
.iter()
.any(|message| message.kind.fixable),
}) })
.sorted_by_key(|statistic| Reverse(statistic.count)) .sorted_by_key(|statistic| Reverse(statistic.count))
.collect::<Vec<_>>(); .collect();
if statistics.is_empty() {
return Ok(());
}
let mut stdout = BufWriter::new(io::stdout().lock()); let mut stdout = BufWriter::new(io::stdout().lock());
match self.format { match self.format {
@ -522,7 +527,7 @@ impl Printer {
); );
let code_width = statistics let code_width = statistics
.iter() .iter()
.map(|statistic| statistic.code.len()) .map(|statistic| statistic.code.to_string().len())
.max() .max()
.unwrap(); .unwrap();
let any_fixable = statistics.iter().any(|statistic| statistic.fixable); let any_fixable = statistics.iter().any(|statistic| statistic.fixable);
@ -536,7 +541,7 @@ impl Printer {
stdout, stdout,
"{:>count_width$}\t{:<code_width$}\t{}{}", "{:>count_width$}\t{:<code_width$}\t{}{}",
statistic.count.to_string().bold(), statistic.count.to_string().bold(),
statistic.code.red().bold(), statistic.code.to_string().red().bold(),
if any_fixable { if any_fixable {
if statistic.fixable { if statistic.fixable {
&fixable &fixable