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::meta::ParseNestedMeta;
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,
};

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>;

pub(crate) trait HasFieldMap {
    /// Returns the binding for the field with the given name, if it exists on the type.
    fn get_field_binding(&self, field: &String) -> Option<&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(slug = "parser-not-javascript-eq", 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!`.
    fn build_format(&self, 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 self.get_field_binding(&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: ParseNestedMeta<'_>,
    allow_multiple: AllowMultipleAlternatives,
) -> syn::Result<Vec<LitStr>> {
    let values = if let Ok(val) = nested.value() {
        vec![val.parse()?]
    } else {
        let content;
        parenthesized!(content in nested.input);

        if let AllowMultipleAlternatives::No = allow_multiple {
            span_err(
                nested.input.span().unwrap(),
                "expected exactly one string literal for `code = ...`",
            )
            .emit();
            vec![]
        } else {
            let literals = Punctuated::<LitStr, Token![,]>::parse_terminated(&content);

            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![]
                }
            }
        }
    };

    Ok(values)
}

/// 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: ParseNestedMeta<'_>,
    fields: &impl HasFieldMap,
    allow_multiple: AllowMultipleAlternatives,
) -> TokenStream {
    let values = match parse_suggestion_values(nested, allow_multiple) {
        Ok(x) => x,
        Err(e) => return e.into_compile_error(),
    };

    if let AllowMultipleAlternatives::Yes = allow_multiple {
        let formatted_strings: Vec<_> = values
            .into_iter()
            .map(|value| fields.build_format(&value.value(), value.span()))
            .collect();
        quote! { let #code_field = [#(#formatted_strings),*].into_iter(); }
    } else if let [value] = values.as_slice() {
        let formatted_str = fields.build_format(&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) slug: Option<Path>,
    pub(super) no_span: bool,
}

impl SubdiagnosticVariant {
    /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`,
    /// `#[error(parser::add_paren, no_span)]` or `#[suggestion(code = "...")]`. Returns the
    /// `SubdiagnosticKind` and the diagnostic slug, if specified.
    pub(super) fn from_attr(
        attr: &Attribute,
        fields: &impl HasFieldMap,
    ) -> 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(some::slug)]`
                list
            }
            Meta::Path(_) => {
                // An attribute without a slug 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, slug: None, no_span: false }));
                    }
                    SubdiagnosticKind::Suggestion { .. } => {
                        throw_span_err!(span, "suggestion without `code = \"...\"`")
                    }
                }
            }
            _ => {
                throw_invalid_attr!(attr)
            }
        };

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

        let mut first = true;
        let mut slug = None;
        let mut no_span = false;

        list.parse_nested_meta(|nested| {
            if nested.input.is_empty() || nested.input.peek(Token![,]) {
                if first {
                    slug = Some(nested.path);
                } else if nested.path.is_ident("no_span") {
                    no_span = true;
                } else {
                    span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit();
                }

                first = false;
                return Ok(());
            }

            first = false;

            let nested_name = nested.path.segments.last().unwrap().ident.to_string();
            let nested_name = nested_name.as_str();

            let path_span = nested.path.span().unwrap();
            let val_span = nested.input.span().unwrap();

            macro_rules! get_string {
                () => {{
                    let Ok(value) = nested.value().and_then(|x| x.parse::<LitStr>()) else {
                        span_err(val_span, "expected `= \"xxx\"`").emit();
                        return Ok(());
                    };
                    value
                }};
            }

            let mut has_errors = false;
            let input = nested.input;

            match (nested_name, &mut kind) {
                ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
                    let code_init = build_suggestion_code(
                        code_field,
                        nested,
                        fields,
                        AllowMultipleAlternatives::Yes,
                    );
                    code.set_once(code_init, path_span);
                }
                (
                    "applicability",
                    SubdiagnosticKind::Suggestion { applicability, .. }
                    | SubdiagnosticKind::MultipartSuggestion { applicability, .. },
                ) => {
                    let value = get_string!();
                    let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
                        span_err(value.span().unwrap(), "invalid applicability").emit();
                        has_errors = true;
                        Applicability::Unspecified
                    });
                    applicability.set_once(value, span);
                }
                (
                    "style",
                    SubdiagnosticKind::Suggestion { .. }
                    | SubdiagnosticKind::MultipartSuggestion { .. },
                ) => {
                    let value = get_string!();

                    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();
                        has_errors = true;
                        SuggestionKind::Normal
                    });

                    suggestion_kind.set_once(value, span);
                }

                // Invalid nested attribute
                (_, SubdiagnosticKind::Suggestion { .. }) => {
                    span_err(path_span, "invalid nested attribute")
                        .help(
                            "only `no_span`, `style`, `code` and `applicability` are valid nested attributes",
                        )
                        .emit();
                    has_errors = true;
                }
                (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
                    span_err(path_span, "invalid nested attribute")
                        .help("only `no_span`, `style` and `applicability` are valid nested attributes")
                        .emit();
                    has_errors = true;
                }
                _ => {
                    span_err(path_span, "only `no_span` is a valid nested attribute").emit();
                    has_errors = true;
                }
            }

            if has_errors {
                // Consume the rest of the input to avoid spamming errors
                let _ = input.parse::<TokenStream>();
            }

            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, slug, no_span }))
    }
}

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"
}
