Skip to content

Doc specific features #7726

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

Closed
Closed
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
2 changes: 2 additions & 0 deletions src/bin/cargo/commands/doc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::command_prelude::*;

use cargo::ops::{self, DocOptions};
use cargo::util;

pub fn cli() -> App {
subcommand("doc")
Expand Down Expand Up @@ -56,6 +57,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
let mut compile_opts =
args.compile_options(config, mode, Some(&ws), ProfileChecking::Checked)?;
compile_opts.rustdoc_document_private_items = args.is_present("document-private-items");
util::get_features_for("doc", &mut compile_opts, &ws)?;

let doc_opts = DocOptions {
open_result: args.is_present("open"),
Expand Down
58 changes: 58 additions & 0 deletions src/cargo/util/build_specific.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::core::Workspace;
use crate::ops::CompileOptions;
use crate::util::{CliError, CliResult};

use failure;
use toml::Value;

/// Check if specific features are available under `[package.metadata.X]` (`X`
/// being one of the supported types).
///
/// For now, it only supports it for "doc" build.
pub fn get_features_for(
r#for: &str,
compile_opts: &mut CompileOptions<'_>,
ws: &Workspace<'_>,
) -> CliResult {
match r#for {
"doc" => {} // If other features-specific kind are added, they should be put here.
_ => return Ok(()),
}
let packages = match compile_opts.spec.get_packages(ws) {
Ok(p) => p,
_ => return Ok(()),
};
for package in packages {
if let Some(Value::Table(ref metadata)) = package.manifest().custom_metadata() {
if let Some(ref doc) = metadata.get(r#for) {
match doc.get("features") {
Some(Value::Array(ref features)) => {
let mut additional_features = Vec::with_capacity(2);

for feature in features.iter() {
if let Value::String(s) = feature {
additional_features.push(s.clone());
} else {
Err(CliError::new(
failure::format_err!(
"Only strings are allowed in `features` array"
),
1,
))?
}
}
compile_opts
.features
.extend(additional_features.into_iter());
}
Some(_) => Err(CliError::new(
failure::format_err!("`features` should be an array"),
1,
))?,
None => {}
}
}
}
}
Ok(())
}
2 changes: 2 additions & 0 deletions src/cargo/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::time::Duration;

pub use self::build_specific::get_features_for;
pub use self::canonical_url::CanonicalUrl;
pub use self::config::{homedir, Config, ConfigValue};
pub use self::dependency_queue::DependencyQueue;
Expand Down Expand Up @@ -28,6 +29,7 @@ pub use self::workspace::{
print_available_tests,
};

pub mod build_specific;
mod canonical_url;
pub mod command_prelude;
pub mod config;
Expand Down
144 changes: 144 additions & 0 deletions tests/testsuite/doc_features_specific.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! Tests for "doc"-specific features.

use cargo_test_support::project;

#[cargo_test]
fn bad1() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []

[package.metadata.doc]
features = "foo"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("doc -v")
.with_status(1)
.with_stderr("error: `features` should be an array")
.run();
}

#[cargo_test]
fn bad2() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []

[package.metadata.doc]
features = [12]
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("doc -v")
.with_status(1)
.with_stderr("error: Only strings are allowed in `features` array")
.run();
}

#[cargo_test]
fn bad3() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []

[package.metadata.doc]
features = ["foo"]
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("doc -v")
.with_status(101)
.with_stderr(
"error: Package `foo v0.1.0 ([..])` does not \
have these features: `foo`",
)
.run();
}

#[cargo_test]
fn success() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []

[features]
foo = []

[package.metadata.doc]
features = ["foo"]
"#,
)
.file(
"src/lib.rs",
r#"
#[cfg(feature = "foo")]
compile_error!("foo is crazy!");
"#,
)
.build();
p.cargo("doc -v")
.with_status(101)
.with_stderr_contains(
"\
3 | compile_error!(\"foo is crazy!\");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Compilation failed, aborting rustdoc

error: aborting due to 2 previous errors",
)
.run();
}

#[cargo_test]
fn success2() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.0"
authors = []

[features]
foo = []

[package.metadata.doc]
features = ["foo"]
"#,
)
.file(
"src/lib.rs",
r#"
#[cfg(feature = "foo")]
compile_error!("foo is crazy!");
"#,
)
.build();
p.cargo("build -v").with_status(0).run();
}
1 change: 1 addition & 0 deletions tests/testsuite/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mod death;
mod dep_info;
mod directory;
mod doc;
mod doc_features_specific;
mod edition;
mod features;
mod fetch;
Expand Down