diff --git a/src/console.rs b/src/console.rs index 76e5e8d2..c6d6c1c0 100644 --- a/src/console.rs +++ b/src/console.rs @@ -630,8 +630,8 @@ fn style_mb(bytes: u64) -> StyledObject { pub fn style_scenario(scenario: &Scenario, line_col: bool) -> Cow<'static, str> { match scenario { - Scenario::Baseline => "Unmutated baseline".into(), - Scenario::Mutant(mutant) => mutant.name(line_col, true).into(), + Scenario::Baseline => Cow::Borrowed("Unmutated baseline"), + Scenario::Mutant(mutant) => Cow::Owned(mutant.to_styled_string(line_col)), } } diff --git a/src/in_diff.rs b/src/in_diff.rs index 488d1f90..ab9a30e7 100644 --- a/src/in_diff.rs +++ b/src/in_diff.rs @@ -66,7 +66,7 @@ pub fn diff_filter(mutants: Vec, diff_text: &str) -> Result> trace!( ?path, line, - mutant = mutant.name(true, false), + mutant = mutant.name(true), "diff matched mutant" ); matched.push(mutant); diff --git a/src/lab.rs b/src/lab.rs index 66957461..cd487a3e 100644 --- a/src/lab.rs +++ b/src/lab.rs @@ -236,7 +236,7 @@ impl Worker<'_> { let Some(mutant) = work_queue.lock().expect("Lock pending work queue").next() else { return Ok(()); }; - let _span = debug_span!("mutant", name = mutant.name(false, false)).entered(); + let _span = debug_span!("mutant", name = mutant.name(false)).entered(); let test_package = match &self.options.test_package { TestPackages::Workspace => PackageSelection::All, TestPackages::Mutated => { diff --git a/src/list.rs b/src/list.rs index f1ad3bbb..6cecf3b3 100644 --- a/src/list.rs +++ b/src/list.rs @@ -39,7 +39,11 @@ pub fn list_mutants(mutants: &[Mutant], options: &Options) -> String { // TODO: Use with_capacity when we can have mutants skip it (#315 let mut out = String::new(); for mutant in mutants { - out.push_str(&mutant.name(options.show_line_col, colors)); + if colors { + out.push_str(&mutant.to_styled_string(options.show_line_col)); + } else { + out.push_str(&mutant.name(options.show_line_col)); + } out.push('\n'); if options.emit_diffs { out.push_str(&mutant.diff(&mutant.mutated_code())); diff --git a/src/mutate.rs b/src/mutate.rs index d07074e2..8a142e9d 100644 --- a/src/mutate.rs +++ b/src/mutate.rs @@ -88,7 +88,28 @@ impl Mutant { .join("") } - pub fn name(&self, show_line_col: bool, styled: bool) -> String { + pub fn name(&self, show_line_col: bool) -> String { + let mut v = Vec::new(); + v.push(self.source_file.tree_relative_slashes()); + if show_line_col { + v.push(format!( + ":{}:{}: ", + self.span.start.line, self.span.start.column + )); + } else { + v.push(": ".to_owned()); + } + v.extend( + self.styled_parts() + .into_iter() + .map(|x| x.force_styling(false).to_string()), + ); + v.join("") + } + + /// Return a one-line description of this mutant, with coloring, including the file names + /// and optionally the line and column. + pub fn to_styled_string(&self, show_line_col: bool) -> String { let mut v = Vec::new(); v.push(self.source_file.tree_relative_slashes()); if show_line_col { @@ -98,16 +119,7 @@ impl Mutant { )); } v.push(": ".to_owned()); - let parts = self.styled_parts(); - if styled { - v.extend(parts.into_iter().map(|x| x.to_string())); - } else { - v.extend( - parts - .into_iter() - .map(|x| x.force_styling(false).to_string()), - ); - } + v.extend(self.styled_parts().into_iter().map(|x| x.to_string())); v.join("") } @@ -270,7 +282,7 @@ mod test { } ); assert_eq!( - mutants[0].name(true, false), + mutants[0].name(true), "src/bin/factorial.rs:2:5: replace main with ()" ); assert_eq!( @@ -292,15 +304,15 @@ mod test { } ); assert_eq!( - mutants[1].name(false, false), + mutants[1].name(false), "src/bin/factorial.rs: replace factorial -> u32 with 0" ); assert_eq!( - mutants[1].name(true, false), + mutants[1].name(true), "src/bin/factorial.rs:8:5: replace factorial -> u32 with 0" ); assert_eq!( - mutants[2].name(true, false), + mutants[2].name(true), "src/bin/factorial.rs:8:5: replace factorial -> u32 with 1" ); } diff --git a/src/output.rs b/src/output.rs index ce289782..901fe506 100644 --- a/src/output.rs +++ b/src/output.rs @@ -220,7 +220,7 @@ impl OutputDir { SummaryOutcome::Unviable => &mut self.unviable_list, _ => return Ok(()), }; - writeln!(file, "{}", mutant.name(true, false)).context("write to list file")?; + writeln!(file, "{}", mutant.name(true)).context("write to list file")?; } Ok(()) } diff --git a/src/scenario.rs b/src/scenario.rs index ea616d91..fa832adc 100644 --- a/src/scenario.rs +++ b/src/scenario.rs @@ -18,7 +18,7 @@ impl fmt::Display for Scenario { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Scenario::Baseline => f.write_str("baseline"), - Scenario::Mutant(mutant) => f.write_str(&mutant.name(true, false)), + Scenario::Mutant(mutant) => f.write_str(&mutant.name(true)), } } } diff --git a/src/visit.rs b/src/visit.rs index 4f463e37..ce4f7039 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -38,7 +38,7 @@ pub struct Discovered { impl Discovered { pub(crate) fn remove_previously_caught(&mut self, previously_caught: &[String]) { self.mutants.retain(|m| { - let name = m.name(true, false); + let name = m.name(true); let c = previously_caught.contains(&name); if c { trace!(?name, "skip previously caught mutant"); @@ -102,7 +102,7 @@ pub fn walk_tree( files.push(source_file); } mutants.retain(|m| { - let name = m.name(true, false); + let name = m.name(true); (options.examine_names.is_empty() || options.examine_names.is_match(&name)) && (options.exclude_names.is_empty() || !options.exclude_names.is_match(&name)) }); @@ -744,7 +744,7 @@ mod test { is_top: true, }; let (mutants, _files) = walk_file(&source_file, &[]).expect("walk_file"); - let mutant_names = mutants.iter().map(|m| m.name(false, false)).collect_vec(); + let mutant_names = mutants.iter().map(|m| m.name(false)).collect_vec(); // It would be good to suggest replacing this with 'false', breaking a key behavior, // but bad to replace it with 'true', changing nothing. assert_eq!(