Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exclusion Patterns for Lines and Branches #416

Merged
merged 17 commits into from
May 4, 2020
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ script:
- |
if [ "$TRAVIS_RUST_VERSION" = "nightly" ] && [ -z "$TRAVIS_TAG" ]; then
zip -0 ccov.zip `find . \( -name "grcov*.gc*" -o -name "llvmgcov.gc*" \) -print`;
./target/debug/grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore "/*" -o lcov.info;
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
./target/debug/grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore "/*" -o lcov.info --excl_line "#\[derive\(" --excl_br_line "#\[derive\(";
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
bash <(curl -s https://codecov.io/bash) -f lcov.info;
fi
- |
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ FLAGS:
OPTIONS:
--commit-sha <COMMIT HASH> Sets the hash of the commit used to generate the code coverage data
--excl_br_line <regex>
Lines containing this marker will be excluded.
Lines in covered files containing this marker will be excluded.
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
--excl_br_start <regex>
Marks the beginning of an excluded section. The current line is part of this section.
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
--excl_br_stop <regex>
Marks the end of an excluded section. The current line is part of this section.
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
--excl_line <regex>
Lines containing this marker will be excluded.
Lines in covered files containing this marker will be excluded.
--excl_start <regex>
Marks the beginning of an excluded section. The current line is part of this section.
--excl_stop <regex>
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test_script:
If ($env:CHANNEL -eq "nightly" -And $env:APPVEYOR_REPO_TAG -eq "false") {
mkdir ccov_dir
Get-ChildItem -Path *\grcov*.gc* -Recurse | Copy-Item -Destination ccov_dir
.\target\debug\grcov ccov_dir -s . -t lcov --llvm --branch --ignore-not-existing --ignore "C:*" -o lcov.info
.\target\debug\grcov ccov_dir -s . -t lcov --llvm --branch --ignore-not-existing --ignore "C:*" -o lcov.info --excl_line "#\[derive\(" --excl_br_line "#\[derive\("
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
(Get-Content lcov.info) | Foreach-Object {$_ -replace "\xEF\xBB\xBF", ""} | Set-Content lcov.info
((Get-Content lcov.info) -join "`n") + "`n" | Set-Content -NoNewline lcov.info
$env:PATH = "C:\msys64\usr\bin;" + $env:PATH
Expand Down
46 changes: 22 additions & 24 deletions src/file_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum FilterType {
Both(u32),
}

#[derive(Default)]
pub struct FileFilter {
excl_line: Option<Regex>,
excl_start: Option<Regex>,
Expand All @@ -16,19 +17,6 @@ pub struct FileFilter {
excl_br_stop: Option<Regex>,
}

impl Default for FileFilter {
fn default() -> Self {
Self {
excl_line: None,
excl_start: None,
excl_stop: None,
excl_br_line: None,
excl_br_start: None,
excl_br_stop: None,
}
}
}

fn matches(regex: &Option<Regex>, line: &str) -> bool {
if let Some(regex) = regex {
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
regex.is_match(line)
Expand Down Expand Up @@ -56,7 +44,7 @@ impl FileFilter {
}
}

pub fn create<'a>(&'a self, file: &PathBuf) -> Vec<FilterType> {
pub fn create(&self, file: &PathBuf) -> Vec<FilterType> {
if self.excl_line.is_none()
&& self.excl_start.is_none()
&& self.excl_br_line.is_none()
Expand All @@ -79,34 +67,41 @@ impl FileFilter {
.enumerate()
.into_iter()
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
.filter_map(move |(number, line)| {
// Line numbers are 1-based.
let number = (number + 1) as u32;

// The file is split on \n, which may result in a trailing \r
// on Windows. Remove it.
let line = if line.ends_with("\r") {
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
&line[..(line.len() - 1)]
} else {
line
};

if ignore_br {
if matches(&self.excl_br_stop, line) {
ignore_br = false
}
// End a branch ignore region. Region endings are exclusive.
if ignore_br && matches(&self.excl_br_stop, line) {
ignore_br = false
}

if ignore {
if matches(&self.excl_stop, line) {
ignore = false
}
// End a line ignore region. Region endings are exclusive.
if ignore && matches(&self.excl_stop, line) {
ignore = false
}

if matches(&self.excl_br_start, line) {
// Start a branch ignore region. Region starts are inclusive.
if !ignore_br && matches(&self.excl_br_start, line) {
ignore_br = true;
}

if matches(&self.excl_start, line) {
// Start a line ignore region. Region starts are inclusive.
if !ignore && matches(&self.excl_start, line) {
ignore = true;
}

if ignore_br {
// Consuming code has to eliminate each of these
// individually, so it has to know when both are ignored vs.
// either.
if ignore {
Some(FilterType::Both(number))
} else {
Expand All @@ -115,6 +110,9 @@ impl FileFilter {
} else if ignore {
Some(FilterType::Line(number))
} else if matches(&self.excl_br_line, line) {
// Single line exclusion. If single line exclusions occur
// inside a region they are meaningless (would be applied
// anway), so they are lower priority.
if matches(&self.excl_line, line) {
Some(FilterType::Both(number))
} else {
Expand Down
48 changes: 26 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,37 +182,37 @@ fn main() {
.default_value("stderr")
.value_name("LOG")
.takes_value(true))

.arg(Arg::with_name("excl_line")
.help("Lines containing this marker will be excluded.")
.help("Lines in covered files containing this marker will be excluded.")
.long("excl_line")
.value_name("regex")
.takes_value(true))

.arg(Arg::with_name("excl_start")
.help("Marks the beginning of an excluded section. The current line is part of this section.")
.long("excl_start")
.value_name("regex")
.takes_value(true))

.arg(Arg::with_name("excl_stop")
.help("Marks the end of an excluded section. The current line is part of this section.")
.long("excl_stop")
.value_name("regex")
.takes_value(true))

.arg(Arg::with_name("excl_br_line")
.help("Lines containing this marker will be excluded.")
.help("Lines in covered files containing this marker will be excluded.")
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
.long("excl_br_line")
.value_name("regex")
.takes_value(true))

.arg(Arg::with_name("excl_br_start")
.help("Marks the beginning of an excluded section. The current line is part of this section.")
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
.long("excl_br_start")
.value_name("regex")
.takes_value(true))

.arg(Arg::with_name("excl_br_stop")
.help("Marks the end of an excluded section. The current line is part of this section.")
jcdickinson marked this conversation as resolved.
Show resolved Hide resolved
.long("excl_br_stop")
Expand Down Expand Up @@ -280,12 +280,24 @@ fn main() {
}
};

let excl_line = as_regex(matches.value_of("excl_line"));
let excl_start = as_regex(matches.value_of("excl_start"));
let excl_stop = as_regex(matches.value_of("excl_stop"));
let excl_br_line = as_regex(matches.value_of("excl_br_line"));
let excl_br_start = as_regex(matches.value_of("excl_br_start"));
let excl_br_stop = as_regex(matches.value_of("excl_br_stop"));
let excl_line = matches.value_of("excl_line").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_line."))
});
let excl_start = matches.value_of("excl_start").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_start."))
});
let excl_stop = matches.value_of("excl_stop").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_stop."))
});
let excl_br_line = matches.value_of("excl_br_line").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_br_line."))
});
let excl_br_start = matches.value_of("excl_br_start").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_br_start."))
});
let excl_br_stop = matches.value_of("excl_br_stop").map_or(None, |f| {
Some(regex::Regex::new(f).expect("invalid regex for excl_br_stop."))
});
let file_filter = FileFilter::new(
excl_line,
excl_start,
Expand Down Expand Up @@ -473,11 +485,3 @@ fn main() {
assert!(false, "{} is not a supported output type", output_type);
}
}

fn as_regex(value: Option<&str>) -> Option<regex::Regex> {
if let Some(value) = value {
Some(regex::Regex::new(value).expect(&format!("invalid regular expression: {}", value)))
} else {
None
}
}