Repository: sourcefrog/cargo-mutants (rust)

Issue:
Exclude specified paths from mutants generation
I believe that it would be handy to exclude specified paths from the mutants generation.

Let's say that I want to exclude things like configuration logic or some test helper logic files, located within the `src` directory. Right now the default behaviour of `cargo mutants` command is that it tries to generate mutants for every file in the `src`  directory and in their child directories.

I could envision having a command line parameter as follows:

```
cargo mutants --exclude <regexes-for-paths-to-be-excluded>
```


## Use case scenario:

### Prerequisite:
Git clone [test repo](https://github.com/dmoka/test-repo-for-cargo-mutants.git)

### Steps:
1. Go to the main directory of the cloned repo
2. Execute the following command
```
cargo mutants --exclude "(\/src\/tests)" "(\/src\/config)"
```

### Expected behaviour:
Every file which is located in either `/src/tests` or `/src/config` directories are excluded from mutants generation.

### Actual behaviour:
Because of the default behaviour of `cargo-mutants` (and due to the non-existency of this command line parameter) there are mutants generated for the files both in `/src/tests` and `/src/config`



Pull request description:
Feat: add exclude files option
## Description
Added new CLI optional parameter `--exclude` to exclude files and paths, according to [issue](https://github.com/sourcefrog/cargo-mutants/issues/58).

Inspired by the `--file` parameter.

Fixes #58 

## Note
I was not able to debug any of the CLI tests, I wonder if it is normal or if something is off on my machine. 
- Because if it is normal, then maybe we could come up with a better debuggable testing strategy, of course if it is possible in an ergonomic way. It felt quite cumbersome to place print statements everywhere to debug my code when executing CLI tests
- If something needs to be configured to make those tests debuggable, then I feel that we should document it

Let me know what you think about this.

Anyway, it was a great fun to work with the codebase, especially liked this snapshot testing!

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 2d7fbe4..d7b95ba 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -233,6 +233,13 @@ dependencies = [
  "mutants 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "cargo-mutants-testdata-with-child-directories"
+version = "0.1.0"
+dependencies = [
+ "mutants 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "cargo-platform"
 version = "0.1.2"
diff --git a/Cargo.toml b/Cargo.toml
index 0bd515b..ffb7251 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -78,6 +78,7 @@ members = [
     "testdata/tree/small_well_tested",
     "testdata/tree/strict_warnings",
     "testdata/tree/well_tested",
+    "testdata/tree/with_child_directories",
 ]
 
 # `replace_dependency` can't be in the workspace, because 'replace' sections
diff --git a/NEWS.md b/NEWS.md
index 2b7c1d1..b30c73f 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,8 @@
 # cargo-mutants changelog
 
-## Unreleased
+## 0.2.11 UNRELEASED
+
+- New `--exclude` command line option to exclude source files from mutants generation, matching a glob.
 
 - Added: A new `mutants.out/debug.log` with internal debugging information.
 
diff --git a/README.md b/README.md
index da763ad..e0eff25 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,13 @@ but not adequately tested.
 
 `-f`, `--file FILE`: Mutate only functions in files matching the given name or
 glob. If the glob contains `/` it matches against the path from the source tree
-root; otherwise it matches only against the file name.
+root; otherwise it matches only against the file name. If used together with `--exclude` argument, 
+then the files to be examined are matched before the files to be excluded.
+
+`-e`, `--exclude FILE`: Exclude files from mutants generation, matching the given name or
+glob. If the glob contains `/` it matches against the path from the source tree
+root; otherwise it matches only against the file name. If used together with `--file` argument, 
+then the files to be examined are matched before the files to be excluded.
 
 `--list`: Show what mutants could be generated, without running them.
 
diff --git a/src/main.rs b/src/main.rs
index 0460519..906d125 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -74,10 +74,15 @@ struct Args {
     dir: Utf8PathBuf,
 
     /// glob for files to examine; with no glob, all files are examined; globs containing
-    /// slash match the entire path.
+    /// slash match the entire path. If used together with `--exclude` argument, then the files to be examined are matched before the files to be excluded.
     #[argh(option, short = 'f')]
     file: Vec<String>,
 
+    /// glob for files to exclude; with no glob, all files are included; globs containing
+    /// slash match the entire path. If used together with `--file` argument, then the files to be examined are matched before the files to be excluded.
+    #[argh(option, short = 'e')]
+    exclude: Vec<String>,
+
     /// output json (only for --list).
     #[argh(switch)]
     json: bool,
diff --git a/src/options.rs b/src/options.rs
index 2a6b554..9bd35e9 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -47,7 +47,10 @@ pub struct Options {
     pub build_source: bool,
 
     /// Files to examine.
-    pub globset: Option<GlobSet>,
+    pub examine_globset: Option<GlobSet>,
+
+    /// Files to exclude
+    pub exclude_globset: Option<GlobSet>,
 
     /// Create `mutants.out` within this directory (by default, the source directory).
     pub output_in_dir: Option<Utf8PathBuf>,
@@ -74,19 +77,8 @@ impl TryFrom<&Args> for Options {
     type Error = anyhow::Error;
 
     fn try_from(args: &Args) -> std::result::Result<Options, anyhow::Error> {
-        let globset = if args.file.is_empty() {
-            None
-        } else {
-            let mut builder = GlobSetBuilder::new();
-            for glob_str in &args.file {
-                if glob_str.contains('/') {
-                    builder.add(Glob::new(glob_str)?);
-                } else {
-                    builder.add(Glob::new(&format!("**/{}", glob_str))?);
-                }
-            }
-            Some(builder.build()?)
-        };
+        let examine_globset = build_glob_set(&args.file)?;
+        let exclude_globset = build_glob_set(&args.exclude)?;
 
         Ok(Options {
             additional_cargo_args: args.cargo_arg.clone(),
@@ -94,7 +86,8 @@ impl TryFrom<&Args> for Options {
             build_source: !args.no_copy_target,
             check_only: args.check,
             copy_target: !args.no_copy_target,
-            globset,
+            examine_globset,
+            exclude_globset,
             output_in_dir: args.output.clone(),
             print_caught: args.caught,
             print_unviable: args.unviable,
@@ -108,3 +101,19 @@ impl TryFrom<&Args> for Options {
         })
     }
 }
+
+fn build_glob_set(glob_set: &Vec<String>) -> Result<Option<GlobSet>> {
+    if glob_set.is_empty() {
+        return Ok(None);
+    }
+
+    let mut builder = GlobSetBuilder::new();
+    for glob_str in glob_set {
+        if glob_str.contains('/') || glob_str.contains(std::path::MAIN_SEPARATOR) {
+            builder.add(Glob::new(glob_str)?);
+        } else {
+            builder.add(Glob::new(&format!("**/{}", glob_str))?);
+        }
+    }
+    Ok(Some(builder.build()?))
+}
diff --git a/src/source.rs b/src/source.rs
index f1fe9ca..a54ceab 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -104,7 +104,12 @@ impl SourceTree {
         options: &Options,
     ) -> Result<impl IntoIterator<Item = TreeRelativePathBuf>> {
         let top_sources = cargo_metadata_sources(&self.metadata)?;
-        indirect_sources(&self.root, top_sources, &options.globset)
+        indirect_sources(
+            &self.root,
+            top_sources,
+            &options.examine_globset,
+            &options.exclude_globset,
+        )
     }
 
     /// Return an iterator of [SourceFile] object, eagerly loading their content.
@@ -140,7 +145,8 @@ impl SourceTree {
 fn indirect_sources(
     root_dir: &Utf8Path,
     top_sources: impl IntoIterator<Item = TreeRelativePathBuf>,
-    globset: &Option<GlobSet>,
+    examine_globset: &Option<GlobSet>,
+    exclude_globset: &Option<GlobSet>,
 ) -> Result<BTreeSet<TreeRelativePathBuf>> {
     let dirs: BTreeSet<TreeRelativePathBuf> = top_sources.into_iter().map(|p| p.parent()).collect();
     let mut files: BTreeSet<TreeRelativePathBuf> = BTreeSet::new();
@@ -164,7 +170,16 @@ fn indirect_sources(
                     .expect("strip prefix")
                     .to_owned()
             })
-            .filter(|rel_path| globset.as_ref().map_or(true, |gs| gs.is_match(rel_path)))
+            .filter(|rel_path| {
+                examine_globset
+                    .as_ref()
+                    .map_or(true, |gs| gs.is_match(rel_path))
+            })
+            .filter(|rel_path| {
+                exclude_globset
+                    .as_ref()
+                    .map_or(true, |gs| !gs.is_match(rel_path))
+            })
         {
             files.insert(p.into());
         }


Test patch:
diff --git a/testdata/tree/with_child_directories/Cargo.toml b/testdata/tree/with_child_directories/Cargo.toml
new file mode 100644
index 0000000..ca0a7ff
--- /dev/null
+++ b/testdata/tree/with_child_directories/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "cargo-mutants-testdata-with-child-directories"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+[dependencies.mutants]
+version = "0.0.3"
diff --git a/testdata/tree/with_child_directories/README.md b/testdata/tree/with_child_directories/README.md
new file mode 100644
index 0000000..62839a5
--- /dev/null
+++ b/testdata/tree/with_child_directories/README.md
@@ -0,0 +1,5 @@
+# `with_child_directories`
+
+An example tree for `cargo-mutants` with various subdirectories, to test matching filenames.
+
+All tests should pass and everything should be covered.
diff --git a/testdata/tree/with_child_directories/src/lib.rs b/testdata/tree/with_child_directories/src/lib.rs
new file mode 100644
index 0000000..794ba47
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/lib.rs
@@ -0,0 +1,6 @@
+//! An example tree for `cargo-mutants` with various subdirectories, to test matching filenames.
+
+#![allow(unused, dead_code)]
+
+mod methods;
+mod module;
diff --git a/testdata/tree/with_child_directories/src/methods.rs b/testdata/tree/with_child_directories/src/methods.rs
new file mode 100644
index 0000000..5fc756b
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/methods.rs
@@ -0,0 +1,11 @@
+pub fn double(x: usize) -> usize {
+    x * 2
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn double() {
+        assert_eq!(super::double(2), 4);
+    }
+}
diff --git a/testdata/tree/with_child_directories/src/module/mod.rs b/testdata/tree/with_child_directories/src/module/mod.rs
new file mode 100644
index 0000000..52ab96b
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/mod.rs
@@ -0,0 +1,2 @@
+mod module_methods;
+mod utils;
diff --git a/testdata/tree/with_child_directories/src/module/module_methods.rs b/testdata/tree/with_child_directories/src/module/module_methods.rs
new file mode 100644
index 0000000..5fc756b
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/module_methods.rs
@@ -0,0 +1,11 @@
+pub fn double(x: usize) -> usize {
+    x * 2
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn double() {
+        assert_eq!(super::double(2), 4);
+    }
+}
diff --git a/testdata/tree/with_child_directories/src/module/utils/inside_mod.rs b/testdata/tree/with_child_directories/src/module/utils/inside_mod.rs
new file mode 100644
index 0000000..b7003f8
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/inside_mod.rs
@@ -0,0 +1,12 @@
+mod outer {
+    mod inner {
+        pub fn name() -> &'static str {
+            "Bob"
+        }
+
+        #[test]
+        fn test_name() {
+            assert_eq!(name(), "Bob");
+        }
+    }
+}
diff --git a/testdata/tree/with_child_directories/src/module/utils/inside_utils_empty_fns.rs b/testdata/tree/with_child_directories/src/module/utils/inside_utils_empty_fns.rs
new file mode 100644
index 0000000..d02e7fc
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/inside_utils_empty_fns.rs
@@ -0,0 +1,25 @@
+//! These functions have empty bodies; we cannot usefully mutate them.
+
+fn just_empty() {}
+
+fn only_a_comment() { /* it's still basically empty */
+}
+
+struct Foo();
+
+impl Foo {
+    fn empty_in_foo(&self) { /* also caught */
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn empty_fns_do_nothing() {
+        just_empty();
+        only_a_comment();
+        Foo().empty_in_foo();
+    }
+}
diff --git a/testdata/tree/with_child_directories/src/module/utils/mod.rs b/testdata/tree/with_child_directories/src/module/utils/mod.rs
new file mode 100644
index 0000000..6f055bc
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/mod.rs
@@ -0,0 +1,4 @@
+mod inside_mod;
+mod inside_utils_empty_fns;
+mod nested_function;
+mod sub_utils;
diff --git a/testdata/tree/with_child_directories/src/module/utils/nested_function.rs b/testdata/tree/with_child_directories/src/module/utils/nested_function.rs
new file mode 100644
index 0000000..a25eee4
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/nested_function.rs
@@ -0,0 +1,14 @@
+fn has_nested() -> u32 {
+    fn inner() -> u32 {
+        12
+    }
+    inner() * inner()
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn has_nested() {
+        assert_eq!(super::has_nested(), 144);
+    }
+}
diff --git a/testdata/tree/with_child_directories/src/module/utils/sub_utils/mod.rs b/testdata/tree/with_child_directories/src/module/utils/sub_utils/mod.rs
new file mode 100644
index 0000000..38dd4cf
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/sub_utils/mod.rs
@@ -0,0 +1,1 @@
+mod subutils_nested_function;
diff --git a/testdata/tree/with_child_directories/src/module/utils/sub_utils/subutils_nested_function.rs b/testdata/tree/with_child_directories/src/module/utils/sub_utils/subutils_nested_function.rs
new file mode 100644
index 0000000..a25eee4
--- /dev/null
+++ b/testdata/tree/with_child_directories/src/module/utils/sub_utils/subutils_nested_function.rs
@@ -0,0 +1,14 @@
+fn has_nested() -> u32 {
+    fn inner() -> u32 {
+        12
+    }
+    inner() * inner()
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn has_nested() {
+        assert_eq!(super::has_nested(), 144);
+    }
+}
diff --git a/tests/cli.rs b/tests/cli.rs
index bbd269e..63f5d5e 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -273,12 +273,75 @@ fn list_mutants_well_tested() {
 }
 
 #[test]
-fn list_mutants_well_tested_name_filter() {
+fn list_mutants_well_tested_examine_name_filter() {
     run()
         .arg("mutants")
         .args(["--list", "--file", "nested_function.rs"])
         .current_dir("testdata/tree/well_tested")
-        .assert_insta("list_mutants_well_tested_name_filter");
+        .assert_insta("list_mutants_well_tested_examine_name_filter");
+}
+
+#[test]
+fn list_mutants_well_tested_exclude_name_filter() {
+    run()
+        .arg("mutants")
+        .args(["--list", "--exclude", "simple_fns.rs"])
+        .current_dir("testdata/tree/well_tested")
+        .assert_insta("list_mutants_well_tested_exclude_name_filter");
+}
+
+#[test]
+fn list_mutants_well_tested_exclude_folder_filter() {
+    run()
+        .arg("mutants")
+        .args(["--list", "--exclude", "*/module/*"])
+        .current_dir("testdata/tree/with_child_directories")
+        .assert_insta("list_mutants_well_tested_exclude_folder_filter");
+}
+
+#[test]
+#[cfg(target_os = "windows")]
+fn list_mutants_well_tested_exclude_folder_containing_backslash_on_windows() {
+    run()
+        .arg("mutants")
+        .args(["--list", "--exclude", "*\\module\\*"])
+        .current_dir("testdata/tree/with_child_directories")
+        .assert_insta("list_mutants_well_tested_exclude_folder_filter");
+}
+
+#[test]
+fn list_mutants_well_tested_examine_and_exclude_name_filter_combined() {
+    run()
+        .arg("mutants")
+        .args([
+            "--list",
+            "--file",
+            "src/module/utils/*.rs",
+            "--exclude",
+            "nested_function.rs",
+        ])
+        .current_dir("testdata/tree/with_child_directories")
+        .assert_insta("list_mutants_well_tested_examine_and_exclude_name_filter_combined");
+}
+
+#[test]
+fn tree_with_child_directories_is_well_tested() {
+    let tmp_src_dir = copy_of_testdata("with_child_directories");
+    run()
+        .arg("mutants")
+        .arg("-d")
+        .arg(tmp_src_dir.path())
+        .assert()
+        .success();
+}
+
+#[test]
+fn list_mutants_well_tested_multiple_examine_and_exclude_name_filter_with_files_and_folders() {
+    run()
+        .arg("mutants")
+        .args(["--list", "--file", "module_methods.rs", "--file", "*/utils/*", "--exclude", "*/sub_utils/*", "--exclude", "nested_function.rs"])
+        .current_dir("testdata/tree/with_child_directories")
+        .assert_insta("list_mutants_well_tested_multiple_examine_and_exclude_name_filter_with_files_and_folders");
 }
 
 #[test]
diff --git a/tests/snapshots/cli__list_mutants_in_all_trees_as_json.snap b/tests/snapshots/cli__list_mutants_in_all_trees_as_json.snap
index a32878a..f1a0fc1 100644
--- a/tests/snapshots/cli__list_mutants_in_all_trees_as_json.snap
+++ b/tests/snapshots/cli__list_mutants_in_all_trees_as_json.snap
@@ -391,4 +391,60 @@ expression: buf
 ]
 ```
 
+## testdata/tree/with_child_directories
+
+```json
+[
+  {
+    "file": "src/methods.rs",
+    "line": 1,
+    "function": "double",
+    "return_type": "-> usize",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/module_methods.rs",
+    "line": 1,
+    "function": "double",
+    "return_type": "-> usize",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/utils/inside_mod.rs",
+    "line": 3,
+    "function": "outer::inner::name",
+    "return_type": "-> &'static str",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/utils/nested_function.rs",
+    "line": 1,
+    "function": "has_nested",
+    "return_type": "-> u32",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/utils/nested_function.rs",
+    "line": 2,
+    "function": "has_nested::inner",
+    "return_type": "-> u32",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/utils/sub_utils/subutils_nested_function.rs",
+    "line": 1,
+    "function": "has_nested",
+    "return_type": "-> u32",
+    "replacement": "Default::default()"
+  },
+  {
+    "file": "src/module/utils/sub_utils/subutils_nested_function.rs",
+    "line": 2,
+    "function": "has_nested::inner",
+    "return_type": "-> u32",
+    "replacement": "Default::default()"
+  }
+]
+```
+
 
diff --git a/tests/snapshots/cli__list_mutants_in_all_trees_as_text.snap b/tests/snapshots/cli__list_mutants_in_all_trees_as_text.snap
index 0ec531f..7fd0996 100644
--- a/tests/snapshots/cli__list_mutants_in_all_trees_as_text.snap
+++ b/tests/snapshots/cli__list_mutants_in_all_trees_as_text.snap
@@ -134,4 +134,16 @@ src/simple_fns.rs:26: replace double_string -> String with "xyzzy".into()
 src/struct_with_lifetime.rs:14: replace Lex<'buf>::buf_len -> usize with Default::default()
 ```
 
+## testdata/tree/with_child_directories
+
+```
+src/methods.rs:1: replace double -> usize with Default::default()
+src/module/module_methods.rs:1: replace double -> usize with Default::default()
+src/module/utils/inside_mod.rs:3: replace outer::inner::name -> &'static str with Default::default()
+src/module/utils/nested_function.rs:1: replace has_nested -> u32 with Default::default()
+src/module/utils/nested_function.rs:2: replace has_nested::inner -> u32 with Default::default()
+src/module/utils/sub_utils/subutils_nested_function.rs:1: replace has_nested -> u32 with Default::default()
+src/module/utils/sub_utils/subutils_nested_function.rs:2: replace has_nested::inner -> u32 with Default::default()
+```
+
 
diff --git a/tests/snapshots/cli__list_mutants_well_tested_examine_and_exclude_name_filter_combined.snap b/tests/snapshots/cli__list_mutants_well_tested_examine_and_exclude_name_filter_combined.snap
new file mode 100644
index 0000000..15204d1
--- /dev/null
+++ b/tests/snapshots/cli__list_mutants_well_tested_examine_and_exclude_name_filter_combined.snap
@@ -0,0 +1,8 @@
+---
+source: tests/cli.rs
+expression: "String::from_utf8_lossy(&output.stdout)"
+---
+src/module/utils/inside_mod.rs:3: replace outer::inner::name -> &'static str with Default::default()
+src/module/utils/sub_utils/subutils_nested_function.rs:1: replace has_nested -> u32 with Default::default()
+src/module/utils/sub_utils/subutils_nested_function.rs:2: replace has_nested::inner -> u32 with Default::default()
+
diff --git a/tests/snapshots/cli__list_mutants_well_tested_name_filter.snap b/tests/snapshots/cli__list_mutants_well_tested_examine_name_filter.snap
similarity index 92%
rename from tests/snapshots/cli__list_mutants_well_tested_name_filter.snap
rename to tests/snapshots/cli__list_mutants_well_tested_examine_name_filter.snap
index b1cf545..ee55349 100644
--- a/tests/snapshots/cli__list_mutants_well_tested_name_filter.snap
+++ b/tests/snapshots/cli__list_mutants_well_tested_examine_name_filter.snap
@@ -1,6 +1,5 @@
 ---
 source: tests/cli.rs
-assertion_line: 41
 expression: "String::from_utf8_lossy(&output.stdout)"
 ---
 src/nested_function.rs:1: replace has_nested -> u32 with Default::default()
diff --git a/tests/snapshots/cli__list_mutants_well_tested_exclude_folder_filter.snap b/tests/snapshots/cli__list_mutants_well_tested_exclude_folder_filter.snap
new file mode 100644
index 0000000..cd64355
--- /dev/null
+++ b/tests/snapshots/cli__list_mutants_well_tested_exclude_folder_filter.snap
@@ -0,0 +1,6 @@
+---
+source: tests/cli.rs
+expression: "String::from_utf8_lossy(&output.stdout)"
+---
+src/methods.rs:1: replace double -> usize with Default::default()
+
diff --git a/tests/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap b/tests/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap
new file mode 100644
index 0000000..bf92012
--- /dev/null
+++ b/tests/snapshots/cli__list_mutants_well_tested_exclude_name_filter.snap
@@ -0,0 +1,14 @@
+---
+source: tests/cli.rs
+expression: "String::from_utf8_lossy(&output.stdout)"
+---
+src/inside_mod.rs:3: replace outer::inner::name -> &'static str with Default::default()
+src/methods.rs:16: replace Foo::double with ()
+src/methods.rs:22: replace <impl Display for Foo>::fmt -> fmt::Result with Ok(Default::default())
+src/methods.rs:28: replace <impl Debug for &Foo>::fmt -> fmt::Result with Ok(Default::default())
+src/nested_function.rs:1: replace has_nested -> u32 with Default::default()
+src/nested_function.rs:2: replace has_nested::inner -> u32 with Default::default()
+src/result.rs:5: replace simple_result -> Result<&'static str, ()> with Ok(Default::default())
+src/result.rs:9: replace error_if_negative -> Result<(), ()> with Ok(Default::default())
+src/struct_with_lifetime.rs:14: replace Lex<'buf>::buf_len -> usize with Default::default()
+
diff --git a/tests/snapshots/cli__list_mutants_well_tested_multiple_examine_and_exclude_name_filter_with_files_and_folders.snap b/tests/snapshots/cli__list_mutants_well_tested_multiple_examine_and_exclude_name_filter_with_files_and_folders.snap
new file mode 100644
index 0000000..9155410
--- /dev/null
+++ b/tests/snapshots/cli__list_mutants_well_tested_multiple_examine_and_exclude_name_filter_with_files_and_folders.snap
@@ -0,0 +1,7 @@
+---
+source: tests/cli.rs
+expression: "String::from_utf8_lossy(&output.stdout)"
+---
+src/module/module_methods.rs:1: replace double -> usize with Default::default()
+src/module/utils/inside_mod.rs:3: replace outer::inner::name -> &'static str with Default::default()
+