expand: Leave traces when expanding cfg_attr
attributes
This commit is contained in:
parent
9bad8ac498
commit
9dd4e4cad1
10 changed files with 136 additions and 19 deletions
|
@ -1,12 +1,15 @@
|
|||
//! Conditional compilation stripping.
|
||||
|
||||
use std::iter;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{
|
||||
AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
|
||||
};
|
||||
use rustc_ast::{
|
||||
self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId,
|
||||
self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner,
|
||||
NodeId, NormalAttr,
|
||||
};
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
|
@ -275,10 +278,23 @@ impl<'a> StripUnconfigured<'a> {
|
|||
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
|
||||
validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr);
|
||||
|
||||
// A trace attribute left in AST in place of the original `cfg_attr` attribute.
|
||||
// It can later be used by lints or other diagnostics.
|
||||
let mut trace_attr = cfg_attr.clone();
|
||||
match &mut trace_attr.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
let NormalAttr { item, tokens } = &mut **normal;
|
||||
item.path.segments[0].ident.name = sym::cfg_attr_trace;
|
||||
// This makes the trace attributes unobservable to token-based proc macros.
|
||||
*tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
|
||||
}
|
||||
AttrKind::DocComment(..) => unreachable!(),
|
||||
}
|
||||
|
||||
let Some((cfg_predicate, expanded_attrs)) =
|
||||
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
|
||||
else {
|
||||
return vec![];
|
||||
return vec![trace_attr];
|
||||
};
|
||||
|
||||
// Lint on zero attributes in source.
|
||||
|
@ -292,22 +308,21 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
|
||||
if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
|
||||
return vec![];
|
||||
return vec![trace_attr];
|
||||
}
|
||||
|
||||
if recursive {
|
||||
// We call `process_cfg_attr` recursively in case there's a
|
||||
// `cfg_attr` inside of another `cfg_attr`. E.g.
|
||||
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
|
||||
expanded_attrs
|
||||
let expanded_attrs = expanded_attrs
|
||||
.into_iter()
|
||||
.flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item)))
|
||||
.collect()
|
||||
.flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item)));
|
||||
iter::once(trace_attr).chain(expanded_attrs).collect()
|
||||
} else {
|
||||
expanded_attrs
|
||||
.into_iter()
|
||||
.map(|item| self.expand_cfg_attr_item(cfg_attr, item))
|
||||
.collect()
|
||||
let expanded_attrs =
|
||||
expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(cfg_attr, item));
|
||||
iter::once(trace_attr).chain(expanded_attrs).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue