1
Fork 0

Unify rustc and rustdoc parsing of cfg()

This extracts a new `parse_cfg` function that's used between both.

- Treat `#[doc(cfg(x), cfg(y))]` the same as `#[doc(cfg(x)]
  #[doc(cfg(y))]`. Previously it would be completely ignored.
- Treat `#[doc(inline, cfg(x))]` the same as `#[doc(inline)]
  #[doc(cfg(x))]`. Previously, the cfg would be ignored.
- Pass the cfg predicate through to rustc_expand to be validated

Co-authored-by: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
This commit is contained in:
Joshua Nelson 2021-04-22 13:28:43 -04:00
parent 78c963945a
commit 6eb4735acc
10 changed files with 82 additions and 64 deletions

View file

@ -464,31 +464,9 @@ impl<'a> StripUnconfigured<'a> {
return true;
}
};
let error = |span, msg, suggestion: &str| {
let mut err = self.sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
if !suggestion.is_empty() {
err.span_suggestion(
span,
"expected syntax is",
suggestion.into(),
Applicability::MaybeIncorrect,
);
}
err.emit();
true
};
let span = meta_item.span;
match meta_item.meta_item_list() {
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
Some([]) => error(span, "`cfg` predicate is not specified", ""),
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
Some([single]) => match single.meta_item() {
Some(meta_item) => {
attr::cfg_matches(meta_item, &self.sess.parse_sess, self.features)
}
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
},
}
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
})
})
}
@ -532,6 +510,32 @@ impl<'a> StripUnconfigured<'a> {
}
}
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
let error = |span, msg, suggestion: &str| {
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
if !suggestion.is_empty() {
err.span_suggestion(
span,
"expected syntax is",
suggestion.into(),
Applicability::HasPlaceholders,
);
}
err.emit();
None
};
let span = meta_item.span;
match meta_item.meta_item_list() {
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
Some([]) => error(span, "`cfg` predicate is not specified", ""),
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
Some([single]) => match single.meta_item() {
Some(meta_item) => Some(meta_item),
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
},
}
}
fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
sess.check_name(attr, sym::cfg)
}