use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::str::FromStr;

use proc_macro::Span;
use proc_macro2::{Ident, TokenStream};
use quote::{ToTokens, format_ident, quote};
use syn::parse::ParseStream;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{Attribute, Field, LitStr, Meta, Path, Token, Type, TypeTuple, parenthesized};
use synstructure::{BindingInfo, VariantInfo};

use super::error::invalid_attr;
use crate::diagnostics::error::{
    DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err,
};
use crate::diagnostics::message::Message;

thread_local! {
    pub(crate) static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0);
}

/// Returns an ident of the form `__code_N` where `N` is incremented once with every call.
pub(crate) fn new_code_ident() -> syn::Ident {
    CODE_IDENT_COUNT.with(|count| {
        let ident = format_ident!("__code_{}", *count.borrow());
        *count.borrow_mut() += 1;
        ident
    })
}

/// Checks whether the type name of `ty` matches `name`.
///
/// Given some struct at `a::b::c::Foo`, this will return true for `c::Foo`, `b::c::Foo`, or
/// `a::b::c::Foo`. This reasonably allows qualified names to be used in the macro.
pub(crate) fn type_matches_path(ty: &Type, name: &[&str]) -> bool {
    if let Type::Path(ty) = ty {
        ty.path
            .segments
            .iter()
            .map(|s| s.ident.to_string())
            .rev()
            .zip(name.iter().rev())
            .all(|(x, y)| &x.as_str() == y)
    } else {
        false
    }
}

/// Checks whether the type `ty` is `()`.
pub(crate) fn type_is_unit(ty: &Type) -> bool {
    if let Type::Tuple(TypeTuple { elems, .. }) = ty { elems.is_empty() } else { false }
}

/// Checks whether the type `ty` is `bool`.
pub(crate) fn type_is_bool(ty: &Type) -> bool {
    type_matches_path(ty, &["bool"])
}

/// Reports a type error for field with `attr`.
pub(crate) fn report_type_error(
    attr: &Attribute,
    ty_name: &str,
) -> Result<!, DiagnosticDeriveError> {
    let name = attr.path().segments.last().unwrap().ident.to_string();
    let meta = &attr.meta;

    throw_span_err!(
        attr.span().unwrap(),
        &format!(
            "the `#[{}{}]` attribute can only be applied to fields of type {}",
            name,
            match meta {
                Meta::Path(_) => "",
                Meta::NameValue(_) => " = ...",
                Meta::List(_) => "(...)",
            },
            ty_name
        )
    );
}

/// Reports an error if the field's type does not match `path`.
fn report_error_if_not_applied_to_ty(
    attr: &Attribute,
    info: &FieldInfo<'_>,
    path: &[&str],
    ty_name: &str,
) -> Result<(), DiagnosticDeriveError> {
    if !type_matches_path(info.ty.inner_type(), path) {
        report_type_error(attr, ty_name)?;
    }

    Ok(())
}

/// Reports an error if the field's type is not `Applicability`.
pub(crate) fn report_error_if_not_applied_to_applicability(
    attr: &Attribute,
    info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
    report_error_if_not_applied_to_ty(
        attr,
        info,
        &["rustc_errors", "Applicability"],
        "`Applicability`",
    )
}

/// Reports an error if the field's type is not `Span`.
pub(crate) fn report_error_if_not_applied_to_span(
    attr: &Attribute,
    info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
    if !type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"])
        && !type_matches_path(info.ty.inner_type(), &["rustc_errors", "MultiSpan"])
    {
        report_type_error(attr, "`Span` or `MultiSpan`")?;
    }

    Ok(())
}

/// Inner type of a field and type of wrapper.
#[derive(Copy, Clone)]
pub(crate) enum FieldInnerTy<'ty> {
    /// Field is wrapped in a `Option<$inner>`.
    Option(&'ty Type),
    /// Field is wrapped in a `Vec<$inner>`.
    Vec(&'ty Type),
    /// Field isn't wrapped in an outer type.
    Plain(&'ty Type),
}

impl<'ty> FieldInnerTy<'ty> {
    /// Returns inner type for a field, if there is one.
    ///
    /// - If `ty` is an `Option<Inner>`, returns `FieldInnerTy::Option(Inner)`.
    /// - If `ty` is a `Vec<Inner>`, returns `FieldInnerTy::Vec(Inner)`.
    /// - Otherwise returns `FieldInnerTy::Plain(ty)`.
    pub(crate) fn from_type(ty: &'ty Type) -> Self {
        fn single_generic_type(ty: &Type) -> &Type {
            let Type::Path(ty_path) = ty else {
                panic!("expected path type");
            };

            let path = &ty_path.path;
            let ty = path.segments.last().unwrap();
            let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else {
                panic!("expected bracketed generic arguments");
            };

            assert_eq!(bracketed.args.len(), 1);

            let syn::GenericArgument::Type(ty) = &bracketed.args[0] else {
                panic!("expected generic parameter to be a type generic");
            };

            ty
        }

        if type_matches_path(ty, &["std", "option", "Option"]) {
            FieldInnerTy::Option(single_generic_type(ty))
        } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
            FieldInnerTy::Vec(single_generic_type(ty))
        } else {
            FieldInnerTy::Plain(ty)
        }
    }

    /// Returns `true` if `FieldInnerTy::with` will result in iteration for this inner type (i.e.
    /// that cloning might be required for values moved in the loop body).
    pub(crate) fn will_iterate(&self) -> bool {
        match self {
            FieldInnerTy::Vec(..) => true,
            FieldInnerTy::Option(..) | FieldInnerTy::Plain(_) => false,
        }
    }

    /// Returns the inner type.
    pub(crate) fn inner_type(&self) -> &'ty Type {
        match self {
            FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) | FieldInnerTy::Plain(inner) => {
                inner
            }
        }
    }

    /// Surrounds `inner` with destructured wrapper type, exposing inner type as `binding`.
    pub(crate) fn with(&self, binding: impl ToTokens, inner: impl ToTokens) -> TokenStream {
        match self {
            FieldInnerTy::Option(..) => quote! {
                if let Some(#binding) = #binding {
                    #inner
                }
            },
            FieldInnerTy::Vec(..) => quote! {
                for #binding in #binding {
                    #inner
                }
            },
            FieldInnerTy::Plain(t) if type_is_bool(t) => quote! {
                if #binding {
                    #inner
                }
            },
            FieldInnerTy::Plain(..) => quote! { #inner },
        }
    }

    pub(crate) fn span(&self) -> proc_macro2::Span {
        match self {
            FieldInnerTy::Option(ty) | FieldInnerTy::Vec(ty) | FieldInnerTy::Plain(ty) => ty.span(),
        }
    }
}

/// Field information passed to the builder. Deliberately omits attrs to discourage the
/// `generate_*` methods from walking the attributes themselves.
pub(crate) struct FieldInfo<'a> {
    pub(crate) binding: &'a BindingInfo<'a>,
    pub(crate) ty: FieldInnerTy<'a>,
    pub(crate) span: &'a proc_macro2::Span,
}

/// Small helper trait for abstracting over `Option` fields that contain a value and a `Span`
/// for error reporting if they are set more than once.
pub(crate) trait SetOnce<T> {
    fn set_once(&mut self, value: T, span: Span);

    fn value(self) -> Option<T>;
    fn value_ref(&self) -> Option<&T>;
}

/// An [`Option<T>`] that keeps track of the span that caused it to be set; used with [`SetOnce`].
pub(super) type SpannedOption<T> = Option<(T, Span)>;

impl<T> SetOnce<T> for SpannedOption<T> {
    fn set_once(&mut self, value: T, span: Span) {
        match self {
            None => {
                *self = Some((value, span));
            }
            Some((_, prev_span)) => {
                span_err(span, "attribute specified multiple times")
                    .span_note(*prev_span, "previously specified here")
                    .emit();
            }
        }
    }

    fn value(self) -> Option<T> {
        self.map(|(v, _)| v)
    }

    fn value_ref(&self) -> Option<&T> {
        self.as_ref().map(|(v, _)| v)
    }
}

pub(super) type FieldMap = HashMap<String, TokenStream>;

/// In the strings in the attributes supplied to this macro, we want callers to be able to
/// reference fields in the format string. For example:
///
/// ```ignore (not-usage-example)
/// /// Suggest `==` when users wrote `===`.
/// #[suggestion("example message", code = "{lhs} == {rhs}")]
/// struct NotJavaScriptEq {
///     #[primary_span]
///     span: Span,
///     lhs: Ident,
///     rhs: Ident,
/// }
/// ```
///
/// We want to automatically pick up that `{lhs}` refers `self.lhs` and `{rhs}` refers to
/// `self.rhs`, then generate this call to `format!`:
///
/// ```ignore (not-usage-example)
/// format!("{lhs} == {rhs}", lhs = self.lhs, rhs = self.rhs)
/// ```
///
/// This function builds the entire call to `format!`.
pub(super) fn build_format(
    field_map: &FieldMap,
    input: &str,
    span: proc_macro2::Span,
) -> TokenStream {
    // This set is used later to generate the final format string. To keep builds reproducible,
    // the iteration order needs to be deterministic, hence why we use a `BTreeSet` here
    // instead of a `HashSet`.
    let mut referenced_fields: BTreeSet<String> = BTreeSet::new();

    // At this point, we can start parsing the format string.
    let mut it = input.chars().peekable();

    // Once the start of a format string has been found, process the format string and spit out
    // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so
    // the next call to `it.next()` retrieves the next character.
    while let Some(c) = it.next() {
        if c != '{' {
            continue;
        }
        if *it.peek().unwrap_or(&'\0') == '{' {
            assert_eq!(it.next().unwrap(), '{');
            continue;
        }
        let mut eat_argument = || -> Option<String> {
            let mut result = String::new();
            // Format specifiers look like:
            //
            //   format   := '{' [ argument ] [ ':' format_spec ] '}' .
            //
            // Therefore, we only need to eat until ':' or '}' to find the argument.
            while let Some(c) = it.next() {
                result.push(c);
                let next = *it.peek().unwrap_or(&'\0');
                if next == '}' {
                    break;
                } else if next == ':' {
                    // Eat the ':' character.
                    assert_eq!(it.next().unwrap(), ':');
                    break;
                }
            }
            // Eat until (and including) the matching '}'
            while it.next()? != '}' {
                continue;
            }
            Some(result)
        };

        if let Some(referenced_field) = eat_argument() {
            referenced_fields.insert(referenced_field);
        }
    }

    // At this point, `referenced_fields` contains a set of the unique fields that were
    // referenced in the format string. Generate the corresponding "x = self.x" format
    // string parameters:
    let args = referenced_fields.into_iter().map(|field: String| {
        let field_ident = format_ident!("{}", field);
        let value = match field_map.get(&field) {
            Some(value) => value.clone(),
            // This field doesn't exist. Emit a diagnostic.
            None => {
                span_err(span.unwrap(), format!("`{field}` doesn't refer to a field on this type"))
                    .emit();
                quote! {
                    "{#field}"
                }
            }
        };
        quote! {
            #field_ident = #value
        }
    });
    quote! {
        format!(#input #(,#args)*)
    }
}

/// `Applicability` of a suggestion - mirrors `rustc_errors::Applicability` - and used to represent
/// the user's selection of applicability if specified in an attribute.
#[derive(Clone, Copy)]
pub(crate) enum Applicability {
    MachineApplicable,
    MaybeIncorrect,
    HasPlaceholders,
    Unspecified,
}

impl FromStr for Applicability {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "machine-applicable" => Ok(Applicability::MachineApplicable),
            "maybe-incorrect" => Ok(Applicability::MaybeIncorrect),
            "has-placeholders" => Ok(Applicability::HasPlaceholders),
            "unspecified" => Ok(Applicability::Unspecified),
            _ => Err(()),
        }
    }
}

impl quote::ToTokens for Applicability {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend(match self {
            Applicability::MachineApplicable => {
                quote! { rustc_errors::Applicability::MachineApplicable }
            }
            Applicability::MaybeIncorrect => {
                quote! { rustc_errors::Applicability::MaybeIncorrect }
            }
            Applicability::HasPlaceholders => {
                quote! { rustc_errors::Applicability::HasPlaceholders }
            }
            Applicability::Unspecified => {
                quote! { rustc_errors::Applicability::Unspecified }
            }
        });
    }
}

/// Build the mapping of field names to fields. This allows attributes to peek values from
/// other fields.
pub(super) fn build_field_mapping(variant: &VariantInfo<'_>) -> HashMap<String, TokenStream> {
    let mut fields_map = FieldMap::new();
    for binding in variant.bindings() {
        if let Some(ident) = &binding.ast().ident {
            fields_map.insert(ident.to_string(), quote! { #binding });
        }
    }
    fields_map
}

#[derive(Copy, Clone, Debug)]
pub(super) enum AllowMultipleAlternatives {
    No,
    Yes,
}

fn parse_suggestion_values(
    nested: ParseStream<'_>,
    allow_multiple: AllowMultipleAlternatives,
) -> syn::Result<Vec<LitStr>> {
    if nested.parse::<Token![=]>().is_ok() {
        return Ok(vec![nested.parse::<LitStr>()?]);
    }

    let content;
    parenthesized!(content in nested);
    if let AllowMultipleAlternatives::No = allow_multiple {
        span_err(content.span().unwrap(), "expected exactly one string literal for `code = ...`")
            .emit();
        return Ok(vec![]);
    }

    let literals = Punctuated::<LitStr, Token![,]>::parse_terminated(&content);
    Ok(match literals {
        Ok(p) if p.is_empty() => {
            span_err(
                content.span().unwrap(),
                "expected at least one string literal for `code(...)`",
            )
            .emit();
            vec![]
        }
        Ok(p) => p.into_iter().collect(),
        Err(_) => {
            span_err(content.span().unwrap(), "`code(...)` must contain only string literals")
                .emit();
            vec![]
        }
    })
}

/// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or
/// `#[suggestion*(code("foo", "bar"))]` attribute field
pub(super) fn build_suggestion_code(
    code_field: &Ident,
    nested: ParseStream<'_>,
    fields: &FieldMap,
    allow_multiple: AllowMultipleAlternatives,
) -> Result<TokenStream, syn::Error> {
    let values = parse_suggestion_values(nested, allow_multiple)?;

    Ok(if let AllowMultipleAlternatives::Yes = allow_multiple {
        let formatted_strings: Vec<_> = values
            .into_iter()
            .map(|value| build_format(fields, &value.value(), value.span()))
            .collect();
        quote! { let #code_field = [#(#formatted_strings),*].into_iter(); }
    } else if let [value] = values.as_slice() {
        let formatted_str = build_format(fields, &value.value(), value.span());
        quote! { let #code_field = #formatted_str; }
    } else {
        // error handled previously
        quote! { let #code_field = String::new(); }
    })
}

/// Possible styles for suggestion subdiagnostics.
#[derive(Clone, Copy, PartialEq)]
pub(super) enum SuggestionKind {
    Normal,
    Short,
    Hidden,
    Verbose,
    ToolOnly,
}

impl FromStr for SuggestionKind {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(SuggestionKind::Normal),
            "short" => Ok(SuggestionKind::Short),
            "hidden" => Ok(SuggestionKind::Hidden),
            "verbose" => Ok(SuggestionKind::Verbose),
            "tool-only" => Ok(SuggestionKind::ToolOnly),
            _ => Err(()),
        }
    }
}

impl fmt::Display for SuggestionKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SuggestionKind::Normal => write!(f, "normal"),
            SuggestionKind::Short => write!(f, "short"),
            SuggestionKind::Hidden => write!(f, "hidden"),
            SuggestionKind::Verbose => write!(f, "verbose"),
            SuggestionKind::ToolOnly => write!(f, "tool-only"),
        }
    }
}

impl SuggestionKind {
    pub(crate) fn to_suggestion_style(&self) -> TokenStream {
        match self {
            SuggestionKind::Normal => {
                quote! { rustc_errors::SuggestionStyle::ShowCode }
            }
            SuggestionKind::Short => {
                quote! { rustc_errors::SuggestionStyle::HideCodeInline }
            }
            SuggestionKind::Hidden => {
                quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
            }
            SuggestionKind::Verbose => {
                quote! { rustc_errors::SuggestionStyle::ShowAlways }
            }
            SuggestionKind::ToolOnly => {
                quote! { rustc_errors::SuggestionStyle::CompletelyHidden }
            }
        }
    }

    fn from_suffix(s: &str) -> Option<Self> {
        match s {
            "" => Some(SuggestionKind::Normal),
            "_short" => Some(SuggestionKind::Short),
            "_hidden" => Some(SuggestionKind::Hidden),
            "_verbose" => Some(SuggestionKind::Verbose),
            _ => None,
        }
    }
}

/// Types of subdiagnostics that can be created using attributes
#[derive(Clone)]
pub(super) enum SubdiagnosticKind {
    /// `#[label(...)]`
    Label,
    /// `#[note(...)]`
    Note,
    /// `#[note_once(...)]`
    NoteOnce,
    /// `#[help(...)]`
    Help,
    /// `#[help_once(...)]`
    HelpOnce,
    /// `#[warning(...)]`
    Warn,
    /// `#[suggestion{,_short,_hidden,_verbose}]`
    Suggestion {
        suggestion_kind: SuggestionKind,
        applicability: SpannedOption<Applicability>,
        /// Identifier for variable used for formatted code, e.g. `___code_0`. Enables separation
        /// of formatting and diagnostic emission so that `arg` calls can happen in-between..
        code_field: syn::Ident,
        /// Initialization logic for `code_field`'s variable, e.g.
        /// `let __formatted_code = /* whatever */;`
        code_init: TokenStream,
    },
    /// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
    MultipartSuggestion {
        suggestion_kind: SuggestionKind,
        applicability: SpannedOption<Applicability>,
    },
}

pub(super) struct SubdiagnosticVariant {
    pub(super) kind: SubdiagnosticKind,
    pub(super) message: Option<Message>,
}

impl SubdiagnosticVariant {
    /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`,
    /// `#[error("add parenthesis")]` or `#[suggestion(code = "...")]`. Returns the
    /// `SubdiagnosticKind` and the diagnostic message, if specified.
    pub(super) fn from_attr(
        attr: &Attribute,
        fields: &FieldMap,
    ) -> Result<Option<SubdiagnosticVariant>, DiagnosticDeriveError> {
        // Always allow documentation comments.
        if is_doc_comment(attr) {
            return Ok(None);
        }

        let span = attr.span().unwrap();

        let name = attr.path().segments.last().unwrap().ident.to_string();
        let name = name.as_str();

        let mut kind = match name {
            "label" => SubdiagnosticKind::Label,
            "note" => SubdiagnosticKind::Note,
            "note_once" => SubdiagnosticKind::NoteOnce,
            "help" => SubdiagnosticKind::Help,
            "help_once" => SubdiagnosticKind::HelpOnce,
            "warning" => SubdiagnosticKind::Warn,
            _ => {
                // Recover old `#[(multipart_)suggestion_*]` syntaxes
                // FIXME(#100717): remove
                if let Some(suggestion_kind) =
                    name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix)
                {
                    if suggestion_kind != SuggestionKind::Normal {
                        invalid_attr(attr)
                            .help(format!(
                                r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"#
                            ))
                            .emit();
                    }

                    SubdiagnosticKind::Suggestion {
                        suggestion_kind: SuggestionKind::Normal,
                        applicability: None,
                        code_field: new_code_ident(),
                        code_init: TokenStream::new(),
                    }
                } else if let Some(suggestion_kind) =
                    name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix)
                {
                    if suggestion_kind != SuggestionKind::Normal {
                        invalid_attr(attr)
                            .help(format!(
                                r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"#
                            ))
                            .emit();
                    }

                    SubdiagnosticKind::MultipartSuggestion {
                        suggestion_kind: SuggestionKind::Normal,
                        applicability: None,
                    }
                } else {
                    throw_invalid_attr!(attr);
                }
            }
        };

        let list = match &attr.meta {
            Meta::List(list) => {
                // An attribute with properties, such as `#[suggestion(code = "...")]` or
                // `#[error("message")]`
                list
            }
            Meta::Path(_) => {
                // An attribute without a message or other properties, such as `#[note]` - return
                // without further processing.
                //
                // Only allow this if there are no mandatory properties, such as `code = "..."` in
                // `#[suggestion(...)]`
                match kind {
                    SubdiagnosticKind::Label
                    | SubdiagnosticKind::Note
                    | SubdiagnosticKind::NoteOnce
                    | SubdiagnosticKind::Help
                    | SubdiagnosticKind::HelpOnce
                    | SubdiagnosticKind::Warn
                    | SubdiagnosticKind::MultipartSuggestion { .. } => {
                        return Ok(Some(SubdiagnosticVariant { kind, message: None }));
                    }
                    SubdiagnosticKind::Suggestion { .. } => {
                        throw_span_err!(span, "suggestion without `code = \"...\"`")
                    }
                }
            }
            _ => {
                throw_invalid_attr!(attr)
            }
        };

        let mut code = None;
        let mut suggestion_kind = None;

        let mut message = None;

        list.parse_args_with(|input: ParseStream<'_>| {
            let mut is_first = true;
            while !input.is_empty() {
                // Try to parse an inline diagnostic message
                if input.peek(LitStr) {
                    let inline_message = input.parse::<LitStr>()?;
                    if !inline_message.suffix().is_empty() {
                        span_err(
                            inline_message.span().unwrap(),
                            "Inline message is not allowed to have a suffix",
                        ).emit();
                    }
                    if !input.is_empty() { input.parse::<Token![,]>()?; }
                    if is_first {
                        message = Some(Message { attr_span: attr.span(), message_span: inline_message.span(), value: inline_message.value() });
                        is_first = false;
                    } else {
                        span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit();
                    }
                    continue
                }
                is_first = false;

                // Try to parse an argument
                let arg_name: Path = input.parse::<Path>()?;
                let arg_name_span = arg_name.span().unwrap();
                match (arg_name.require_ident()?.to_string().as_str(), &mut kind) {
                    ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
                        let code_init = build_suggestion_code(
                            &code_field,
                            &input,
                            fields,
                            AllowMultipleAlternatives::Yes,
                        )?;
                        code.set_once(code_init, arg_name_span);
                    }
                    (
                        "applicability",
                        SubdiagnosticKind::Suggestion { applicability, .. }
                        | SubdiagnosticKind::MultipartSuggestion { applicability, .. },
                    ) => {
                        input.parse::<Token![=]>()?;
                        let value = input.parse::<LitStr>()?;
                        let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
                            span_err(value.span().unwrap(), "invalid applicability").emit();
                            Applicability::Unspecified
                        });
                        applicability.set_once(value, span);
                    }
                    (
                        "style",
                        SubdiagnosticKind::Suggestion { .. }
                        | SubdiagnosticKind::MultipartSuggestion { .. },
                    ) => {
                        input.parse::<Token![=]>()?;
                        let value = input.parse::<LitStr>()?;

                        let value = value.value().parse().unwrap_or_else(|()| {
                            span_err(value.span().unwrap(), "invalid suggestion style")
                                .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`")
                                .emit();
                            SuggestionKind::Normal
                        });

                        suggestion_kind.set_once(value, span);
                    }


                    // Invalid nested attribute
                    (_, SubdiagnosticKind::Suggestion { .. }) => {
                        span_err(arg_name_span, "invalid nested attribute")
                            .help(
                                "only `style`, `code` and `applicability` are valid nested attributes",
                            )
                            .emit();
                        // Consume the rest of the input to avoid spamming errors
                        let _ = input.parse::<TokenStream>();
                    }
                    (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
                        span_err(arg_name_span, "invalid nested attribute")
                            .help("only `style` and `applicability` are valid nested attributes")
                            .emit();
                        // Consume the rest of the input to avoid spamming errors
                        let _ = input.parse::<TokenStream>();
                    }
                    _ => {
                        span_err(arg_name_span, "no nested attribute expected here").emit();
                        // Consume the rest of the input to avoid spamming errors
                        let _ = input.parse::<TokenStream>();
                    }
                }

                if input.is_empty() { break }
                input.parse::<Token![,]>()?;
            }
            Ok(())
        })?;

        match kind {
            SubdiagnosticKind::Suggestion {
                ref code_field,
                ref mut code_init,
                suggestion_kind: ref mut kind_field,
                ..
            } => {
                if let Some(kind) = suggestion_kind.value() {
                    *kind_field = kind;
                }

                *code_init = if let Some(init) = code.value() {
                    init
                } else {
                    span_err(span, "suggestion without `code = \"...\"`").emit();
                    quote! { let #code_field = std::iter::empty(); }
                };
            }
            SubdiagnosticKind::MultipartSuggestion {
                suggestion_kind: ref mut kind_field, ..
            } => {
                if let Some(kind) = suggestion_kind.value() {
                    *kind_field = kind;
                }
            }
            SubdiagnosticKind::Label
            | SubdiagnosticKind::Note
            | SubdiagnosticKind::NoteOnce
            | SubdiagnosticKind::Help
            | SubdiagnosticKind::HelpOnce
            | SubdiagnosticKind::Warn => {}
        }

        Ok(Some(SubdiagnosticVariant { kind, message }))
    }
}

impl quote::IdentFragment for SubdiagnosticKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SubdiagnosticKind::Label => write!(f, "label"),
            SubdiagnosticKind::Note => write!(f, "note"),
            SubdiagnosticKind::NoteOnce => write!(f, "note_once"),
            SubdiagnosticKind::Help => write!(f, "help"),
            SubdiagnosticKind::HelpOnce => write!(f, "help_once"),
            SubdiagnosticKind::Warn => write!(f, "warn"),
            SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"),
            SubdiagnosticKind::MultipartSuggestion { .. } => {
                write!(f, "multipart_suggestion_with_style")
            }
        }
    }

    fn span(&self) -> Option<proc_macro2::Span> {
        None
    }
}

/// Returns `true` if `field` should generate a `arg` call rather than any other diagnostic
/// call (like `span_label`).
pub(super) fn should_generate_arg(field: &Field) -> bool {
    // Perhaps this should be an exhaustive list...
    field.attrs.iter().all(|attr| is_doc_comment(attr))
}

pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
    attr.path().segments.last().unwrap().ident == "doc"
}
