//! Meta-syntax validation logic of attributes for post-expansion.

use crate::parse_in;

use rustc_errors::{PResult, Applicability};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::attr::mk_name_value_item_str;
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
use syntax::tokenstream::DelimSpan;
use syntax::sess::ParseSess;
use syntax_pos::{Symbol, sym};

pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
    let attr_info =
        attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);

    // Check input tokens for built-in and key-value attributes.
    match attr_info {
        // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
        Some((name, _, template, _)) if name != sym::rustc_dummy =>
            check_builtin_attribute(sess, attr, name, template),
        _ => if let MacArgs::Eq(..) = attr.get_normal_item().args {
            // All key-value attributes are restricted to meta-item syntax.
            parse_meta(sess, attr).map_err(|mut err| err.emit()).ok();
        }
    }
}

pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
    Ok(match attr.kind {
        AttrKind::Normal(ref item) => MetaItem {
            span: attr.span,
            path: item.path.clone(),
            kind: match &attr.get_normal_item().args {
                MacArgs::Empty => MetaItemKind::Word,
                MacArgs::Eq(_, t) => {
                    let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
                    MetaItemKind::NameValue(v)
                }
                MacArgs::Delimited(dspan, delim, t) => {
                    check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
                    let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                    MetaItemKind::List(nmis)
                }
            }
        },
        AttrKind::DocComment(comment) => {
            mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
        }
    })
}

crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
    if let ast::MacDelimiter::Parenthesis = delim {
        return;
    }

    sess.span_diagnostic
        .struct_span_err(span.entire(), msg)
        .multipart_suggestion(
            "the delimiters should be `(` and `)`",
            vec![
                (span.open, "(".to_string()),
                (span.close, ")".to_string()),
            ],
            Applicability::MachineApplicable,
        )
        .emit();
}

/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
    match meta {
        MetaItemKind::Word => template.word,
        MetaItemKind::List(..) => template.list.is_some(),
        MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(),
        MetaItemKind::NameValue(..) => false,
    }
}

pub fn check_builtin_attribute(
    sess: &ParseSess,
    attr: &Attribute,
    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;
    // Some of previously accepted forms were used in practice,
    // report them as warnings for now.
    let should_warn = |name| name == sym::doc || name == sym::ignore ||
                             name == sym::inline || name == sym::link ||
                             name == sym::test || name == sym::bench;

    match parse_meta(sess, attr) {
        Ok(meta) => if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
            let error_msg = format!("malformed `{}` attribute input", name);
            let mut msg = "attribute must be of the form ".to_owned();
            let mut suggestions = vec![];
            let mut first = true;
            if template.word {
                first = false;
                let code = format!("#[{}]", name);
                msg.push_str(&format!("`{}`", &code));
                suggestions.push(code);
            }
            if let Some(descr) = template.list {
                if !first {
                    msg.push_str(" or ");
                }
                first = false;
                let code = format!("#[{}({})]", name, descr);
                msg.push_str(&format!("`{}`", &code));
                suggestions.push(code);
            }
            if let Some(descr) = template.name_value_str {
                if !first {
                    msg.push_str(" or ");
                }
                let code = format!("#[{} = \"{}\"]", name, descr);
                msg.push_str(&format!("`{}`", &code));
                suggestions.push(code);
            }
            if should_warn(name) {
                sess.buffer_lint(
                    &ILL_FORMED_ATTRIBUTE_INPUT,
                    meta.span,
                    ast::CRATE_NODE_ID,
                    &msg,
                );
            } else {
                sess.span_diagnostic.struct_span_err(meta.span, &error_msg)
                    .span_suggestions(
                        meta.span,
                        if suggestions.len() == 1 {
                            "must be of the form"
                        } else {
                            "the following are the possible correct uses"
                        },
                        suggestions.into_iter(),
                        Applicability::HasPlaceholders,
                    ).emit();
            }
        }
        Err(mut err) => err.emit(),
    }
}
