Make cfg implicitly imply doc(cfg)
This is only active when the `doc_cfg` feature is active. The implicit cfg can be overridden via #[doc(cfg(...))], so e.g. to hide a #[cfg] you can use something like: ```rust #[cfg(unix)] #[doc(cfg(all()))] pub struct Unix; ``` (since `all()` is always true, it is never shown in the docs)
This commit is contained in:
parent
074f63648b
commit
10cdbd847f
8 changed files with 92 additions and 9 deletions
|
@ -318,10 +318,10 @@ fn merge_attrs(
|
||||||
} else {
|
} else {
|
||||||
Attributes::from_ast(&both, None)
|
Attributes::from_ast(&both, None)
|
||||||
},
|
},
|
||||||
both.cfg(cx.sess()),
|
both.cfg(cx.tcx),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(old_attrs.clean(cx), old_attrs.cfg(cx.sess()))
|
(old_attrs.clean(cx), old_attrs.cfg(cx.tcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1973,7 +1973,7 @@ fn clean_extern_crate(
|
||||||
def_id: crate_def_id.into(),
|
def_id: crate_def_id.into(),
|
||||||
visibility: krate.vis.clean(cx),
|
visibility: krate.vis.clean(cx),
|
||||||
kind: box ExternCrateItem { src: orig_name },
|
kind: box ExternCrateItem { src: orig_name },
|
||||||
cfg: attrs.cfg(cx.sess()),
|
cfg: attrs.cfg(cx.tcx),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -421,7 +421,7 @@ impl Item {
|
||||||
kind,
|
kind,
|
||||||
box ast_attrs.clean(cx),
|
box ast_attrs.clean(cx),
|
||||||
cx,
|
cx,
|
||||||
ast_attrs.cfg(cx.sess()),
|
ast_attrs.cfg(cx.tcx),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,7 +747,7 @@ crate trait AttributesExt {
|
||||||
|
|
||||||
fn other_attrs(&self) -> Vec<ast::Attribute>;
|
fn other_attrs(&self) -> Vec<ast::Attribute>;
|
||||||
|
|
||||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
|
fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributesExt for [ast::Attribute] {
|
impl AttributesExt for [ast::Attribute] {
|
||||||
|
@ -772,8 +772,52 @@ impl AttributesExt for [ast::Attribute] {
|
||||||
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
|
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
|
fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>> {
|
||||||
let mut cfg = Cfg::True;
|
let sess = tcx.sess;
|
||||||
|
let doc_cfg_active = tcx.features().doc_cfg;
|
||||||
|
|
||||||
|
trait SingleExt {
|
||||||
|
type Item;
|
||||||
|
fn single(self) -> Option<Self::Item>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IntoIterator> SingleExt for T {
|
||||||
|
type Item = T::Item;
|
||||||
|
fn single(self) -> Option<Self::Item> {
|
||||||
|
let mut iter = self.into_iter();
|
||||||
|
let item = iter.next()?;
|
||||||
|
iter.next().is_none().then_some(())?;
|
||||||
|
Some(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cfg = if doc_cfg_active {
|
||||||
|
let mut doc_cfg = self
|
||||||
|
.iter()
|
||||||
|
.filter(|attr| attr.has_name(sym::doc))
|
||||||
|
.filter_map(|attr| Some(attr.meta_item_list()?.single()?))
|
||||||
|
.filter(|attr| attr.has_name(sym::cfg))
|
||||||
|
.filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
|
||||||
|
.peekable();
|
||||||
|
if doc_cfg.peek().is_some() {
|
||||||
|
doc_cfg
|
||||||
|
.filter_map(|attr| {
|
||||||
|
Cfg::parse(&attr).map_err(|e| sess.diagnostic().span_err(e.span, e.msg)).ok()
|
||||||
|
})
|
||||||
|
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
.iter()
|
||||||
|
.filter(|attr| attr.has_name(sym::cfg))
|
||||||
|
.filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
|
||||||
|
.filter_map(|attr| {
|
||||||
|
Cfg::parse(&attr).map_err(|e| sess.diagnostic().span_err(e.span, e.msg)).ok()
|
||||||
|
})
|
||||||
|
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Cfg::True
|
||||||
|
};
|
||||||
|
|
||||||
for attr in self.iter() {
|
for attr in self.iter() {
|
||||||
// #[doc]
|
// #[doc]
|
||||||
|
|
|
@ -1123,7 +1123,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
|
||||||
let ast_attrs = self.tcx.hir().attrs(hir_id);
|
let ast_attrs = self.tcx.hir().attrs(hir_id);
|
||||||
let mut attrs = Attributes::from_ast(ast_attrs, None);
|
let mut attrs = Attributes::from_ast(ast_attrs, None);
|
||||||
|
|
||||||
if let Some(ref cfg) = ast_attrs.cfg(self.sess) {
|
if let Some(ref cfg) = ast_attrs.cfg(self.tcx) {
|
||||||
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||||
let import_item = clean::Item {
|
let import_item = clean::Item {
|
||||||
def_id: import_def_id.into(),
|
def_id: import_def_id.into(),
|
||||||
attrs: import_attrs,
|
attrs: import_attrs,
|
||||||
cfg: ast_attrs.cfg(cx.sess()),
|
cfg: ast_attrs.cfg(cx.tcx()),
|
||||||
..myitem.clone()
|
..myitem.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(array_methods)]
|
#![feature(array_methods)]
|
||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
7
src/test/rustdoc/doc-cfg-implicit-gate.rs
Normal file
7
src/test/rustdoc/doc-cfg-implicit-gate.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// compile-flags:--cfg feature="worricow"
|
||||||
|
#![crate_name = "xenogenous"]
|
||||||
|
|
||||||
|
// @has 'xenogenous/struct.Worricow.html'
|
||||||
|
// @count - '//*[@class="stab portability"]' 0
|
||||||
|
#[cfg(feature = "worricow")]
|
||||||
|
pub struct Worricow;
|
31
src/test/rustdoc/doc-cfg-implicit.rs
Normal file
31
src/test/rustdoc/doc-cfg-implicit.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#![crate_name = "funambulism"]
|
||||||
|
#![feature(doc_cfg)]
|
||||||
|
|
||||||
|
// @has 'funambulism/struct.Disorbed.html'
|
||||||
|
// @count - '//*[@class="stab portability"]' 1
|
||||||
|
// @matches - '//*[@class="stab portability"]' 'crate feature disorbed'
|
||||||
|
// compile-flags:--cfg feature="disorbed"
|
||||||
|
#[cfg(feature = "disorbed")]
|
||||||
|
pub struct Disorbed;
|
||||||
|
|
||||||
|
// @has 'funambulism/struct.Aesthesia.html'
|
||||||
|
// @count - '//*[@class="stab portability"]' 1
|
||||||
|
// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia'
|
||||||
|
// compile-flags:--cfg feature="aesthesia"
|
||||||
|
#[doc(cfg(feature = "aesthesia"))]
|
||||||
|
pub struct Aesthesia;
|
||||||
|
|
||||||
|
// @has 'funambulism/struct.Pliothermic.html'
|
||||||
|
// @count - '//*[@class="stab portability"]' 1
|
||||||
|
// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic'
|
||||||
|
// compile-flags:--cfg feature="epopoeist"
|
||||||
|
#[cfg(feature = "epopoeist")]
|
||||||
|
#[doc(cfg(feature = "pliothermic"))]
|
||||||
|
pub struct Pliothermic;
|
||||||
|
|
||||||
|
// @has 'funambulism/struct.Simillimum.html'
|
||||||
|
// @count - '//*[@class="stab portability"]' 0
|
||||||
|
// compile-flags:--cfg feature="simillimum"
|
||||||
|
#[cfg(feature = "simillimum")]
|
||||||
|
#[doc(cfg(all()))]
|
||||||
|
pub struct Simillimum;
|
Loading…
Add table
Add a link
Reference in a new issue