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

Add unstable --dep-coverage option #353

Merged
merged 1 commit into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,6 @@ OPTIONS:

This flag can only be used together with --json, --lcov, or --cobertura.

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--output-path <PATH>
Specify a file to write coverage data into.

Expand Down Expand Up @@ -178,6 +173,14 @@ OPTIONS:
--include-build-script
Include build script in coverage report

--dep-coverage <NAME>
Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--doctests
Including doc tests (unstable)

Expand Down
13 changes: 8 additions & 5 deletions docs/cargo-llvm-cov-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ OPTIONS:

This flag can only be used together with --json, --lcov, or --cobertura.

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--output-path <PATH>
Specify a file to write coverage data into.

Expand Down Expand Up @@ -115,6 +110,14 @@ OPTIONS:
--include-build-script
Include build script in coverage report

--dep-coverage <NAME>
Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--doctests
Including doc tests (unstable)

Expand Down
13 changes: 8 additions & 5 deletions docs/cargo-llvm-cov-run.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ OPTIONS:

This flag can only be used together with --json, --lcov, or --cobertura.

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--output-path <PATH>
Specify a file to write coverage data into.

Expand Down Expand Up @@ -132,6 +127,14 @@ OPTIONS:
--include-build-script
Include build script in coverage report

--dep-coverage <NAME>
Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--ignore-run-fail
Run all tests regardless of failure and generate report

Expand Down
13 changes: 8 additions & 5 deletions docs/cargo-llvm-cov-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,6 @@ OPTIONS:

This flag can only be used together with --json, --lcov, or --cobertura.

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--output-path <PATH>
Specify a file to write coverage data into.

Expand Down Expand Up @@ -137,6 +132,14 @@ OPTIONS:
--include-build-script
Include build script in coverage report

--dep-coverage <NAME>
Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--doctests
Including doc tests (unstable)

Expand Down
13 changes: 8 additions & 5 deletions docs/cargo-llvm-cov.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ OPTIONS:

This flag can only be used together with --json, --lcov, or --cobertura.

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--output-path <PATH>
Specify a file to write coverage data into.

Expand Down Expand Up @@ -132,6 +127,14 @@ OPTIONS:
--include-build-script
Include build script in coverage report

--dep-coverage <NAME>
Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)

--skip-functions
Skip exporting per-function coverage data.

This flag can only be used together with --json, --lcov, or --cobertura.

--doctests
Including doc tests (unstable)

Expand Down
5 changes: 5 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl Args {
let mut fail_uncovered_functions = None;
let mut show_missing_lines = false;
let mut include_build_script = false;
let mut dep_coverage = None;
let mut skip_functions = false;

// build options
Expand Down Expand Up @@ -420,6 +421,7 @@ impl Args {
Long("fail-uncovered-functions") => parse_opt!(fail_uncovered_functions),
Long("show-missing-lines") => parse_flag!(show_missing_lines),
Long("include-build-script") => parse_flag!(include_build_script),
Long("dep-coverage") => parse_opt!(dep_coverage),

// show-env options
Long("export-prefix") => parse_flag!(export_prefix),
Expand Down Expand Up @@ -882,6 +884,7 @@ impl Args {
fail_uncovered_functions,
show_missing_lines,
include_build_script,
dep_coverage,
skip_functions,
},
show_env: ShowEnvOptions { export_prefix },
Expand Down Expand Up @@ -1117,6 +1120,8 @@ pub(crate) struct LlvmCovOptions {
pub(crate) show_missing_lines: bool,
/// Include build script in coverage report.
pub(crate) include_build_script: bool,
/// Show coverage of th specified dependency instead of the crates in the current workspace. (unstable)
pub(crate) dep_coverage: Option<String>,
/// Skip functions in coverage report.
pub(crate) skip_functions: bool,
}
Expand Down
3 changes: 3 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ impl Context {
if args.cov.disable_default_ignore_filename_regex {
warn!("--disable-default-ignore-filename-regex option is unstable");
}
if args.cov.dep_coverage.is_some() {
warn!("--dep-coverage option is unstable");
}
if args.doc {
warn!("--doc option is unstable");
} else if args.doctests {
Expand Down
10 changes: 5 additions & 5 deletions src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serde_derive::{Deserialize, Serialize};
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct LlvmCovJsonExport {
/// List of one or more export objects
data: Vec<Export>,
pub data: Vec<Export>,
// llvm.coverage.json.export
#[serde(rename = "type")]
type_: String,
Expand Down Expand Up @@ -319,9 +319,9 @@ impl LlvmCovJsonExport {
/// Json representation of one `CoverageMapping`
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(test, serde(deny_unknown_fields))]
struct Export {
pub struct Export {
/// List of objects describing coverage for files
files: Vec<File>,
pub files: Vec<File>,
/// List of objects describing coverage for functions
///
/// This is None if report is summary-only.
Expand All @@ -333,7 +333,7 @@ struct Export {
/// Coverage for a single file
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(test, serde(deny_unknown_fields))]
struct File {
pub struct File {
/// List of Branches in the file
///
/// This is None if report is summary-only.
Expand All @@ -345,7 +345,7 @@ struct File {
/// This is None if report is summary-only.
#[serde(skip_serializing_if = "Option::is_none")]
expansions: Option<Vec<serde_json::Value>>,
filename: String,
pub filename: String,
/// List of Segments contained in the file
///
/// This is None if report is summary-only.
Expand Down
82 changes: 53 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ fn generate_report(cx: &Context) -> Result<()> {
merge_profraw(cx).context("failed to merge profile data")?;

let object_files = object_files(cx).context("failed to collect object files")?;
let ignore_filename_regex = ignore_filename_regex(cx);
let ignore_filename_regex = ignore_filename_regex(cx, &object_files)?;
let format = Format::from_args(cx);
format
.generate_report(cx, &object_files, ignore_filename_regex.as_deref())
Expand Down Expand Up @@ -1165,7 +1165,7 @@ impl Format {
}
}

fn ignore_filename_regex(cx: &Context) -> Option<String> {
fn ignore_filename_regex(cx: &Context, object_files: &[OsString]) -> Result<Option<String>> {
// On Windows, we should escape the separator.
const SEPARATOR: &str = if cfg!(windows) { "\\\\" } else { "/" };

Expand Down Expand Up @@ -1193,41 +1193,65 @@ fn ignore_filename_regex(cx: &Context) -> Option<String> {
out.push(ignore_filename);
}
if !cx.args.cov.disable_default_ignore_filename_regex {
// TODO: Should we use the actual target path instead of using `tests|examples|benches`?
// We may have a directory like tests/support, so maybe we need both?
if cx.args.remap_path_prefix {
out.push(format!(
r"(^|{SEPARATOR})(rustc{SEPARATOR}([0-9a-f]+|[0-9]+\.[0-9]+\.[0-9]+)|tests|examples|benches){SEPARATOR}"
));
if let Some(dep) = &cx.args.cov.dep_coverage {
let format = Format::Json;
let json = format.get_json(cx, object_files, None).context("failed to get json")?;
let crates_io_re = Regex::new(&format!("{SEPARATOR}registry{SEPARATOR}src{SEPARATOR}index\\.crates\\.io-[0-9a-f]+{SEPARATOR}[0-9A-Za-z-_]+-[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z\\.-]+)?(\\+[0-9A-Za-z\\.-]+)?{SEPARATOR}"))?;
let dep_re = Regex::new(&format!("{SEPARATOR}registry{SEPARATOR}src{SEPARATOR}index\\.crates\\.io-[0-9a-f]+{SEPARATOR}{dep}-[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z\\.-]+)?(\\+[0-9A-Za-z\\.-]+)?{SEPARATOR}"))?;
let mut set = BTreeSet::new();
for data in &json.data {
for file in &data.files {
// TODO: non-crates-io
if let Some(crates_io) = crates_io_re.find(&file.filename) {
if !dep_re.is_match(crates_io.as_str()) {
set.insert(crates_io.as_str());
}
} else {
// TODO: dedup
set.insert(&file.filename);
}
}
}
for f in set {
out.push(f);
}
} else {
out.push(format!(
r"{SEPARATOR}rustc{SEPARATOR}([0-9a-f]+|[0-9]+\.[0-9]+\.[0-9]+){SEPARATOR}|^{}({SEPARATOR}.*)?{SEPARATOR}(tests|examples|benches){SEPARATOR}",
regex::escape(cx.ws.metadata.workspace_root.as_str())
));
}
out.push_abs_path(&cx.ws.target_dir);
if cx.args.remap_path_prefix {
if let Some(path) = env::home_dir() {
// TODO: Should we use the actual target path instead of using `tests|examples|benches`?
// We may have a directory like tests/support, so maybe we need both?
if cx.args.remap_path_prefix {
out.push(format!(
r"(^|{SEPARATOR})(rustc{SEPARATOR}([0-9a-f]+|[0-9]+\.[0-9]+\.[0-9]+)|tests|examples|benches){SEPARATOR}"
));
} else {
out.push(format!(
r"{SEPARATOR}rustc{SEPARATOR}([0-9a-f]+|[0-9]+\.[0-9]+\.[0-9]+){SEPARATOR}|^{}({SEPARATOR}.*)?{SEPARATOR}(tests|examples|benches){SEPARATOR}",
regex::escape(cx.ws.metadata.workspace_root.as_str())
));
}
out.push_abs_path(&cx.ws.target_dir);
if cx.args.remap_path_prefix {
if let Some(path) = env::home_dir() {
out.push_abs_path(path);
}
}
if let Some(path) = env::cargo_home_with_cwd(&cx.current_dir) {
let path = regex::escape(&path.as_os_str().to_string_lossy());
let path = format!("^{path}{SEPARATOR}(registry|git){SEPARATOR}");
out.push(path);
}
if let Some(path) = env::rustup_home_with_cwd(&cx.current_dir) {
out.push_abs_path(path.join("toolchains"));
}
for path in resolve_excluded_paths(cx) {
out.push_abs_path(path);
}
}
if let Some(path) = env::cargo_home_with_cwd(&cx.current_dir) {
let path = regex::escape(&path.as_os_str().to_string_lossy());
let path = format!("^{path}{SEPARATOR}(registry|git){SEPARATOR}");
out.push(path);
}
if let Some(path) = env::rustup_home_with_cwd(&cx.current_dir) {
out.push_abs_path(path.join("toolchains"));
}
for path in resolve_excluded_paths(cx) {
out.push_abs_path(path);
}
}

if out.0.is_empty() {
None
Ok(None)
} else {
Some(out.0)
Ok(Some(out.0))
}
}

Expand Down