Repository: xd009642/tarpaulin (rust)

Issue:
`#[no_coverage]` is working but `#[cfg_attr(tarpaulin, no_coverage)]` not
**Describe the bug**

I am conditionally add `no_coverage` attribute only if `--cfg tarpaulin` is set.

```rust
#[cfg_attr(tarpaulin, no_coverage)]
mod info;
```

It's not working but putting just `#[no_coverage]` works as expected.

**To Reproduce**

1. Create function and add attribute `#[cfg_attr(tarpaulin, no_coverage)]`.
2. Run `cargo tarpaulin`.
3. Check report - function is included in coverage lines.
4. Change attribute into `#[no_coverage]`.
5. Run `cargo tarpaulin`.
6. Check report - function is ignored as expected.

**Expected behavior**

Item should be ignored from coverage.

**Live example**

Check my [`ferric-bytes/chksum-build`](https://github.com/ferric-bytes/chksum-build) repo - specially code below.

https://github.com/ferric-bytes/chksum-build/blob/299e286ddfea98edc0687d63c8959ce7e3ebd264/src/lib.rs#L178-L179

**Possible fix**

As far as I understand some extra checks should be added to this function.

https://github.com/xd009642/tarpaulin/blob/343e912bf33a3872ff9f49d48686831d7ca701da/src/source_analysis/attributes.rs#L35-L73

Pull request:
Fixes #1160 
Look at cfg_attr in more detail

<!--- When contributing to tarpaulin all contributions should branch off the -->
<!--- develop branch as master is only used for releases. --> 

<!--- Check CONTRIBUTING.md for more information-->

<!--- Please describe the changes in the PR and them motivation below -->


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3ec5c2..3da2295 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ operating systems
 - Set `LLVM_PROFILE_FILE` for building tests and delete the generated profraws to ignore build script
 coverage 
 - Remove dependency on memmap
+- Filter out expressions or items with `#[cfg_attr(tarpaulin, no_coverage)]`
 
 ## [0.24.0] 2023-01-24
 ### Added
diff --git a/src/source_analysis/attributes.rs b/src/source_analysis/attributes.rs
index 7912d2e..c282baf 100644
--- a/src/source_analysis/attributes.rs
+++ b/src/source_analysis/attributes.rs
@@ -55,8 +55,24 @@ pub(crate) fn check_cfg_attr(attr: &Meta) -> bool {
                 }
             }
         }
+    } else if id.is_ident("cfg_attr") {
+        if let Meta::List(ml) = attr {
+            let tarp_cfged_ignores = &["no_coverage"];
+            if let NestedMeta::Meta(Meta::Path(ref i)) = ml.nested[0] {
+                if i.is_ident("tarpaulin") {
+                    for p in ml.nested.iter().skip(1) {
+                        if let NestedMeta::Meta(Meta::Path(ref path)) = p {
+                            if tarp_cfged_ignores.iter().any(|x| path.is_ident(x)) {
+                                ignore_span = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
     } else {
-        let skip_attrs = vec!["tarpaulin", "skip"];
+        let skip_attrs = &["tarpaulin", "skip"];
         let mut n = 0;
         ignore_span = true;
         for (segment, attr) in id.segments.iter().zip(skip_attrs.iter()) {


Test patch:
diff --git a/src/source_analysis/tests.rs b/src/source_analysis/tests.rs
index 07ad7c9..dd89cb1 100644
--- a/src/source_analysis/tests.rs
+++ b/src/source_analysis/tests.rs
@@ -816,6 +816,11 @@ fn tarpaulin_skip_attr() {
         fn uncovered3() {
             println!(\"zombie lincoln\");
         }
+
+        #[cfg_attr(tarpaulin, no_coverage)]
+        fn uncovered4() {
+            println!(\"zombie lincoln\");
+        }
         ",
         file: Path::new(""),
         ignore_mods: RefCell::new(HashSet::new()),
@@ -834,6 +839,7 @@ fn tarpaulin_skip_attr() {
     assert!(lines.ignore.contains(&Lines::Line(18)));
     assert!(lines.ignore.contains(&Lines::Line(22)));
     assert!(lines.ignore.contains(&Lines::Line(23)));
+    assert!(lines.ignore.contains(&Lines::Line(28)));
 
     let ctx = Context {
         config: &config,