Skip to content

Commit e7d5853

Browse files
author
Ojus Chugh
committed
Respect public-dependency when documenting deps
Fixes #2025 When the public-dependency feature is enabled, cargo doc now only documents direct dependencies and their public dependencies recursively. This reduces documentation clutter by excluding transitive private dependencies that users don't need to know about. Behavior: - Without public-dependency: all deps documented (backward compatible) - With public-dependency enabled: * Direct dependencies always documented * Transitive deps only if marked public This allows library authors to control their documentation surface by marking which dependencies are part of their public API.
1 parent 172fb93 commit e7d5853

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,17 @@ fn compute_deps_doc(
637637
// built. If we're documenting *all* libraries, then we also depend on
638638
// the documentation of the library being built.
639639
let mut ret = Vec::new();
640+
let is_root = state.ws.is_member(&unit.pkg);
641+
642+
// Check if public-dependency feature is enabled
643+
let public_dep = state.gctx.cli_unstable().public_dependency
644+
|| unit
645+
.pkg
646+
.manifest()
647+
.unstable_features()
648+
.require(Feature::public_dependency())
649+
.is_ok();
650+
640651
for (id, deps) in state.deps(unit, unit_for) {
641652
let Some(dep_lib) = calc_artifact_deps(unit, unit_for, id, &deps, state, &mut ret)? else {
642653
continue;
@@ -657,7 +668,20 @@ fn compute_deps_doc(
657668
IS_NO_ARTIFACT_DEP,
658669
)?;
659670
ret.push(lib_unit_dep);
660-
if dep_lib.documented() && state.intent.wants_deps_docs() {
671+
672+
// Decide whether to document this dependency.
673+
// When public-dependency is enabled, only document:
674+
// - Direct dependencies of workspace members
675+
// - Public dependencies (recursively)
676+
let should_doc = dep_lib.documented() && state.intent.wants_deps_docs() && {
677+
if public_dep {
678+
is_root || state.resolve().is_public_dep(unit.pkg.package_id(), id)
679+
} else {
680+
true
681+
}
682+
};
683+
684+
if should_doc {
661685
// Document this lib as well.
662686
let doc_unit_dep = new_unit_dep(
663687
state,

tests/testsuite/doc_direct_deps.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,18 @@ fn doc_direct_deps_only() {
6060
assert!(p.root().join("target/doc/baz/index.html").is_file());
6161
}
6262

63-
6463
#[cargo_test(nightly, reason = "public-dependency feature is unstable")]
6564
fn doc_with_public_dependency_feature() {
6665
// foo -> bar (public) -> baz (public)
6766
// baz should be documented since bar marks it as public
68-
67+
6968
Package::new("baz", "0.0.1")
7069
.file("src/lib.rs", "pub fn baz() {}")
7170
.publish();
7271

7372
Package::new("bar", "0.0.1")
7473
.cargo_feature("public-dependency")
75-
.add_dep(
76-
cargo_test_support::registry::Dependency::new("baz", "0.0.1").public(true)
77-
)
74+
.add_dep(cargo_test_support::registry::Dependency::new("baz", "0.0.1").public(true))
7875
.file("src/lib.rs", "extern crate baz; pub fn bar() {}")
7976
.publish();
8077

@@ -128,7 +125,7 @@ fn doc_with_public_dependency_feature() {
128125
fn doc_with_private_dependency() {
129126
// foo -> bar (private) -> baz
130127
// baz should NOT be documented (transitive private dep)
131-
128+
132129
Package::new("baz", "0.0.1")
133130
.file("src/lib.rs", "pub fn baz() {}")
134131
.publish();
@@ -201,7 +198,10 @@ fn doc_mixed_public_private_deps() {
201198

202199
Package::new("priv_dep_with_dep", "0.0.1")
203200
.dep("transitive", "0.0.1")
204-
.file("src/lib.rs", "extern crate transitive; pub fn priv_dep_with_dep() {}")
201+
.file(
202+
"src/lib.rs",
203+
"extern crate transitive; pub fn priv_dep_with_dep() {}",
204+
)
205205
.publish();
206206

207207
let p = project()
@@ -235,8 +235,12 @@ fn doc_mixed_public_private_deps() {
235235
assert!(p.root().join("target/doc/foo/index.html").is_file());
236236
assert!(p.root().join("target/doc/pub_dep/index.html").is_file());
237237
assert!(p.root().join("target/doc/priv_dep/index.html").is_file());
238-
assert!(p.root().join("target/doc/priv_dep_with_dep/index.html").is_file());
239-
238+
assert!(
239+
p.root()
240+
.join("target/doc/priv_dep_with_dep/index.html")
241+
.is_file()
242+
);
243+
240244
// transitive should NOT be documented
241245
assert!(!p.root().join("target/doc/transitive/index.html").is_file());
242246
}

0 commit comments

Comments
 (0)