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

use std::slice;

use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{
    self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, NodeId,
    Path, Safety,
};
use rustc_attr_parsing::{AttributeParser, Late};
use rustc_errors::{Applicability, DiagCtxtHandle, FatalError, PResult};
use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
use rustc_session::errors::report_lit_error;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE};
use rustc_session::parse::ParseSess;
use rustc_span::{Span, Symbol, sym};

use crate::{errors, parse_in};

pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) {
    if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
    {
        return;
    }

    let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));

    let builtin_attr_safety = builtin_attr_info.map(|x| x.safety);
    check_attribute_safety(psess, builtin_attr_safety, attr, id);

    // Check input tokens for built-in and key-value attributes.
    match builtin_attr_info {
        // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
        Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
            match parse_meta(psess, attr) {
                // Don't check safety again, we just did that
                Ok(meta) => {
                    check_builtin_meta_item(psess, &meta, attr.style, *name, *template, false)
                }
                Err(err) => {
                    err.emit();
                }
            }
        }
        _ => {
            let attr_item = attr.get_normal_item();
            if let AttrArgs::Eq { .. } = attr_item.args {
                // All key-value attributes are restricted to meta-item syntax.
                match parse_meta(psess, attr) {
                    Ok(_) => {}
                    Err(err) => {
                        err.emit();
                    }
                }
            }
        }
    }
}

pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
    let item = attr.get_normal_item();
    Ok(MetaItem {
        unsafety: item.unsafety,
        span: attr.span,
        path: item.path.clone(),
        kind: match &item.args {
            AttrArgs::Empty => MetaItemKind::Word,
            AttrArgs::Delimited(DelimArgs { dspan, delim, tokens }) => {
                check_meta_bad_delim(psess, *dspan, *delim);
                let nmis =
                    parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                MetaItemKind::List(nmis)
            }
            AttrArgs::Eq { expr, .. } => {
                if let ast::ExprKind::Lit(token_lit) = expr.kind {
                    let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
                    let res = match res {
                        Ok(lit) => {
                            if token_lit.suffix.is_some() {
                                let mut err = psess.dcx().struct_span_err(
                                    expr.span,
                                    "suffixed literals are not allowed in attributes",
                                );
                                err.help(
                                    "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
                                    use an unsuffixed version (`1`, `1.0`, etc.)",
                                );
                                return Err(err);
                            } else {
                                MetaItemKind::NameValue(lit)
                            }
                        }
                        Err(err) => {
                            let guar = report_lit_error(psess, err, token_lit, expr.span);
                            let lit = ast::MetaItemLit {
                                symbol: token_lit.symbol,
                                suffix: token_lit.suffix,
                                kind: ast::LitKind::Err(guar),
                                span: expr.span,
                            };
                            MetaItemKind::NameValue(lit)
                        }
                    };
                    res
                } else {
                    // Example cases:
                    // - `#[foo = 1+1]`: results in `ast::ExprKind::Binary`.
                    // - `#[foo = include_str!("nonexistent-file.rs")]`:
                    //   results in `ast::ExprKind::Err`. In that case we delay
                    //   the error because an earlier error will have already
                    //   been reported.
                    let msg = "attribute value must be a literal";
                    let mut err = psess.dcx().struct_span_err(expr.span, msg);
                    if let ast::ExprKind::Err(_) = expr.kind {
                        err.downgrade_to_delayed_bug();
                    }
                    return Err(err);
                }
            }
        },
    })
}

fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
    if let Delimiter::Parenthesis = delim {
        return;
    }
    psess.dcx().emit_err(errors::MetaBadDelim {
        span: span.entire(),
        sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
    });
}

pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
    if let Delimiter::Parenthesis = delim {
        return;
    }
    psess.dcx().emit_err(errors::CfgAttrBadDelim {
        span: span.entire(),
        sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
    });
}

/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
    let is_one_allowed_subword = |items: &[MetaItemInner]| match items {
        [item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)),
        _ => false,
    };
    match meta {
        MetaItemKind::Word => template.word,
        MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items),
        MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(),
        MetaItemKind::NameValue(..) => false,
    }
}

pub fn check_attribute_safety(
    psess: &ParseSess,
    builtin_attr_safety: Option<AttributeSafety>,
    attr: &Attribute,
    id: NodeId,
) {
    let attr_item = attr.get_normal_item();
    match (builtin_attr_safety, attr_item.unsafety) {
        // - Unsafe builtin attribute
        // - User wrote `#[unsafe(..)]`, which is permitted on any edition
        (Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => {
            // OK
        }

        // - Unsafe builtin attribute
        // - User did not write `#[unsafe(..)]`
        (Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => {
            let path_span = attr_item.path.span;

            // If the `attr_item`'s span is not from a macro, then just suggest
            // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
            // `unsafe(`, `)` right after and right before the opening and closing
            // square bracket respectively.
            let diag_span = attr_item.span();

            // Attributes can be safe in earlier editions, and become unsafe in later ones.
            //
            // Use the span of the attribute's name to determine the edition: the span of the
            // attribute as a whole may be inaccurate if it was emitted by a macro.
            //
            // See https://github.com/rust-lang/rust/issues/142182.
            let emit_error = match unsafe_since {
                None => true,
                Some(unsafe_since) => path_span.edition() >= unsafe_since,
            };

            if emit_error {
                psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
                    span: path_span,
                    suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
                        left: diag_span.shrink_to_lo(),
                        right: diag_span.shrink_to_hi(),
                    },
                });
            } else {
                psess.buffer_lint(
                    UNSAFE_ATTR_OUTSIDE_UNSAFE,
                    path_span,
                    id,
                    BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
                        attribute_name_span: path_span,
                        sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
                    },
                );
            }
        }

        // - Normal builtin attribute, or any non-builtin attribute
        // - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is
        //   not permitted on non-builtin attributes or normal builtin attributes
        (Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => {
            psess.dcx().emit_err(errors::InvalidAttrUnsafe {
                span: unsafe_span,
                name: attr_item.path.clone(),
            });
        }

        // - Normal builtin attribute
        // - No explicit `#[unsafe(..)]` written.
        (Some(AttributeSafety::Normal), Safety::Default) => {
            // OK
        }

        // - Non-builtin attribute
        // - No explicit `#[unsafe(..)]` written.
        (None, Safety::Default) => {
            // OK
        }

        (
            Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None,
            Safety::Safe(..),
        ) => {
            psess.dcx().span_delayed_bug(
                attr_item.span(),
                "`check_attribute_safety` does not expect `Safety::Safe` on attributes",
            );
        }
    }
}

// Called by `check_builtin_meta_item` and code that manually denies
// `unsafe(...)` in `cfg`
pub fn deny_builtin_meta_unsafety(diag: DiagCtxtHandle<'_>, unsafety: Safety, name: &Path) {
    // This only supports denying unsafety right now - making builtin attributes
    // support unsafety will requite us to thread the actual `Attribute` through
    // for the nice diagnostics.
    if let Safety::Unsafe(unsafe_span) = unsafety {
        diag.emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: name.clone() });
    }
}

pub fn check_builtin_meta_item(
    psess: &ParseSess,
    meta: &MetaItem,
    style: ast::AttrStyle,
    name: Symbol,
    template: AttributeTemplate,
    deny_unsafety: bool,
) {
    if !is_attr_template_compatible(&template, &meta.kind) {
        // attrs with new parsers are locally validated so excluded here
        if AttributeParser::<Late>::is_parsed_attribute(slice::from_ref(&name)) {
            return;
        }
        emit_malformed_attribute(psess, style, meta.span, name, template);
    }

    if deny_unsafety {
        deny_builtin_meta_unsafety(psess.dcx(), meta.unsafety, &meta.path);
    }
}

fn emit_malformed_attribute(
    psess: &ParseSess,
    style: ast::AttrStyle,
    span: Span,
    name: Symbol,
    template: AttributeTemplate,
) {
    // Some of previously accepted forms were used in practice,
    // report them as warnings for now.
    let should_warn = |name| matches!(name, sym::doc | sym::link | sym::test | sym::bench);

    let error_msg = format!("malformed `{name}` attribute input");
    let mut suggestions = vec![];
    let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
    if template.word {
        suggestions.push(format!("#{inner}[{name}]"));
    }
    if let Some(descr) = template.list {
        for descr in descr {
            suggestions.push(format!("#{inner}[{name}({descr})]"));
        }
    }
    suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
    if let Some(descr) = template.name_value_str {
        for descr in descr {
            suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
        }
    }
    if should_warn(name) {
        psess.buffer_lint(
            ILL_FORMED_ATTRIBUTE_INPUT,
            span,
            ast::CRATE_NODE_ID,
            BuiltinLintDiag::IllFormedAttributeInput {
                suggestions: suggestions.clone(),
                docs: template.docs,
            },
        );
    } else {
        suggestions.sort();
        let mut err = psess.dcx().struct_span_err(span, error_msg).with_span_suggestions(
            span,
            if suggestions.len() == 1 {
                "must be of the form"
            } else {
                "the following are the possible correct uses"
            },
            suggestions,
            Applicability::HasPlaceholders,
        );
        if let Some(link) = template.docs {
            err.note(format!("for more information, visit <{link}>"));
        }
        err.emit();
    }
}

pub fn emit_fatal_malformed_builtin_attribute(
    psess: &ParseSess,
    attr: &Attribute,
    name: Symbol,
) -> ! {
    let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
    emit_malformed_attribute(psess, 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()
}
