Skip to content

Commit 9c55f9b

Browse files
pietroalbiniJoshua Nelson
authored andcommitted
remove the macro and improve the coverage extraction code
1 parent 315281d commit 9c55f9b

File tree

1 file changed

+107
-109
lines changed

1 file changed

+107
-109
lines changed

src/docbuilder/rustwide_builder.rs

Lines changed: 107 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustwide::toolchain::ToolchainError;
2020
use rustwide::{Build, Crate, Toolchain, Workspace, WorkspaceBuilder};
2121
use serde_json::Value;
2222
use std::borrow::Cow;
23-
use std::collections::HashSet;
23+
use std::collections::{HashMap, HashSet};
2424
use std::path::Path;
2525
use std::sync::Arc;
2626

@@ -69,84 +69,6 @@ const ESSENTIAL_FILES_UNVERSIONED: &[&str] = &[
6969
const DUMMY_CRATE_NAME: &str = "empty-library";
7070
const DUMMY_CRATE_VERSION: &str = "1.0.0";
7171

72-
// This macro exists because of lifetimes issues surrounding the `Command::process_lines` method:
73-
// it expects a mutable reference to a closure, in which we capture a variable in order to store
74-
// the JSON output. Unfortunately, we *need* to create the command in the same scope level otherwise
75-
// rustc becomes very grumpy about the fact that the variable needs to be static because it is
76-
// captured in a mutably referenced closure.
77-
//
78-
// So either you create a function with a callback in which you pass the `Command` as an argument,
79-
// or you create a function returning a `Command`, it's very unhappy in both cases.
80-
//
81-
// TODO: make `Command::process_lines` take the closure by value rather than a mutable reference.
82-
macro_rules! config_command {
83-
($obj:ident, $build:expr, $target:expr, $metadata:expr, $limits:expr, $rustdoc_flags_extras:expr, $($extra:tt)+) => {{
84-
let mut cargo_args = vec!["doc", "--lib", "--no-deps"];
85-
if $target != HOST_TARGET {
86-
// If the explicit target is not a tier one target, we need to install it.
87-
if !TARGETS.contains(&$target) {
88-
// This is a no-op if the target is already installed.
89-
$obj.toolchain.add_target(&$obj.workspace, $target)?;
90-
}
91-
cargo_args.push("--target");
92-
cargo_args.push($target);
93-
};
94-
95-
let tmp;
96-
if let Some(cpu_limit) = $obj.cpu_limit {
97-
tmp = format!("-j{}", cpu_limit);
98-
cargo_args.push(&tmp);
99-
}
100-
101-
let tmp;
102-
if let Some(features) = &$metadata.features {
103-
cargo_args.push("--features");
104-
tmp = features.join(" ");
105-
cargo_args.push(&tmp);
106-
}
107-
if $metadata.all_features {
108-
cargo_args.push("--all-features");
109-
}
110-
if $metadata.no_default_features {
111-
cargo_args.push("--no-default-features");
112-
}
113-
114-
let mut rustdoc_flags = vec![
115-
"-Z".to_string(),
116-
"unstable-options".to_string(),
117-
"--static-root-path".to_string(),
118-
"/".to_string(),
119-
"--cap-lints".to_string(),
120-
"warn".to_string(),
121-
];
122-
123-
if let Some(package_rustdoc_args) = &$metadata.rustdoc_args {
124-
rustdoc_flags.append(&mut package_rustdoc_args.clone());
125-
}
126-
127-
rustdoc_flags.extend($rustdoc_flags_extras);
128-
129-
$build
130-
.cargo()
131-
.timeout(Some($limits.timeout()))
132-
.no_output_timeout(None)
133-
.env(
134-
"RUSTFLAGS",
135-
$metadata
136-
.rustc_args
137-
.as_ref()
138-
.map(|args| args.join(" "))
139-
.unwrap_or_default(),
140-
)
141-
.env("RUSTDOCFLAGS", rustdoc_flags.join(" "))
142-
// For docs.rs detection from build script:
143-
// https://github.com/rust-lang/docs.rs/issues/147
144-
.env("DOCS_RS", "1")
145-
.args(&cargo_args)
146-
$($extra)+
147-
}}
148-
}
149-
15072
pub struct RustwideBuilder {
15173
workspace: Workspace,
15274
toolchain: Toolchain,
@@ -558,41 +480,46 @@ impl RustwideBuilder {
558480
metadata: &Metadata,
559481
limits: &Limits,
560482
) -> Result<Option<DocCoverage>> {
561-
let mut doc_coverage_json = None;
562-
563483
let rustdoc_flags = vec![
564484
"--output-format".to_string(),
565485
"json".to_string(),
566486
"--show-coverage".to_string(),
567487
];
568-
config_command!(self, build, target, metadata, limits, rustdoc_flags,
488+
489+
#[derive(serde::Deserialize)]
490+
struct FileCoverage {
491+
total: i32,
492+
with_docs: i32,
493+
}
494+
495+
let mut coverage = DocCoverage {
496+
total_items: 0,
497+
documented_items: 0,
498+
};
499+
500+
self.prepare_command(build, target, metadata, limits, rustdoc_flags)?
569501
.process_lines(&mut |line, _| {
570502
if line.starts_with('{') && line.ends_with('}') {
571-
doc_coverage_json = Some(line.to_owned());
503+
let parsed = match serde_json::from_str::<HashMap<String, FileCoverage>>(line) {
504+
Ok(parsed) => parsed,
505+
Err(_) => return,
506+
};
507+
for file in parsed.values() {
508+
coverage.total_items += file.total;
509+
coverage.documented_items += file.with_docs;
510+
}
572511
}
573512
})
574513
.log_output(false)
575514
.run()?;
576-
);
577-
578-
if let Some(json) = doc_coverage_json {
579-
if let Ok(Value::Object(m)) = serde_json::from_str(&json) {
580-
let (mut total_items, mut documented_items) = (0, 0);
581-
for entry in m.values() {
582-
if let Some(Value::Number(n)) = entry.get("total") {
583-
total_items += n.as_i64().unwrap_or(0) as i32;
584-
}
585-
if let Some(Value::Number(n)) = entry.get("with_docs") {
586-
documented_items += n.as_i64().unwrap_or(0) as i32;
587-
}
588-
}
589-
return Ok(Some(DocCoverage {
590-
total_items,
591-
documented_items,
592-
}));
593-
}
594-
}
595-
Ok(None)
515+
516+
Ok(
517+
if coverage.total_items == 0 && coverage.documented_items == 0 {
518+
None
519+
} else {
520+
Some(coverage)
521+
},
522+
)
596523
}
597524

598525
fn execute_build(
@@ -627,12 +554,9 @@ impl RustwideBuilder {
627554
storage.set_max_size(limits.max_log_size());
628555

629556
let successful = logging::capture(&storage, || {
630-
let wrap = || {
631-
config_command!(self, build, target, metadata, limits, rustdoc_flags,
632-
.run()
633-
)
634-
};
635-
wrap().is_ok()
557+
self.prepare_command(build, target, metadata, limits, rustdoc_flags)
558+
.and_then(|command| command.run().map_err(failure::Error::from))
559+
.is_ok()
636560
});
637561
let doc_coverage = if successful {
638562
self.get_coverage(target, build, metadata, limits)?
@@ -665,6 +589,80 @@ impl RustwideBuilder {
665589
})
666590
}
667591

592+
fn prepare_command<'ws, 'pl>(
593+
&self,
594+
build: &'ws Build,
595+
target: &str,
596+
metadata: &Metadata,
597+
limits: &Limits,
598+
rustdoc_flags_extras: Vec<String>,
599+
) -> Result<Command<'ws, 'pl>> {
600+
let mut cargo_args = vec!["doc", "--lib", "--no-deps"];
601+
if target != HOST_TARGET {
602+
// If the explicit target is not a tier one target, we need to install it.
603+
if !TARGETS.contains(&target) {
604+
// This is a no-op if the target is already installed.
605+
self.toolchain.add_target(&self.workspace, target)?;
606+
}
607+
cargo_args.push("--target");
608+
cargo_args.push(target);
609+
};
610+
611+
let tmp;
612+
if let Some(cpu_limit) = self.cpu_limit {
613+
tmp = format!("-j{}", cpu_limit);
614+
cargo_args.push(&tmp);
615+
}
616+
617+
let tmp;
618+
if let Some(features) = &metadata.features {
619+
cargo_args.push("--features");
620+
tmp = features.join(" ");
621+
cargo_args.push(&tmp);
622+
}
623+
if metadata.all_features {
624+
cargo_args.push("--all-features");
625+
}
626+
if metadata.no_default_features {
627+
cargo_args.push("--no-default-features");
628+
}
629+
630+
let mut rustdoc_flags = vec![
631+
"-Z".to_string(),
632+
"unstable-options".to_string(),
633+
"--static-root-path".to_string(),
634+
"/".to_string(),
635+
"--cap-lints".to_string(),
636+
"warn".to_string(),
637+
];
638+
639+
if let Some(package_rustdoc_args) = &metadata.rustdoc_args {
640+
rustdoc_flags.append(&mut package_rustdoc_args.clone());
641+
}
642+
643+
rustdoc_flags.extend(rustdoc_flags_extras);
644+
645+
let command = build
646+
.cargo()
647+
.timeout(Some(limits.timeout()))
648+
.no_output_timeout(None)
649+
.env(
650+
"RUSTFLAGS",
651+
metadata
652+
.rustc_args
653+
.as_ref()
654+
.map(|args| args.join(" "))
655+
.unwrap_or_default(),
656+
)
657+
.env("RUSTDOCFLAGS", rustdoc_flags.join(" "))
658+
// For docs.rs detection from build script:
659+
// https://github.com/rust-lang/docs.rs/issues/147
660+
.env("DOCS_RS", "1")
661+
.args(&cargo_args);
662+
663+
Ok(command)
664+
}
665+
668666
fn copy_docs(
669667
&self,
670668
target_dir: &Path,

0 commit comments

Comments
 (0)