//! This is in essence an (improved) duplicate of `rustc_ast/attr/mod.rs`.
//! That module is intended to be deleted in its entirety.
//!
//! FIXME(jdonszelmann): delete `rustc_ast/attr/mod.rs`

use std::borrow::Borrow;
use std::fmt::{Debug, Display};

use rustc_ast::token::{self, Delimiter, MetaVarKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, Path, StmtKind, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr};
use rustc_session::errors::{create_lit_error, report_lit_error};
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
use thin_vec::ThinVec;

use crate::ShouldEmit;
use crate::session_diagnostics::{
    InvalidMetaItem, InvalidMetaItemQuoteIdentSugg, InvalidMetaItemRemoveNegSugg, MetaBadDelim,
    MetaBadDelimSugg, SuffixedLiteralInAttribute,
};

#[derive(Clone, Debug)]
pub struct PathParser<P: Borrow<Path>>(pub P);

pub type OwnedPathParser = PathParser<Path>;
pub type RefPathParser<'p> = PathParser<&'p Path>;

impl<P: Borrow<Path>> PathParser<P> {
    pub fn get_attribute_path(&self) -> hir::AttrPath {
        AttrPath {
            segments: self.segments().copied().collect::<Vec<_>>().into_boxed_slice(),
            span: self.span(),
        }
    }

    pub fn segments(&self) -> impl Iterator<Item = &Ident> {
        self.0.borrow().segments.iter().map(|seg| &seg.ident)
    }

    pub fn span(&self) -> Span {
        self.0.borrow().span
    }

    pub fn len(&self) -> usize {
        self.0.borrow().segments.len()
    }

    pub fn segments_is(&self, segments: &[Symbol]) -> bool {
        self.segments().map(|segment| &segment.name).eq(segments)
    }

    pub fn word(&self) -> Option<Ident> {
        (self.len() == 1).then(|| **self.segments().next().as_ref().unwrap())
    }

    pub fn word_sym(&self) -> Option<Symbol> {
        self.word().map(|ident| ident.name)
    }

    /// Asserts that this MetaItem is some specific word.
    ///
    /// See [`word`](Self::word) for examples of what a word is.
    pub fn word_is(&self, sym: Symbol) -> bool {
        self.word().map(|i| i.name == sym).unwrap_or(false)
    }

    /// Checks whether the first segments match the givens.
    ///
    /// Unlike [`segments_is`](Self::segments_is),
    /// `self` may contain more segments than the number matched  against.
    pub fn starts_with(&self, segments: &[Symbol]) -> bool {
        segments.len() < self.len() && self.segments().zip(segments).all(|(a, b)| a.name == *b)
    }
}

impl<P: Borrow<Path>> Display for PathParser<P> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", pprust::path_to_string(self.0.borrow()))
    }
}

#[derive(Clone, Debug)]
#[must_use]
pub enum ArgParser {
    NoArgs,
    List(MetaItemListParser),
    NameValue(NameValueParser),
}

impl ArgParser {
    pub fn span(&self) -> Option<Span> {
        match self {
            Self::NoArgs => None,
            Self::List(l) => Some(l.span),
            Self::NameValue(n) => Some(n.value_span.with_lo(n.eq_span.lo())),
        }
    }

    pub fn from_attr_args<'sess>(
        value: &AttrArgs,
        parts: &[Symbol],
        psess: &'sess ParseSess,
        should_emit: ShouldEmit,
    ) -> Option<Self> {
        Some(match value {
            AttrArgs::Empty => Self::NoArgs,
            AttrArgs::Delimited(args) => {
                // The arguments of rustc_dummy are not validated if the arguments are delimited
                if parts == &[sym::rustc_dummy] {
                    return Some(ArgParser::List(MetaItemListParser {
                        sub_parsers: ThinVec::new(),
                        span: args.dspan.entire(),
                    }));
                }

                if args.delim != Delimiter::Parenthesis {
                    psess.dcx().emit_err(MetaBadDelim {
                        span: args.dspan.entire(),
                        sugg: MetaBadDelimSugg { open: args.dspan.open, close: args.dspan.close },
                    });
                    return None;
                }

                Self::List(
                    MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit)
                        .map_err(|e| should_emit.emit_err(e))
                        .ok()?,
                )
            }
            AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
                eq_span: *eq_span,
                value: expr_to_lit(psess, &expr, expr.span, should_emit)?,
                value_span: expr.span,
            }),
        })
    }

    /// Asserts that this MetaItem is a list
    ///
    /// Some examples:
    ///
    /// - `#[allow(clippy::complexity)]`: `(clippy::complexity)` is a list
    /// - `#[rustfmt::skip::macros(target_macro_name)]`: `(target_macro_name)` is a list
    pub fn list(&self) -> Option<&MetaItemListParser> {
        match self {
            Self::List(l) => Some(l),
            Self::NameValue(_) | Self::NoArgs => None,
        }
    }

    /// Asserts that this MetaItem is a name-value pair.
    ///
    /// Some examples:
    ///
    /// - `#[clippy::cyclomatic_complexity = "100"]`: `clippy::cyclomatic_complexity = "100"` is a name value pair,
    ///   where the name is a path (`clippy::cyclomatic_complexity`). You already checked the path
    ///   to get an `ArgParser`, so this method will effectively only assert that the `= "100"` is
    ///   there
    /// - `#[doc = "hello"]`: `doc = "hello`  is also a name value pair
    pub fn name_value(&self) -> Option<&NameValueParser> {
        match self {
            Self::NameValue(n) => Some(n),
            Self::List(_) | Self::NoArgs => None,
        }
    }

    /// Assert that there were no args.
    /// If there were, get a span to the arguments
    /// (to pass to [`AcceptContext::expected_no_args`](crate::context::AcceptContext::expected_no_args)).
    pub fn no_args(&self) -> Result<(), Span> {
        match self {
            Self::NoArgs => Ok(()),
            Self::List(args) => Err(args.span),
            Self::NameValue(args) => Err(args.args_span()),
        }
    }
}

/// Inside lists, values could be either literals, or more deeply nested meta items.
/// This enum represents that.
///
/// Choose which one you want using the provided methods.
#[derive(Debug, Clone)]
pub enum MetaItemOrLitParser {
    MetaItemParser(MetaItemParser),
    Lit(MetaItemLit),
    Err(Span, ErrorGuaranteed),
}

impl MetaItemOrLitParser {
    pub fn parse_single<'sess>(
        parser: &mut Parser<'sess>,
        should_emit: ShouldEmit,
    ) -> PResult<'sess, MetaItemOrLitParser> {
        let mut this = MetaItemListParserContext { parser, should_emit };
        this.parse_meta_item_inner()
    }

    pub fn span(&self) -> Span {
        match self {
            MetaItemOrLitParser::MetaItemParser(generic_meta_item_parser) => {
                generic_meta_item_parser.span()
            }
            MetaItemOrLitParser::Lit(meta_item_lit) => meta_item_lit.span,
            MetaItemOrLitParser::Err(span, _) => *span,
        }
    }

    pub fn lit(&self) -> Option<&MetaItemLit> {
        match self {
            MetaItemOrLitParser::Lit(meta_item_lit) => Some(meta_item_lit),
            _ => None,
        }
    }

    pub fn meta_item(&self) -> Option<&MetaItemParser> {
        match self {
            MetaItemOrLitParser::MetaItemParser(parser) => Some(parser),
            _ => None,
        }
    }
}

/// Utility that deconstructs a MetaItem into usable parts.
///
/// MetaItems are syntactically extremely flexible, but specific attributes want to parse
/// them in custom, more restricted ways. This can be done using this struct.
///
/// MetaItems consist of some path, and some args. The args could be empty. In other words:
///
/// - `name` -> args are empty
/// - `name(...)` -> args are a [`list`](ArgParser::list), which is the bit between the parentheses
/// - `name = value`-> arg is [`name_value`](ArgParser::name_value), where the argument is the
///   `= value` part
///
/// The syntax of MetaItems can be found at <https://doc.rust-lang.org/reference/attributes.html>
#[derive(Clone)]
pub struct MetaItemParser {
    path: OwnedPathParser,
    args: ArgParser,
}

impl Debug for MetaItemParser {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("MetaItemParser")
            .field("path", &self.path)
            .field("args", &self.args)
            .finish()
    }
}

impl MetaItemParser {
    pub fn span(&self) -> Span {
        if let Some(other) = self.args.span() {
            self.path.borrow().span().with_hi(other.hi())
        } else {
            self.path.borrow().span()
        }
    }

    /// Gets just the path, without the args. Some examples:
    ///
    /// - `#[rustfmt::skip]`: `rustfmt::skip` is a path
    /// - `#[allow(clippy::complexity)]`: `clippy::complexity` is a path
    /// - `#[inline]`: `inline` is a single segment path
    pub fn path(&self) -> &OwnedPathParser {
        &self.path
    }

    /// Gets just the args parser, without caring about the path.
    pub fn args(&self) -> &ArgParser {
        &self.args
    }

    /// Asserts that this MetaItem starts with a word, or single segment path.
    ///
    /// Some examples:
    /// - `#[inline]`: `inline` is a word
    /// - `#[rustfmt::skip]`: `rustfmt::skip` is a path,
    ///   and not a word and should instead be parsed using [`path`](Self::path)
    pub fn word_is(&self, sym: Symbol) -> Option<&ArgParser> {
        self.path().word_is(sym).then(|| self.args())
    }
}

#[derive(Clone)]
pub struct NameValueParser {
    pub eq_span: Span,
    value: MetaItemLit,
    pub value_span: Span,
}

impl Debug for NameValueParser {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("NameValueParser")
            .field("eq_span", &self.eq_span)
            .field("value", &self.value)
            .field("value_span", &self.value_span)
            .finish()
    }
}

impl NameValueParser {
    pub fn value_as_lit(&self) -> &MetaItemLit {
        &self.value
    }

    pub fn value_as_str(&self) -> Option<Symbol> {
        self.value_as_lit().kind.str()
    }

    pub fn args_span(&self) -> Span {
        self.eq_span.to(self.value_span)
    }
}

fn expr_to_lit(
    psess: &ParseSess,
    expr: &Expr,
    span: Span,
    should_emit: ShouldEmit,
) -> Option<MetaItemLit> {
    if let ExprKind::Lit(token_lit) = expr.kind {
        let res = MetaItemLit::from_token_lit(token_lit, expr.span);
        match res {
            Ok(lit) => {
                if token_lit.suffix.is_some() {
                    should_emit.emit_err(
                        psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
                    );
                    None
                } else {
                    if !lit.kind.is_unsuffixed() {
                        // Emit error and continue, we can still parse the attribute as if the suffix isn't there
                        should_emit.emit_err(
                            psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
                        );
                    }

                    Some(lit)
                }
            }
            Err(err) => {
                let guar = report_lit_error(psess, err, token_lit, expr.span);
                let lit = MetaItemLit {
                    symbol: token_lit.symbol,
                    suffix: token_lit.suffix,
                    kind: LitKind::Err(guar),
                    span: expr.span,
                };
                Some(lit)
            }
        }
    } else {
        if matches!(should_emit, ShouldEmit::Nothing) {
            return None;
        }

        // Example cases:
        // - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
        // - `#[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 err = psess.dcx().struct_span_err(span, msg);
        should_emit.emit_err(err);
        None
    }
}

struct MetaItemListParserContext<'a, 'sess> {
    parser: &'a mut Parser<'sess>,
    should_emit: ShouldEmit,
}

impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
    fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'sess, MetaItemLit> {
        let Some(token_lit) = self.parser.eat_token_lit() else { return Err(self.expected_lit()) };
        self.unsuffixed_meta_item_from_lit(token_lit)
    }

    fn unsuffixed_meta_item_from_lit(
        &mut self,
        token_lit: token::Lit,
    ) -> PResult<'sess, MetaItemLit> {
        let lit = match MetaItemLit::from_token_lit(token_lit, self.parser.prev_token.span) {
            Ok(lit) => lit,
            Err(err) => {
                return Err(create_lit_error(
                    &self.parser.psess,
                    err,
                    token_lit,
                    self.parser.prev_token_uninterpolated_span(),
                ));
            }
        };

        if !lit.kind.is_unsuffixed() {
            // Emit error and continue, we can still parse the attribute as if the suffix isn't there
            self.should_emit.emit_err(
                self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
            );
        }

        Ok(lit)
    }

    fn parse_attr_item(&mut self) -> PResult<'sess, MetaItemParser> {
        if let Some(MetaVarKind::Meta { has_meta_form }) = self.parser.token.is_metavar_seq() {
            return if has_meta_form {
                let attr_item = self
                    .parser
                    .eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
                        MetaItemListParserContext { parser: this, should_emit: self.should_emit }
                            .parse_attr_item()
                    })
                    .unwrap();
                Ok(attr_item)
            } else {
                self.parser.unexpected_any()
            };
        }

        let path = self.parser.parse_path(PathStyle::Mod)?;

        // Check style of arguments that this meta item has
        let args = if self.parser.check(exp!(OpenParen)) {
            let start = self.parser.token.span;
            let (sub_parsers, _) = self.parser.parse_paren_comma_seq(|parser| {
                MetaItemListParserContext { parser, should_emit: self.should_emit }
                    .parse_meta_item_inner()
            })?;
            let end = self.parser.prev_token.span;
            ArgParser::List(MetaItemListParser { sub_parsers, span: start.with_hi(end.hi()) })
        } else if self.parser.eat(exp!(Eq)) {
            let eq_span = self.parser.prev_token.span;
            let value = self.parse_unsuffixed_meta_item_lit()?;

            ArgParser::NameValue(NameValueParser { eq_span, value, value_span: value.span })
        } else {
            ArgParser::NoArgs
        };

        Ok(MetaItemParser { path: PathParser(path), args })
    }

    fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser> {
        if let Some(token_lit) = self.parser.eat_token_lit() {
            // If a literal token is parsed, we commit to parsing a MetaItemLit for better errors
            Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?))
        } else {
            let prev_pros = self.parser.approx_token_stream_pos();
            match self.parse_attr_item() {
                Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)),
                Err(err) => {
                    // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
                    // If it didn't make progress we use the `expected_lit` from below
                    if self.parser.approx_token_stream_pos() != prev_pros {
                        Err(err)
                    } else {
                        err.cancel();
                        Err(self.expected_lit())
                    }
                }
            }
        }
    }

    fn expected_lit(&mut self) -> Diag<'sess> {
        let mut err = InvalidMetaItem {
            span: self.parser.token.span,
            descr: token_descr(&self.parser.token),
            quote_ident_sugg: None,
            remove_neg_sugg: None,
            label: None,
        };

        if let token::OpenInvisible(_) = self.parser.token.kind {
            // Do not attempt to suggest anything when encountered as part of a macro expansion.
            return self.parser.dcx().create_err(err);
        }

        // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
        // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
        // when macro metavariables are involved.
        let snapshot = self.parser.create_snapshot_for_diagnostic();
        let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false);
        match stmt {
            Ok(Some(stmt)) => {
                // The user tried to write something like
                // `#[deprecated(note = concat!("a", "b"))]`.
                err.descr = stmt.kind.descr().to_string();
                err.label = Some(stmt.span);
                err.span = stmt.span;
                if let StmtKind::Expr(expr) = &stmt.kind
                    && let ExprKind::Unary(UnOp::Neg, val) = &expr.kind
                    && let ExprKind::Lit(_) = val.kind
                {
                    err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg {
                        negative_sign: expr.span.until(val.span),
                    });
                } else if let StmtKind::Expr(expr) = &stmt.kind
                    && let ExprKind::Path(None, Path { segments, .. }) = &expr.kind
                    && segments.len() == 1
                {
                    while let token::Ident(..) | token::Literal(_) | token::Dot =
                        self.parser.token.kind
                    {
                        // We've got a word, so we try to consume the rest of a potential sentence.
                        // We include `.` to correctly handle things like `A sentence here.`.
                        self.parser.bump();
                    }
                    err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg {
                        before: expr.span.shrink_to_lo(),
                        after: self.parser.prev_token.span.shrink_to_hi(),
                    });
                }
            }
            Ok(None) => {}
            Err(e) => {
                e.cancel();
                self.parser.restore_snapshot(snapshot);
            }
        }

        self.parser.dcx().create_err(err)
    }

    fn parse(
        tokens: TokenStream,
        psess: &'sess ParseSess,
        span: Span,
        should_emit: ShouldEmit,
    ) -> PResult<'sess, MetaItemListParser> {
        let mut parser = Parser::new(psess, tokens, None);
        let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };

        // Presumably, the majority of the time there will only be one attr.
        let mut sub_parsers = ThinVec::with_capacity(1);
        while this.parser.token != token::Eof {
            sub_parsers.push(this.parse_meta_item_inner()?);

            if !this.parser.eat(exp!(Comma)) {
                break;
            }
        }

        if parser.token != token::Eof {
            parser.unexpected()?;
        }

        Ok(MetaItemListParser { sub_parsers, span })
    }
}

#[derive(Debug, Clone)]
pub struct MetaItemListParser {
    sub_parsers: ThinVec<MetaItemOrLitParser>,
    pub span: Span,
}

impl MetaItemListParser {
    pub(crate) fn new<'sess>(
        tokens: &TokenStream,
        span: Span,
        psess: &'sess ParseSess,
        should_emit: ShouldEmit,
    ) -> Result<Self, Diag<'sess>> {
        MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit)
    }

    /// Lets you pick and choose as what you want to parse each element in the list
    pub fn mixed(&self) -> impl Iterator<Item = &MetaItemOrLitParser> {
        self.sub_parsers.iter()
    }

    pub fn len(&self) -> usize {
        self.sub_parsers.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns Some if the list contains only a single element.
    ///
    /// Inside the Some is the parser to parse this single element.
    pub fn single(&self) -> Option<&MetaItemOrLitParser> {
        let mut iter = self.mixed();
        iter.next().filter(|_| iter.next().is_none())
    }
}
