//! Parsing of attribute arguments.
//!
//! Depending on the attribute parser, an [`ArgParser`] can be used to parse the arguments given to
//! an attribute. See its documentation for more information.
//!
//! 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};
#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicBool, Ordering};

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

use crate::ShouldEmit;
use crate::session_diagnostics::{
    AdditionalCommaSuggestion, ExpectedComma, 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().map(|s| s.name).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()))
    }
}

/// Used for parsing attribute arguments.
///
/// See also [`AttributeDiagnosticContext`], which is the preferred interface for issuing argument
/// parsing related diagnostics.
///
/// [`AttributeDiagnosticContext`]: crate::context::AttributeDiagnosticContext
#[derive(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,
        allow_expr_metavar: AllowExprMetavar,
    ) -> Option<Self> {
        Some(match value {
            AttrArgs::Empty => Self::NoArgs,
            AttrArgs::Delimited(args) => {
                // Diagnostic attributes can't error if they encounter non meta item syntax.
                // However, the current syntax for diagnostic attributes is meta item syntax.
                // Therefore we can substitute with a dummy value on invalid syntax.
                if matches!(parts, [sym::rustc_dummy] | [sym::diagnostic, ..]) {
                    match MetaItemListParser::new(
                        &args.tokens,
                        args.dspan.entire(),
                        psess,
                        ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden },
                        allow_expr_metavar,
                    ) {
                        Ok(p) => return Some(ArgParser::List(p)),
                        Err(e) => {
                            // We can just dispose of the diagnostic and not bother with a lint,
                            // because this will look like `#[diagnostic::attr()]` was used. This
                            // is invalid for all diagnostic attrs, so a lint explaining the proper
                            // form will be issued later.
                            e.cancel();
                            return Some(ArgParser::List(MetaItemListParser {
                                sub_parsers: ThinVec::new(),
                                span: args.dspan.entire(),
                            }));
                        }
                    }
                }

                if args.delim != Delimiter::Parenthesis {
                    should_emit.emit_err(psess.dcx().create_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,
                        allow_expr_metavar,
                    )
                    .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)
                    .map_err(|e| should_emit.emit_err(e))
                    .ok()??,
                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 as_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 as_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 [`AttributeDiagnosticContext::expected_no_args`](crate::context::AttributeDiagnosticContext::expected_no_args)).
    pub fn as_no_args(&self) -> Result<(), Span> {
        match self {
            Self::NoArgs => Ok(()),
            Self::List(args) => Err(args.span),
            Self::NameValue(args) => Err(args.args_span()),
        }
    }

    /// Explicitly ignore the arguments, disarming the arguments-used check
    pub fn ignore_args(&self) {
        #[cfg(debug_assertions)]
        match self {
            ArgParser::List(list) => {
                for item in list.mixed() {
                    item.ignore_args();
                }
            }
            _ => {}
        }
    }
}

/// 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)]
pub enum MetaItemOrLitParser {
    MetaItemParser(MetaItemParser),
    Lit(MetaItemLit),
}

impl MetaItemOrLitParser {
    pub fn parse_single<'sess>(
        parser: &mut Parser<'sess>,
        should_emit: ShouldEmit,
        allow_expr_metavar: AllowExprMetavar,
    ) -> PResult<'sess, MetaItemOrLitParser> {
        let mut this = MetaItemListParserContext { parser, should_emit, allow_expr_metavar };
        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,
        }
    }

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

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

    /// Returns some if this `MetaItemOrLitParser` is a `MetaItem` with no arguments
    pub fn meta_item_no_args(&self) -> Option<&MetaItemParser> {
        let meta_item = self.meta_item()?;
        match meta_item.args().as_no_args() {
            Ok(_) => Some(meta_item),
            Err(_) => None,
        }
    }

    /// Explicitly ignore the arguments, disarming the arguments-used check
    pub fn ignore_args(&self) {
        #[cfg(debug_assertions)]
        match self {
            MetaItemOrLitParser::MetaItemParser(meta_item) => {
                meta_item.ignore_args();
            }
            MetaItemOrLitParser::Lit(_) => {}
        }
    }
}

// FIXME(scrabsha): once #155696 is merged, update this and mention the higher-level APIs.
/// 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::as_list), which is the bit between the
///   parentheses
/// - `name = value`-> arg is [`name_value`](ArgParser::as_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>
pub struct MetaItemParser {
    path: OwnedPathParser,
    args: ArgParser,

    /// Whether the `args` of this meta item have been looked at.
    /// This is tracked because if the arguments of a `MetaItemParser` are ignored, this is probably a mistake
    #[cfg(debug_assertions)]
    args_checked: AtomicBool,
}

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 {
    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
    pub fn ident(&self) -> Option<Ident> {
        if let [PathSegment { ident, .. }] = self.path.0.segments[..] { Some(ident) } else { None }
    }

    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 {
        #[cfg(debug_assertions)]
        self.args_checked.store(true, Ordering::Relaxed);
        &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())
    }

    /// Explicitly ignore the arguments, disarming the arguments-used check
    pub fn ignore_args(&self) {
        self.args().ignore_args();
    }

    #[cfg(debug_assertions)]
    pub fn are_args_checked(&self) -> bool {
        self.args_checked.load(Ordering::Relaxed)
    }
}

#[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()
    }

    /// If the value is a string literal, it will return its value associated with its span (an
    /// `Ident` in short).
    pub fn value_as_ident(&self) -> Option<Ident> {
        let meta_item = self.value_as_lit();
        meta_item.kind.str().map(|name| Ident { name, span: meta_item.span })
    }

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

fn expr_to_lit<'sess>(
    psess: &'sess ParseSess,
    expr: &Expr,
    span: Span,
    should_emit: ShouldEmit,
) -> PResult<'sess, 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() {
                    Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }))
                } else {
                    if lit.kind.is_unsuffixed() {
                        Ok(Some(lit))
                    } else {
                        Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }))
                    }
                }
            }
            Err(err) => {
                let err = create_lit_error(psess, err, token_lit, expr.span);
                if matches!(
                    should_emit,
                    ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
                ) {
                    Err(err)
                } else {
                    let lit = MetaItemLit {
                        symbol: token_lit.symbol,
                        suffix: token_lit.suffix,
                        kind: LitKind::Err(err.emit()),
                        span: expr.span,
                    };
                    Ok(Some(lit))
                }
            }
        }
    } else {
        if matches!(should_emit, ShouldEmit::Nothing) || matches!(expr.kind, ExprKind::Err(_)) {
            return Ok(None);
        }

        // Example cases:
        // - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
        // - `#[foo = include_str!("nonexistent-file.rs")]`:
        //   results in `ast::ExprKind::Err`.
        let msg = "attribute value must be a literal";
        let mut err = psess.dcx().struct_span_err(span, msg);

        // Suggest adding quotation marks to turn an identifier into a string literal
        if let ExprKind::Path(None, ref path) = expr.kind
            && let [segment] = path.segments.as_slice()
        {
            err.span_suggestion(
                expr.span,
                "try adding quotation marks",
                &format!("\"{}\"", segment.ident),
                Applicability::MaybeIncorrect,
            );
        }

        Err(err)
    }
}

/// Whether expansions of `expr` metavariables from decrarative macros
/// are permitted. Used when parsing meta items; currently, only `cfg` predicates
/// enable this option
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AllowExprMetavar {
    No,
    Yes,
}

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

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
            let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span });
            if matches!(
                self.should_emit,
                ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
            ) {
                return Err(err);
            } else {
                self.should_emit.emit_err(err)
            };
        }

        Ok(lit)
    }

    fn parse_meta_item(&mut self) -> PResult<'sess, MetaItemParser> {
        if let Some(metavar) = self.parser.token.is_metavar_seq() {
            match (metavar, self.allow_expr_metavar) {
                (kind @ MetaVarKind::Expr { .. }, AllowExprMetavar::Yes) => {
                    return self
                        .parser
                        .eat_metavar_seq(kind, |this| {
                            MetaItemListParserContext {
                                parser: this,
                                should_emit: self.should_emit,
                                allow_expr_metavar: AllowExprMetavar::Yes,
                            }
                            .parse_meta_item()
                        })
                        .ok_or_else(|| {
                            self.parser.unexpected_any::<core::convert::Infallible>().unwrap_err()
                        });
                }
                (MetaVarKind::Meta { has_meta_form }, _) => {
                    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,
                                    allow_expr_metavar: self.allow_expr_metavar,
                                }
                                .parse_meta_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,
                    allow_expr_metavar: self.allow_expr_metavar,
                }
                .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,
            #[cfg(debug_assertions)]
            args_checked: AtomicBool::new(false),
        })
    }

    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_meta_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);
        }

        if let ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } = self.should_emit {
            // Do not attempt to suggest anything in `Recovery::Forbidden` mode.
            // Malformed diagnostic-attr arguments that start with an `if` expression can lead to
            // an ICE (https://github.com/rust-lang/rust/issues/152744), because callers may cancel the `InvalidMetaItem` error.
            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 should_continue_parsing_meta_items(&mut self) -> Result<bool, Diag<'sess>> {
        if self.parser.eat(exp!(Comma)) {
            return Ok(true);
        } else if self.parser.token == token::Eof {
            return Ok(false);
        }

        let mut snapshot = self.parser.create_snapshot_for_diagnostic();
        if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }) {
            let mut missing_commas = ThinVec::new();
            let mut found_comma = false;
            while self.parser.token != token::Eof {
                let span = self.parser.prev_token.span.shrink_to_hi();
                self.should_emit = ShouldEmit::Nothing;
                match self.parse_meta_item_inner() {
                    Ok(_) => {
                        if !found_comma {
                            missing_commas.push(span);
                        }
                    }
                    Err(e) => {
                        e.cancel();
                        break;
                    }
                }
                found_comma = self.parser.eat(exp!(Comma));
            }

            let mut missing_commas = missing_commas.into_iter();
            if let Some(span) = missing_commas.next() {
                let additional =
                    missing_commas.map(|span| AdditionalCommaSuggestion { span }).collect();
                return Err(self.parser.dcx().create_err(ExpectedComma { span, additional }));
            }
        }
        snapshot.unexpected_any()
    }

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

        let mut this =
            MetaItemListParserContext { parser: &mut parser, should_emit, allow_expr_metavar };

        // 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.should_continue_parsing_meta_items()? {
                break;
            }
        }

        Ok(MetaItemListParser { sub_parsers, span })
    }
}

#[derive(Debug)]
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,
        allow_expr_metavar: AllowExprMetavar,
    ) -> Result<Self, Diag<'sess>> {
        MetaItemListParserContext::parse(
            tokens.clone(),
            psess,
            span,
            should_emit,
            allow_expr_metavar,
        )
    }

    /// 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 as_single(&self) -> Option<&MetaItemOrLitParser> {
        let mut iter = self.mixed();
        iter.next().filter(|_| iter.next().is_none())
    }
}
