-use rustc_ast::{Attribute, MetaItem};
+use rustc_ast::{AttrStyle, Attribute, MetaItem};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_feature::AttributeTemplate;
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
// All the built-in macro attributes are "words" at the moment.
let template = AttributeTemplate { word: true, ..Default::default() };
- let attr = ecx.attribute(meta_item.clone());
- validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
+ validate_attr::check_builtin_meta_item(
+ &ecx.sess.parse_sess,
+ &meta_item,
+ AttrStyle::Outer,
+ name,
+ template,
+ );
}
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_session::parse::ParseSess;
-use rustc_span::{sym, Symbol};
+use rustc_span::{sym, Span, Symbol};
-pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
+pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
if attr.is_doc_comment() {
return;
}
name: Symbol,
template: AttributeTemplate,
) {
- // Some special attributes like `cfg` must be checked
- // before the generic check, so we skip them here.
- let should_skip = |name| name == sym::cfg;
-
match parse_meta(sess, attr) {
- Ok(meta) => {
- if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
- emit_malformed_attribute(sess, attr, name, template);
- }
- }
+ Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
Err(mut err) => {
err.emit();
}
}
}
+pub fn check_builtin_meta_item(
+ sess: &ParseSess,
+ meta: &MetaItem,
+ style: ast::AttrStyle,
+ name: Symbol,
+ template: AttributeTemplate,
+) {
+ // Some special attributes like `cfg` must be checked
+ // before the generic check, so we skip them here.
+ let should_skip = |name| name == sym::cfg;
+
+ if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
+ emit_malformed_attribute(sess, style, meta.span, name, template);
+ }
+}
+
fn emit_malformed_attribute(
sess: &ParseSess,
- attr: &Attribute,
+ style: ast::AttrStyle,
+ span: Span,
name: Symbol,
template: AttributeTemplate,
) {
let mut msg = "attribute must be of the form ".to_owned();
let mut suggestions = vec![];
let mut first = true;
- let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" };
+ let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
if template.word {
first = false;
let code = format!("#{}[{}]", inner, name);
suggestions.push(code);
}
if should_warn(name) {
- sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg);
+ sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
} else {
sess.span_diagnostic
- .struct_span_err(attr.span, &error_msg)
+ .struct_span_err(span, &error_msg)
.span_suggestions(
- attr.span,
+ span,
if suggestions.len() == 1 {
"must be of the form"
} else {
name: Symbol,
) -> ! {
let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
- emit_malformed_attribute(sess, attr, name, template);
+ emit_malformed_attribute(sess, attr.style, attr.span, name, template);
// This is fatal, otherwise it will likely cause a cascade of other errors
// (and an error here is expected to be very rare).
FatalError.raise()