mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Add doc comments to explain scrape-examples feature
This commit is contained in:
parent
b325a8d5d5
commit
c26ed6357f
@ -78,6 +78,9 @@ pub struct Context<'a, 'cfg> {
|
|||||||
/// See Context::find_metadata_units for more details.
|
/// See Context::find_metadata_units for more details.
|
||||||
pub metadata_for_doc_units: HashMap<Unit, Metadata>,
|
pub metadata_for_doc_units: HashMap<Unit, Metadata>,
|
||||||
|
|
||||||
|
/// Set of metadata of Docscrape units that fail before completion, e.g.
|
||||||
|
/// because the target has a type error. This is in an Arc<Mutex<..>>
|
||||||
|
/// because it is continuously updated as the job progresses.
|
||||||
pub failed_scrape_units: Arc<Mutex<HashSet<Metadata>>>,
|
pub failed_scrape_units: Arc<Mutex<HashSet<Metadata>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,23 +348,29 @@ enum Message {
|
|||||||
BuildPlanMsg(String, ProcessBuilder, Arc<Vec<OutputFile>>),
|
BuildPlanMsg(String, ProcessBuilder, Arc<Vec<OutputFile>>),
|
||||||
Stdout(String),
|
Stdout(String),
|
||||||
Stderr(String),
|
Stderr(String),
|
||||||
|
|
||||||
|
// This is for general stderr output from subprocesses
|
||||||
Diagnostic {
|
Diagnostic {
|
||||||
id: JobId,
|
id: JobId,
|
||||||
level: String,
|
level: String,
|
||||||
diag: String,
|
diag: String,
|
||||||
fixable: bool,
|
fixable: bool,
|
||||||
},
|
},
|
||||||
// This is distinct from Diagnostic because it gets emitted through
|
// This handles duplicate output that is suppressed, for showing
|
||||||
// a different Shell pathway
|
// only a count of duplicate messages instead
|
||||||
Warning {
|
|
||||||
id: JobId,
|
|
||||||
warning: String,
|
|
||||||
},
|
|
||||||
WarningCount {
|
WarningCount {
|
||||||
id: JobId,
|
id: JobId,
|
||||||
emitted: bool,
|
emitted: bool,
|
||||||
fixable: bool,
|
fixable: bool,
|
||||||
},
|
},
|
||||||
|
// This is for warnings generated by Cargo's interpretation of the
|
||||||
|
// subprocess output, e.g. scrape-examples prints a warning if a
|
||||||
|
// unit fails to be scraped
|
||||||
|
Warning {
|
||||||
|
id: JobId,
|
||||||
|
warning: String,
|
||||||
|
},
|
||||||
|
|
||||||
FixDiagnostic(diagnostic_server::Message),
|
FixDiagnostic(diagnostic_server::Message),
|
||||||
Token(io::Result<Acquired>),
|
Token(io::Result<Acquired>),
|
||||||
Finish(JobId, Artifact, CargoResult<()>),
|
Finish(JobId, Artifact, CargoResult<()>),
|
||||||
@ -412,6 +418,7 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See [`Message::Diagnostic`] and [`Message::WarningCount`].
|
||||||
pub fn emit_diag(&self, level: String, diag: String, fixable: bool) -> CargoResult<()> {
|
pub fn emit_diag(&self, level: String, diag: String, fixable: bool) -> CargoResult<()> {
|
||||||
if let Some(dedupe) = self.output {
|
if let Some(dedupe) = self.output {
|
||||||
let emitted = dedupe.emit_diag(&diag)?;
|
let emitted = dedupe.emit_diag(&diag)?;
|
||||||
@ -433,6 +440,7 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See [`Message::Warning`].
|
||||||
pub fn warning(&self, warning: String) -> CargoResult<()> {
|
pub fn warning(&self, warning: String) -> CargoResult<()> {
|
||||||
self.messages.push_bounded(Message::Warning {
|
self.messages.push_bounded(Message::Warning {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
|
@ -654,8 +654,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
|
|||||||
rustdoc.arg("-C").arg(format!("metadata={}", metadata));
|
rustdoc.arg("-C").arg(format!("metadata={}", metadata));
|
||||||
|
|
||||||
let scrape_output_path = |unit: &Unit| -> CargoResult<PathBuf> {
|
let scrape_output_path = |unit: &Unit| -> CargoResult<PathBuf> {
|
||||||
cx.outputs(unit)
|
cx.outputs(unit).map(|outputs| outputs[0].path.clone())
|
||||||
.map(|outputs| outputs[0].path.to_path_buf())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if unit.mode.is_doc_scrape() {
|
if unit.mode.is_doc_scrape() {
|
||||||
|
@ -191,6 +191,8 @@ pub fn add_root_urls(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether a target should have examples scraped from it
|
||||||
|
/// by rustdoc. Configured within Cargo.toml.
|
||||||
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)]
|
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)]
|
||||||
pub enum RustdocScrapeExamples {
|
pub enum RustdocScrapeExamples {
|
||||||
Enabled,
|
Enabled,
|
||||||
|
@ -12,6 +12,7 @@ use serde::Serialize;
|
|||||||
use toml_edit::easy as toml;
|
use toml_edit::easy as toml;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::core::compiler::rustdoc::RustdocScrapeExamples;
|
||||||
use crate::core::compiler::{CompileKind, CrateType};
|
use crate::core::compiler::{CompileKind, CrateType};
|
||||||
use crate::core::resolver::ResolveBehavior;
|
use crate::core::resolver::ResolveBehavior;
|
||||||
use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
|
use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
|
||||||
@ -21,8 +22,6 @@ use crate::util::interning::InternedString;
|
|||||||
use crate::util::toml::{TomlManifest, TomlProfiles};
|
use crate::util::toml::{TomlManifest, TomlProfiles};
|
||||||
use crate::util::{short_hash, Config, Filesystem};
|
use crate::util::{short_hash, Config, Filesystem};
|
||||||
|
|
||||||
use super::compiler::rustdoc::RustdocScrapeExamples;
|
|
||||||
|
|
||||||
pub enum EitherManifest {
|
pub enum EitherManifest {
|
||||||
Real(Manifest),
|
Real(Manifest),
|
||||||
Virtual(VirtualManifest),
|
Virtual(VirtualManifest),
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
//! Filters and their rules to select which Cargo targets will be built.
|
//! Filters and their rules to select which Cargo targets will be built.
|
||||||
|
|
||||||
use crate::core::compiler::CompileMode;
|
use crate::core::compiler::CompileMode;
|
||||||
use crate::core::{Target, TargetKind};
|
use crate::core::dependency::DepKind;
|
||||||
|
use crate::core::resolver::HasDevUnits;
|
||||||
|
use crate::core::{Package, Target, TargetKind};
|
||||||
use crate::util::restricted_names::is_glob_pattern;
|
use crate::util::restricted_names::is_glob_pattern;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
@ -299,4 +301,67 @@ impl CompileFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a CompileFilter that represents the maximal set of targets
|
||||||
|
/// that should be considered for scraped examples.
|
||||||
|
pub(super) fn refine_for_docscrape(
|
||||||
|
&self,
|
||||||
|
to_builds: &[&Package],
|
||||||
|
has_dev_units: HasDevUnits,
|
||||||
|
) -> CompileFilter {
|
||||||
|
// In general, the goal is to scrape examples from (a) whatever targets
|
||||||
|
// the user is documenting, and (b) Example targets. However, if the user
|
||||||
|
// is documenting a library with dev-dependencies, those dev-deps are not
|
||||||
|
// needed for the library, while dev-deps are needed for the examples.
|
||||||
|
//
|
||||||
|
// If scrape-examples caused `cargo doc` to start requiring dev-deps, this
|
||||||
|
// would be a breaking change to crates whose dev-deps don't compile.
|
||||||
|
// Therefore we ONLY want to scrape Example targets if either:
|
||||||
|
// (1) No package has dev-dependencies, so this is a moot issue, OR
|
||||||
|
// (2) The provided CompileFilter requires dev-dependencies anyway.
|
||||||
|
//
|
||||||
|
// The next two variables represent these two conditions.
|
||||||
|
|
||||||
|
let no_pkg_has_dev_deps = to_builds.iter().all(|pkg| {
|
||||||
|
pkg.summary()
|
||||||
|
.dependencies()
|
||||||
|
.iter()
|
||||||
|
.all(|dep| !matches!(dep.kind(), DepKind::Development))
|
||||||
|
});
|
||||||
|
|
||||||
|
let reqs_dev_deps = matches!(has_dev_units, HasDevUnits::Yes);
|
||||||
|
|
||||||
|
let example_filter = if no_pkg_has_dev_deps || reqs_dev_deps {
|
||||||
|
FilterRule::All
|
||||||
|
} else {
|
||||||
|
FilterRule::none()
|
||||||
|
};
|
||||||
|
|
||||||
|
match self {
|
||||||
|
CompileFilter::Only {
|
||||||
|
all_targets,
|
||||||
|
lib,
|
||||||
|
bins,
|
||||||
|
tests,
|
||||||
|
benches,
|
||||||
|
..
|
||||||
|
} => CompileFilter::Only {
|
||||||
|
all_targets: *all_targets,
|
||||||
|
lib: lib.clone(),
|
||||||
|
bins: bins.clone(),
|
||||||
|
examples: example_filter,
|
||||||
|
tests: tests.clone(),
|
||||||
|
benches: benches.clone(),
|
||||||
|
},
|
||||||
|
|
||||||
|
CompileFilter::Default { .. } => CompileFilter::Only {
|
||||||
|
all_targets: false,
|
||||||
|
lib: LibRule::Default,
|
||||||
|
bins: FilterRule::none(),
|
||||||
|
examples: example_filter,
|
||||||
|
tests: FilterRule::none(),
|
||||||
|
benches: FilterRule::none(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ use crate::core::compiler::{standard_lib, CrateType, TargetInfo};
|
|||||||
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
|
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
|
||||||
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, RustcTargetData, Unit};
|
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, RustcTargetData, Unit};
|
||||||
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
|
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
|
||||||
use crate::core::dependency::DepKind;
|
|
||||||
use crate::core::profiles::{Profiles, UnitFor};
|
use crate::core::profiles::{Profiles, UnitFor};
|
||||||
use crate::core::resolver::features::{self, CliFeatures, FeaturesFor};
|
use crate::core::resolver::features::{self, CliFeatures, FeaturesFor};
|
||||||
use crate::core::resolver::{HasDevUnits, Resolve};
|
use crate::core::resolver::{HasDevUnits, Resolve};
|
||||||
@ -370,7 +369,7 @@ pub fn create_bcx<'a, 'cfg>(
|
|||||||
|
|
||||||
let should_scrape = build_config.mode.is_doc() && config.cli_unstable().rustdoc_scrape_examples;
|
let should_scrape = build_config.mode.is_doc() && config.cli_unstable().rustdoc_scrape_examples;
|
||||||
let mut scrape_units = if should_scrape {
|
let mut scrape_units = if should_scrape {
|
||||||
let scrape_filter = filter_for_scrape_units(&to_builds, has_dev_units, filter);
|
let scrape_filter = filter.refine_for_docscrape(&to_builds, has_dev_units);
|
||||||
let all_units = generate_targets(
|
let all_units = generate_targets(
|
||||||
ws,
|
ws,
|
||||||
&to_builds,
|
&to_builds,
|
||||||
@ -567,56 +566,6 @@ pub fn create_bcx<'a, 'cfg>(
|
|||||||
Ok(bcx)
|
Ok(bcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a CompileFilter that represents the maximal set of targets that should be
|
|
||||||
/// considered for scraping. Should be a subset of the CLI-provided CompileFilter.
|
|
||||||
fn filter_for_scrape_units(
|
|
||||||
to_builds: &[&Package],
|
|
||||||
has_dev_units: HasDevUnits,
|
|
||||||
filter: &CompileFilter,
|
|
||||||
) -> CompileFilter {
|
|
||||||
let no_pkg_has_dev_deps = to_builds.iter().all(|pkg| {
|
|
||||||
pkg.summary()
|
|
||||||
.dependencies()
|
|
||||||
.iter()
|
|
||||||
.all(|dep| !matches!(dep.kind(), DepKind::Development))
|
|
||||||
});
|
|
||||||
|
|
||||||
// We are allowed to include examples ONLY if they cannot possibly require dev dependencies,
|
|
||||||
// or if dev dependencies are already required anyway due to the user's configuration.
|
|
||||||
let example_filter = if matches!(has_dev_units, HasDevUnits::Yes) || no_pkg_has_dev_deps {
|
|
||||||
FilterRule::All
|
|
||||||
} else {
|
|
||||||
FilterRule::none()
|
|
||||||
};
|
|
||||||
|
|
||||||
match filter {
|
|
||||||
CompileFilter::Only {
|
|
||||||
all_targets,
|
|
||||||
lib,
|
|
||||||
bins,
|
|
||||||
tests,
|
|
||||||
benches,
|
|
||||||
..
|
|
||||||
} => CompileFilter::Only {
|
|
||||||
all_targets: *all_targets,
|
|
||||||
lib: lib.clone(),
|
|
||||||
bins: bins.clone(),
|
|
||||||
examples: example_filter,
|
|
||||||
tests: tests.clone(),
|
|
||||||
benches: benches.clone(),
|
|
||||||
},
|
|
||||||
|
|
||||||
CompileFilter::Default { .. } => CompileFilter::Only {
|
|
||||||
all_targets: false,
|
|
||||||
lib: LibRule::Default,
|
|
||||||
bins: FilterRule::none(),
|
|
||||||
examples: example_filter,
|
|
||||||
tests: FilterRule::none(),
|
|
||||||
benches: FilterRule::none(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A proposed target.
|
/// A proposed target.
|
||||||
///
|
///
|
||||||
/// Proposed targets are later filtered into actual `Unit`s based on whether or
|
/// Proposed targets are later filtered into actual `Unit`s based on whether or
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//! Tests for the `cargo doc` command.
|
//! Tests for the `cargo doc` command with `-Zrustdoc-scrape-examples`.
|
||||||
|
|
||||||
use cargo_test_support::is_nightly;
|
|
||||||
use cargo_test_support::project;
|
use cargo_test_support::project;
|
||||||
|
|
||||||
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
||||||
@ -41,11 +40,6 @@ fn basic() {
|
|||||||
|
|
||||||
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
||||||
fn avoid_build_script_cycle() {
|
fn avoid_build_script_cycle() {
|
||||||
if !is_nightly() {
|
|
||||||
// -Z rustdoc-scrape-examples is unstable
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let p = project()
|
let p = project()
|
||||||
// package with build dependency
|
// package with build dependency
|
||||||
.file(
|
.file(
|
||||||
@ -81,7 +75,7 @@ fn avoid_build_script_cycle() {
|
|||||||
.file("bar/build.rs", "fn main(){}")
|
.file("bar/build.rs", "fn main(){}")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
p.cargo("doc --all -Zunstable-options -Zrustdoc-scrape-examples")
|
p.cargo("doc --workspace -Zunstable-options -Zrustdoc-scrape-examples")
|
||||||
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -138,7 +132,7 @@ fn complex_reverse_dependencies() {
|
|||||||
.file("b/src/lib.rs", "")
|
.file("b/src/lib.rs", "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
p.cargo("doc --all --examples -Zunstable-options -Zrustdoc-scrape-examples")
|
p.cargo("doc --workspace --examples -Zunstable-options -Zrustdoc-scrape-examples")
|
||||||
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -208,7 +202,7 @@ fn configure_target() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
||||||
fn configure_profile() {
|
fn configure_profile_issue_10500() {
|
||||||
let p = project()
|
let p = project()
|
||||||
.file(
|
.file(
|
||||||
"Cargo.toml",
|
"Cargo.toml",
|
||||||
@ -277,7 +271,7 @@ fn issue_10545() {
|
|||||||
.file("b/src/lib.rs", "")
|
.file("b/src/lib.rs", "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
p.cargo("doc --all -Zunstable-options -Zrustdoc-scrape-examples")
|
p.cargo("doc --workspace -Zunstable-options -Zrustdoc-scrape-examples")
|
||||||
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
.masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -412,6 +406,10 @@ error: expected one of `!` or `::`, found `NOT`
|
|||||||
|
|
||||||
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
|
||||||
fn no_scrape_with_dev_deps() {
|
fn no_scrape_with_dev_deps() {
|
||||||
|
// Tests that a crate with dev-dependencies does not have its examples
|
||||||
|
// scraped unless explicitly prompted to check them. See
|
||||||
|
// `CompileFilter::refine_for_docscrape` for details on why.
|
||||||
|
|
||||||
let p = project()
|
let p = project()
|
||||||
.file(
|
.file(
|
||||||
"Cargo.toml",
|
"Cargo.toml",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user