rustdoc: Extract AttributesExt::cfg trait method as function
It's never overridden, so it shouldn't be on the trait.
This commit is contained in:
parent
e7ad3ae331
commit
e2fcdb8d36
4 changed files with 85 additions and 80 deletions
|
|
@ -17,12 +17,12 @@ use rustc_span::symbol::{Symbol, sym};
|
|||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use super::Item;
|
||||
use super::{Item, extract_cfg_from_attrs};
|
||||
use crate::clean::{
|
||||
self, Attributes, AttributesExt, ImplKind, ItemId, Type, clean_bound_vars, clean_generics,
|
||||
clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty,
|
||||
clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type,
|
||||
clean_ty_generics, clean_variant_def, utils,
|
||||
self, Attributes, ImplKind, ItemId, Type, clean_bound_vars, clean_generics, clean_impl_item,
|
||||
clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_poly_fn_sig,
|
||||
clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type, clean_ty_generics,
|
||||
clean_variant_def, utils,
|
||||
};
|
||||
use crate::core::DocContext;
|
||||
use crate::formats::item_type::ItemType;
|
||||
|
|
@ -408,10 +408,13 @@ pub(crate) fn merge_attrs(
|
|||
} else {
|
||||
Attributes::from_hir(&both)
|
||||
},
|
||||
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(&both[..], cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(Attributes::from_hir(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
(
|
||||
Attributes::from_hir(old_attrs),
|
||||
extract_cfg_from_attrs(&old_attrs[..], cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ fn generate_item_with_correct_attrs(
|
|||
target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
|
||||
};
|
||||
|
||||
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
|
||||
let cfg = extract_cfg_from_attrs(&attrs[..], cx.tcx, &cx.cache.hidden_cfg);
|
||||
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
|
||||
let name = renamed.or(Some(name));
|
||||
|
|
|
|||
|
|
@ -479,7 +479,7 @@ impl Item {
|
|||
name,
|
||||
kind,
|
||||
Attributes::from_hir(hir_attrs),
|
||||
hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(hir_attrs, cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -990,95 +990,98 @@ pub(crate) trait AttributesExt {
|
|||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_>;
|
||||
|
||||
fn iter(&self) -> Self::Attributes<'_>;
|
||||
}
|
||||
|
||||
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
|
||||
let sess = tcx.sess;
|
||||
let doc_cfg_active = tcx.features().doc_cfg();
|
||||
let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
|
||||
pub fn extract_cfg_from_attrs<A: AttributesExt + ?Sized>(
|
||||
attrs: &A,
|
||||
tcx: TyCtxt<'_>,
|
||||
hidden_cfg: &FxHashSet<Cfg>,
|
||||
) -> Option<Arc<Cfg>> {
|
||||
let sess = tcx.sess;
|
||||
let doc_cfg_active = tcx.features().doc_cfg();
|
||||
let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
|
||||
|
||||
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
|
||||
let mut iter = it.into_iter();
|
||||
let item = iter.next()?;
|
||||
if iter.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
Some(item)
|
||||
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
|
||||
let mut iter = it.into_iter();
|
||||
let item = iter.next()?;
|
||||
if iter.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
Some(item)
|
||||
}
|
||||
|
||||
let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
|
||||
let mut doc_cfg = self
|
||||
let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
|
||||
let mut doc_cfg = attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
|
||||
.filter(|attr| attr.has_name(sym::cfg))
|
||||
.peekable();
|
||||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||
doc_cfg
|
||||
.filter_map(|attr| Cfg::parse(&attr).ok())
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else if doc_auto_cfg_active {
|
||||
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
|
||||
// `doc(cfg())` overrides `cfg()`).
|
||||
attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
|
||||
.filter(|attr| attr.has_name(sym::cfg))
|
||||
.peekable();
|
||||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||
doc_cfg
|
||||
.filter_map(|attr| Cfg::parse(&attr).ok())
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else if doc_auto_cfg_active {
|
||||
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
|
||||
// `doc(cfg())` overrides `cfg()`).
|
||||
self.iter()
|
||||
.filter(|attr| attr.has_name(sym::cfg))
|
||||
.filter_map(|attr| single(attr.meta_item_list()?))
|
||||
.filter_map(|attr| {
|
||||
Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()
|
||||
})
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else {
|
||||
Cfg::True
|
||||
}
|
||||
.filter_map(|attr| single(attr.meta_item_list()?))
|
||||
.filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else {
|
||||
Cfg::True
|
||||
};
|
||||
}
|
||||
} else {
|
||||
Cfg::True
|
||||
};
|
||||
|
||||
for attr in self.iter() {
|
||||
// #[doc]
|
||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||
// #[doc(...)]
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list {
|
||||
// #[doc(hidden)]
|
||||
if !item.has_name(sym::cfg) {
|
||||
continue;
|
||||
}
|
||||
// #[doc(cfg(...))]
|
||||
if let Some(cfg_mi) = item
|
||||
.meta_item()
|
||||
.and_then(|item| rustc_expand::config::parse_cfg(item, sess))
|
||||
{
|
||||
match Cfg::parse(cfg_mi) {
|
||||
Ok(new_cfg) => cfg &= new_cfg,
|
||||
Err(e) => {
|
||||
sess.dcx().span_err(e.span, e.msg);
|
||||
}
|
||||
for attr in attrs.iter() {
|
||||
// #[doc]
|
||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||
// #[doc(...)]
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list {
|
||||
// #[doc(hidden)]
|
||||
if !item.has_name(sym::cfg) {
|
||||
continue;
|
||||
}
|
||||
// #[doc(cfg(...))]
|
||||
if let Some(cfg_mi) = item
|
||||
.meta_item()
|
||||
.and_then(|item| rustc_expand::config::parse_cfg(item, sess))
|
||||
{
|
||||
match Cfg::parse(cfg_mi) {
|
||||
Ok(new_cfg) => cfg &= new_cfg,
|
||||
Err(e) => {
|
||||
sess.dcx().span_err(e.span, e.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// treat #[target_feature(enable = "feat")] attributes as if they were
|
||||
// #[doc(cfg(target_feature = "feat"))] attributes as well
|
||||
for attr in self.lists(sym::target_feature) {
|
||||
if attr.has_name(sym::enable) {
|
||||
if attr.value_str().is_some() {
|
||||
// Clone `enable = "feat"`, change to `target_feature = "feat"`.
|
||||
// Unwrap is safe because `value_str` succeeded above.
|
||||
let mut meta = attr.meta_item().unwrap().clone();
|
||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
||||
// treat #[target_feature(enable = "feat")] attributes as if they were
|
||||
// #[doc(cfg(target_feature = "feat"))] attributes as well
|
||||
for attr in attrs.lists(sym::target_feature) {
|
||||
if attr.has_name(sym::enable) {
|
||||
if attr.value_str().is_some() {
|
||||
// Clone `enable = "feat"`, change to `target_feature = "feat"`.
|
||||
// Unwrap is safe because `value_str` succeeded above.
|
||||
let mut meta = attr.meta_item().unwrap().clone();
|
||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
||||
|
||||
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
|
||||
cfg &= feat_cfg;
|
||||
}
|
||||
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
|
||||
cfg &= feat_cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
|
||||
}
|
||||
|
||||
if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
|
||||
}
|
||||
|
||||
impl AttributesExt for [hir::Attribute] {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ use rustc_span::source_map::SourceMap;
|
|||
use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span};
|
||||
|
||||
use super::{DocTestVisitor, ScrapedDocTest};
|
||||
use crate::clean::Attributes;
|
||||
use crate::clean::types::AttributesExt;
|
||||
use crate::clean::{Attributes, extract_cfg_from_attrs};
|
||||
use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine};
|
||||
|
||||
struct RustCollector {
|
||||
|
|
@ -97,7 +96,7 @@ impl HirCollector<'_> {
|
|||
nested: F,
|
||||
) {
|
||||
let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
|
||||
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
|
||||
if let Some(ref cfg) = extract_cfg_from_attrs(ast_attrs, self.tcx, &FxHashSet::default()) {
|
||||
if !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features())) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue