From 247672da59656aae806007abd3aa1a9b4c3f7198 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 29 Nov 2023 21:49:54 -0800 Subject: [PATCH 1/2] Show the right context for mutants in trait default fns --- src/mutate.rs | 30 +++---- ..._expected_mutants_for_own_source_tree.snap | 3 +- src/visit.rs | 25 ++++++ testdata/well_tested/src/lib.rs | 1 + testdata/well_tested/src/traits.rs | 22 +++++ tests/cli/config.rs | 1 + tests/cli/main.rs | 4 +- .../cli__list_files_json_well_tested.snap | 4 + .../cli__list_files_text_well_tested.snap | 1 + ...li__list_mutants_in_all_trees_as_json.snap | 90 +++++++++++++++++++ ...li__list_mutants_in_all_trees_as_text.snap | 5 +- .../cli__list_mutants_json_well_tested.snap | 90 +++++++++++++++++++ .../cli__list_mutants_well_tested.snap | 5 +- ...tants_well_tested_exclude_name_filter.snap | 5 +- .../cli__well_tested_tree_check_only.snap | 9 +- ...i__well_tested_tree_finds_no_problems.snap | 9 +- ...ed_tree_finds_no_problems__caught.txt.snap | 5 +- .../cli__well_tested_tree_quiet.snap | 4 +- 18 files changed, 283 insertions(+), 30 deletions(-) create mode 100644 testdata/well_tested/src/traits.rs diff --git a/src/mutate.rs b/src/mutate.rs index 822114bc..2921f178 100644 --- a/src/mutate.rs +++ b/src/mutate.rs @@ -118,26 +118,26 @@ impl Mutant { } let mut v: Vec> = Vec::new(); v.push(s("replace ")); - if self.genre != Genre::FnValue { + if self.genre == Genre::FnValue { + let function = self + .function + .as_ref() + .expect("FnValue mutant should have a function"); + v.push(s(&function.function_name).bright().magenta()); + if !function.return_type.is_empty() { + v.push(s(" ")); + v.push(s(&function.return_type).magenta()); + } + v.push(s(" with ")); + v.push(s(self.replacement_text()).yellow()); + } else { v.push(s(self.original_text()).yellow()); v.push(s(" with ")); v.push(s(&self.replacement).bright().yellow()); - v.push(s(" in ")); - } - if let Some(function) = &self.function { - v.push(s(&function.function_name).bright().magenta()); - } else { - v.push(s("module")); - } - if self.genre == Genre::FnValue { if let Some(function) = &self.function { - if !function.return_type.is_empty() { - v.push(s(" ")); - v.push(s(&function.return_type).magenta()); - } + v.push(s(" in ")); + v.push(s(&function.function_name).bright().magenta()); } - v.push(s(" with ")); - v.push(s(self.replacement_text()).yellow()); } v } diff --git a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap index f09656c5..259b41f7 100644 --- a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap +++ b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap @@ -230,7 +230,6 @@ src/mutate.rs: replace Mutant::styled_parts::s -> StyledObject with Styl src/mutate.rs: replace Mutant::styled_parts::s -> StyledObject with StyledObject::from_iter(["xyzzy".into()]) src/mutate.rs: replace Mutant::styled_parts::s -> StyledObject with StyledObject::new("xyzzy".into()) src/mutate.rs: replace Mutant::styled_parts::s -> StyledObject with StyledObject::from("xyzzy".into()) -src/mutate.rs: replace != with == in Mutant::styled_parts src/mutate.rs: replace == with != in Mutant::styled_parts src/mutate.rs: replace Mutant::original_text -> String with String::new() src/mutate.rs: replace Mutant::original_text -> String with "xyzzy".into() @@ -401,6 +400,8 @@ src/visit.rs: replace DiscoveryVisitor<'o>::in_namespace -> T with Default::defa src/visit.rs: replace >::visit_item_fn with () src/visit.rs: replace >::visit_impl_item_fn with () src/visit.rs: replace == with != in >::visit_impl_item_fn +src/visit.rs: replace >::visit_trait_item_fn with () +src/visit.rs: replace == with != in >::visit_trait_item_fn src/visit.rs: replace >::visit_item_impl with () src/visit.rs: replace == with != in >::visit_item_impl src/visit.rs: replace >::visit_item_mod with () diff --git a/src/visit.rs b/src/visit.rs index b03153d5..2da80681 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -226,6 +226,7 @@ impl<'ast> Visit<'ast> for DiscoveryVisitor<'_> { name = function_name ) .entered(); + trace!("visit fn"); if fn_sig_excluded(&i.sig) || attrs_excluded(&i.attrs) || block_is_empty(&i.block) { return; } @@ -259,6 +260,29 @@ impl<'ast> Visit<'ast> for DiscoveryVisitor<'_> { self.leave_function(function); } + /// Visit `fn foo() { ... }` within a trait, i.e. a default implementation of a function. + fn visit_trait_item_fn(&mut self, i: &'ast syn::TraitItemFn) { + let function_name = i.sig.ident.to_pretty_string(); + let _span = trace_span!( + "fn", + line = i.sig.fn_token.span.start().line, + name = function_name + ) + .entered(); + if fn_sig_excluded(&i.sig) || attrs_excluded(&i.attrs) || i.sig.ident == "new" { + return; + } + if let Some(block) = &i.default { + if block_is_empty(block) { + return; + } + let function = self.enter_function(&i.sig.ident, &i.sig.output, i.span()); + self.collect_fn_mutants(&i.sig, block); + syn::visit::visit_trait_item_fn(self, i); + self.leave_function(function); + } + } + /// Visit `impl Foo { ...}` or `impl Debug for Foo { ... }`. fn visit_item_impl(&mut self, i: &'ast syn::ItemImpl) { if attrs_excluded(&i.attrs) { @@ -298,6 +322,7 @@ impl<'ast> Visit<'ast> for DiscoveryVisitor<'_> { /// Visit `a op b` expressions. fn visit_expr_binary(&mut self, i: &'ast syn::ExprBinary) { let _span = trace_span!("binary", line = i.op.span().start().line).entered(); + trace!("visit binary operator"); if attrs_excluded(&i.attrs) { return; } diff --git a/testdata/well_tested/src/lib.rs b/testdata/well_tested/src/lib.rs index fdda45b8..7c7263d3 100644 --- a/testdata/well_tested/src/lib.rs +++ b/testdata/well_tested/src/lib.rs @@ -21,3 +21,4 @@ pub mod simple_fns; mod slices; mod static_item; mod struct_with_lifetime; +mod traits; diff --git a/testdata/well_tested/src/traits.rs b/testdata/well_tested/src/traits.rs new file mode 100644 index 00000000..aba1320c --- /dev/null +++ b/testdata/well_tested/src/traits.rs @@ -0,0 +1,22 @@ +//! Test mutation of a default fn in a trait. + +trait Something { + fn is_three(&self, a: usize) -> bool { + a == 3 + } +} + +#[cfg(test)] +mod test { + use super::*; + + struct Three; + + impl Something for Three {} + + #[test] + fn test_is_three() { + assert!(Three.is_three(3)); + assert!(!Three.is_three(4)); + } +} diff --git a/tests/cli/config.rs b/tests/cli/config.rs index 0461cec6..9feb6d95 100644 --- a/tests/cli/config.rs +++ b/tests/cli/config.rs @@ -148,6 +148,7 @@ fn exclude_file_argument_overrides_config() { src/empty_fns.rs src/methods.rs src/result.rs + src/traits.rs " })); } diff --git a/tests/cli/main.rs b/tests/cli/main.rs index 009bc616..2960290b 100644 --- a/tests/cli/main.rs +++ b/tests/cli/main.rs @@ -568,8 +568,8 @@ fn well_tested_tree_quiet() { fs::read_to_string(tmp_src_dir.path().join("mutants.out/outcomes.json")).unwrap(); println!("outcomes.json:\n{outcomes_json}"); let outcomes: serde_json::Value = outcomes_json.parse().unwrap(); - assert_eq!(outcomes["total_mutants"], 43); - assert_eq!(outcomes["caught"], 43); + assert_eq!(outcomes["total_mutants"], 46); + assert_eq!(outcomes["caught"], 46); assert_eq!(outcomes["unviable"], 0); assert_eq!(outcomes["missed"], 0); } diff --git a/tests/cli/snapshots/cli__list_files_json_well_tested.snap b/tests/cli/snapshots/cli__list_files_json_well_tested.snap index bc033b4e..33fde586 100644 --- a/tests/cli/snapshots/cli__list_files_json_well_tested.snap +++ b/tests/cli/snapshots/cli__list_files_json_well_tested.snap @@ -58,6 +58,10 @@ expression: "String::from_utf8_lossy(&output.stdout)" { "package": "cargo-mutants-testdata-well-tested", "path": "src/struct_with_lifetime.rs" + }, + { + "package": "cargo-mutants-testdata-well-tested", + "path": "src/traits.rs" } ] diff --git a/tests/cli/snapshots/cli__list_files_text_well_tested.snap b/tests/cli/snapshots/cli__list_files_text_well_tested.snap index a17c9e27..5ed340d0 100644 --- a/tests/cli/snapshots/cli__list_files_text_well_tested.snap +++ b/tests/cli/snapshots/cli__list_files_text_well_tested.snap @@ -16,4 +16,5 @@ src/simple_fns.rs src/slices.rs src/static_item.rs src/struct_with_lifetime.rs +src/traits.rs diff --git a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap index 0b5688df..5a64b323 100644 --- a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap +++ b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap @@ -3789,6 +3789,96 @@ expression: buf "line": 15 } } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "FnValue", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "true", + "span": { + "end": { + "column": 15, + "line": 5 + }, + "start": { + "column": 9, + "line": 5 + } + } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "FnValue", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "false", + "span": { + "end": { + "column": 15, + "line": 5 + }, + "start": { + "column": 9, + "line": 5 + } + } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "BinaryOperator", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "!=", + "span": { + "end": { + "column": 13, + "line": 5 + }, + "start": { + "column": 11, + "line": 5 + } + } } ] ``` diff --git a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap index 9151d57d..c8d4e2d0 100644 --- a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap +++ b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap @@ -286,9 +286,12 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) -src/static_item.rs:1:33: replace == with != in module +src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 +src/traits.rs:5:9: replace is_three -> bool with true +src/traits.rs:5:9: replace is_three -> bool with false +src/traits.rs:5:11: replace == with != in is_three ``` ## testdata/with_child_directories diff --git a/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap b/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap index 756728f7..b90ab5bb 100644 --- a/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap +++ b/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap @@ -1279,5 +1279,95 @@ expression: "String::from_utf8_lossy(&output.stdout)" "line": 15 } } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "FnValue", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "true", + "span": { + "end": { + "column": 15, + "line": 5 + }, + "start": { + "column": 9, + "line": 5 + } + } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "FnValue", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "false", + "span": { + "end": { + "column": 15, + "line": 5 + }, + "start": { + "column": 9, + "line": 5 + } + } + }, + { + "file": "src/traits.rs", + "function": { + "function_name": "is_three", + "return_type": "-> bool", + "span": { + "end": { + "column": 6, + "line": 6 + }, + "start": { + "column": 5, + "line": 4 + } + } + }, + "genre": "BinaryOperator", + "package": "cargo-mutants-testdata-well-tested", + "replacement": "!=", + "span": { + "end": { + "column": 13, + "line": 5 + }, + "start": { + "column": 11, + "line": 5 + } + } } ] diff --git a/tests/cli/snapshots/cli__list_mutants_well_tested.snap b/tests/cli/snapshots/cli__list_mutants_well_tested.snap index 1ba6b749..8ead7dca 100644 --- a/tests/cli/snapshots/cli__list_mutants_well_tested.snap +++ b/tests/cli/snapshots/cli__list_mutants_well_tested.snap @@ -42,7 +42,10 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) -src/static_item.rs:1:33: replace == with != in module +src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 +src/traits.rs:5:9: replace is_three -> bool with true +src/traits.rs:5:9: replace is_three -> bool with false +src/traits.rs:5:11: replace == with != in is_three diff --git a/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap b/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap index 42bb65ec..d5cdc5b5 100644 --- a/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap +++ b/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap @@ -34,7 +34,10 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) -src/static_item.rs:1:33: replace == with != in module +src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 +src/traits.rs:5:9: replace is_three -> bool with true +src/traits.rs:5:9: replace is_three -> bool with false +src/traits.rs:5:11: replace == with != in is_three diff --git a/tests/cli/snapshots/cli__well_tested_tree_check_only.snap b/tests/cli/snapshots/cli__well_tested_tree_check_only.snap index 396d9edc..b75271f8 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_check_only.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_check_only.snap @@ -2,7 +2,7 @@ source: tests/cli/main.rs expression: stdout --- -Found 43 mutants to test +Found 46 mutants to test Unmutated baseline ... ok src/arc.rs:4:5: replace return_arc -> Arc with Arc::new(String::new()) ... ok src/arc.rs:4:5: replace return_arc -> Arc with Arc::new("xyzzy".into()) ... ok @@ -44,8 +44,11 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) ... ok src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) ... ok src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) ... ok -src/static_item.rs:1:33: replace == with != in module ... ok +src/static_item.rs:1:33: replace == with != ... ok src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 ... ok src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 ... ok -43 mutants tested: 43 succeeded +src/traits.rs:5:9: replace is_three -> bool with true ... ok +src/traits.rs:5:9: replace is_three -> bool with false ... ok +src/traits.rs:5:11: replace == with != in is_three ... ok +46 mutants tested: 46 succeeded diff --git a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap index 378a58eb..a3dddd2f 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap @@ -2,7 +2,7 @@ source: tests/cli/main.rs expression: stdout --- -Found 43 mutants to test +Found 46 mutants to test Unmutated baseline ... ok src/arc.rs:4:5: replace return_arc -> Arc with Arc::new(String::new()) ... caught src/arc.rs:4:5: replace return_arc -> Arc with Arc::new("xyzzy".into()) ... caught @@ -44,8 +44,11 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) ... caught src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) ... caught src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) ... caught -src/static_item.rs:1:33: replace == with != in module ... caught +src/static_item.rs:1:33: replace == with != ... caught src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 ... caught src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 ... caught -43 mutants tested: 43 caught +src/traits.rs:5:9: replace is_three -> bool with true ... caught +src/traits.rs:5:9: replace is_three -> bool with false ... caught +src/traits.rs:5:11: replace == with != in is_three ... caught +46 mutants tested: 46 caught diff --git a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap index e5bbcbd0..d7ab8740 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap @@ -42,7 +42,10 @@ src/slices.rs:4:5: replace pad -> &'a[Cow<'static, str>] with Vec::leak(vec![Cow src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(Vec::new()) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![0]) src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![1]) -src/static_item.rs:1:33: replace == with != in module +src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 +src/traits.rs:5:9: replace is_three -> bool with true +src/traits.rs:5:9: replace is_three -> bool with false +src/traits.rs:5:11: replace == with != in is_three diff --git a/tests/cli/snapshots/cli__well_tested_tree_quiet.snap b/tests/cli/snapshots/cli__well_tested_tree_quiet.snap index ee0e4373..894422b0 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_quiet.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_quiet.snap @@ -2,7 +2,7 @@ source: tests/cli/main.rs expression: stdout --- -Found 43 mutants to test +Found 46 mutants to test Unmutated baseline ... ok -43 mutants tested: 43 caught +46 mutants tested: 46 caught From acaf51760d2367bdcddee93b336e4663e975de38 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 29 Nov 2023 21:57:00 -0800 Subject: [PATCH 2/2] Include trait names in namespace stack --- ...it__test__expected_mutants_for_own_source_tree.snap | 1 + src/visit.rs | 10 ++++++++++ .../cli__list_mutants_in_all_trees_as_json.snap | 6 +++--- .../cli__list_mutants_in_all_trees_as_text.snap | 6 +++--- .../snapshots/cli__list_mutants_json_well_tested.snap | 6 +++--- tests/cli/snapshots/cli__list_mutants_well_tested.snap | 6 +++--- ...__list_mutants_well_tested_exclude_name_filter.snap | 6 +++--- .../snapshots/cli__well_tested_tree_check_only.snap | 6 +++--- .../cli__well_tested_tree_finds_no_problems.snap | 6 +++--- ...well_tested_tree_finds_no_problems__caught.txt.snap | 6 +++--- 10 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap index 259b41f7..f8cdab09 100644 --- a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap +++ b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap @@ -404,6 +404,7 @@ src/visit.rs: replace >::visit_trait_item_fn src/visit.rs: replace == with != in >::visit_trait_item_fn src/visit.rs: replace >::visit_item_impl with () src/visit.rs: replace == with != in >::visit_item_impl +src/visit.rs: replace >::visit_item_trait with () src/visit.rs: replace >::visit_item_mod with () src/visit.rs: replace >::visit_expr_binary with () src/visit.rs: replace function_body_span -> Option with None diff --git a/src/visit.rs b/src/visit.rs index 2da80681..9f9de2f6 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -302,6 +302,16 @@ impl<'ast> Visit<'ast> for DiscoveryVisitor<'_> { self.in_namespace(&name, |v| syn::visit::visit_item_impl(v, i)); } + /// Visit `trait Foo { ... }` + fn visit_item_trait(&mut self, i: &'ast syn::ItemTrait) { + let name = i.ident.to_pretty_string(); + let _span = trace_span!("trait", line = i.span().start().line, name).entered(); + if attrs_excluded(&i.attrs) { + return; + } + self.in_namespace(&name, |v| syn::visit::visit_item_trait(v, i)); + } + /// Visit `mod foo { ... }` or `mod foo;`. fn visit_item_mod(&mut self, node: &'ast syn::ItemMod) { let mod_name = &node.ident.unraw().to_string(); diff --git a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap index 5a64b323..b2bec39a 100644 --- a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap +++ b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_json.snap @@ -3793,7 +3793,7 @@ expression: buf { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { @@ -3823,7 +3823,7 @@ expression: buf { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { @@ -3853,7 +3853,7 @@ expression: buf { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { diff --git a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap index c8d4e2d0..9f702a2b 100644 --- a/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap +++ b/tests/cli/snapshots/cli__list_mutants_in_all_trees_as_text.snap @@ -289,9 +289,9 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 -src/traits.rs:5:9: replace is_three -> bool with true -src/traits.rs:5:9: replace is_three -> bool with false -src/traits.rs:5:11: replace == with != in is_three +src/traits.rs:5:9: replace Something::is_three -> bool with true +src/traits.rs:5:9: replace Something::is_three -> bool with false +src/traits.rs:5:11: replace == with != in Something::is_three ``` ## testdata/with_child_directories diff --git a/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap b/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap index b90ab5bb..34ef16c4 100644 --- a/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap +++ b/tests/cli/snapshots/cli__list_mutants_json_well_tested.snap @@ -1283,7 +1283,7 @@ expression: "String::from_utf8_lossy(&output.stdout)" { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { @@ -1313,7 +1313,7 @@ expression: "String::from_utf8_lossy(&output.stdout)" { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { @@ -1343,7 +1343,7 @@ expression: "String::from_utf8_lossy(&output.stdout)" { "file": "src/traits.rs", "function": { - "function_name": "is_three", + "function_name": "Something::is_three", "return_type": "-> bool", "span": { "end": { diff --git a/tests/cli/snapshots/cli__list_mutants_well_tested.snap b/tests/cli/snapshots/cli__list_mutants_well_tested.snap index 8ead7dca..0200e1bb 100644 --- a/tests/cli/snapshots/cli__list_mutants_well_tested.snap +++ b/tests/cli/snapshots/cli__list_mutants_well_tested.snap @@ -45,7 +45,7 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 -src/traits.rs:5:9: replace is_three -> bool with true -src/traits.rs:5:9: replace is_three -> bool with false -src/traits.rs:5:11: replace == with != in is_three +src/traits.rs:5:9: replace Something::is_three -> bool with true +src/traits.rs:5:9: replace Something::is_three -> bool with false +src/traits.rs:5:11: replace == with != in Something::is_three diff --git a/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap b/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap index d5cdc5b5..80e3e42e 100644 --- a/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap +++ b/tests/cli/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap @@ -37,7 +37,7 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 -src/traits.rs:5:9: replace is_three -> bool with true -src/traits.rs:5:9: replace is_three -> bool with false -src/traits.rs:5:11: replace == with != in is_three +src/traits.rs:5:9: replace Something::is_three -> bool with true +src/traits.rs:5:9: replace Something::is_three -> bool with false +src/traits.rs:5:11: replace == with != in Something::is_three diff --git a/tests/cli/snapshots/cli__well_tested_tree_check_only.snap b/tests/cli/snapshots/cli__well_tested_tree_check_only.snap index b75271f8..0ce7d6a7 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_check_only.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_check_only.snap @@ -47,8 +47,8 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != ... ok src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 ... ok src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 ... ok -src/traits.rs:5:9: replace is_three -> bool with true ... ok -src/traits.rs:5:9: replace is_three -> bool with false ... ok -src/traits.rs:5:11: replace == with != in is_three ... ok +src/traits.rs:5:9: replace Something::is_three -> bool with true ... ok +src/traits.rs:5:9: replace Something::is_three -> bool with false ... ok +src/traits.rs:5:11: replace == with != in Something::is_three ... ok 46 mutants tested: 46 succeeded diff --git a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap index a3dddd2f..5b665d13 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems.snap @@ -47,8 +47,8 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != ... caught src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 ... caught src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 ... caught -src/traits.rs:5:9: replace is_three -> bool with true ... caught -src/traits.rs:5:9: replace is_three -> bool with false ... caught -src/traits.rs:5:11: replace == with != in is_three ... caught +src/traits.rs:5:9: replace Something::is_three -> bool with true ... caught +src/traits.rs:5:9: replace Something::is_three -> bool with false ... caught +src/traits.rs:5:11: replace == with != in Something::is_three ... caught 46 mutants tested: 46 caught diff --git a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap index d7ab8740..daf8bf38 100644 --- a/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap +++ b/tests/cli/snapshots/cli__well_tested_tree_finds_no_problems__caught.txt.snap @@ -45,7 +45,7 @@ src/slices.rs:13:5: replace return_mut_slice -> &mut[usize] with Vec::leak(vec![ src/static_item.rs:1:33: replace == with != src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 0 src/struct_with_lifetime.rs:15:9: replace Lex<'buf>::buf_len -> usize with 1 -src/traits.rs:5:9: replace is_three -> bool with true -src/traits.rs:5:9: replace is_three -> bool with false -src/traits.rs:5:11: replace == with != in is_three +src/traits.rs:5:9: replace Something::is_three -> bool with true +src/traits.rs:5:9: replace Something::is_three -> bool with false +src/traits.rs:5:11: replace == with != in Something::is_three