//! This module defines traits for attribute parsers, little state machines that recognize and parse
//! attributes out of a longer list of attributes. The main trait is called [`AttributeParser`].
//! You can find more docs about [`AttributeParser`]s on the trait itself.
//! However, for many types of attributes, implementing [`AttributeParser`] is not necessary.
//! It allows for a lot of flexibility you might not want.
//!
//! Specifically, you might not care about managing the state of your [`AttributeParser`]
//! state machine yourself. In this case you can choose to implement:
//!
//! - [`SingleAttributeParser`]: makes it easy to implement an attribute which should error if it
//! appears more than once in a list of attributes
//! - [`CombineAttributeParser`]: makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.

use std::marker::PhantomData;

use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;

use crate::context::{AcceptContext, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;

pub(crate) mod allow_unstable;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod deprecation;
pub(crate) mod dummy;
pub(crate) mod inline;
pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod non_exhaustive;
pub(crate) mod path;
pub(crate) mod repr;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;
pub(crate) mod stability;
pub(crate) mod test_attrs;
pub(crate) mod traits;
pub(crate) mod transparency;
pub(crate) mod util;

type AcceptFn<T, S> = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess, S>, &ArgParser<'_>);
type AcceptMapping<T, S> = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn<T, S>)];

/// An [`AttributeParser`] is a type which searches for syntactic attributes.
///
/// Parsers are often tiny state machines that gets to see all syntactical attributes on an item.
/// [`Default::default`] creates a fresh instance that sits in some kind of initial state, usually that the
/// attribute it is looking for was not yet seen.
///
/// Then, it defines what paths this group will accept in [`AttributeParser::ATTRIBUTES`].
/// These are listed as pairs, of symbols and function pointers. The function pointer will
/// be called when that attribute is found on an item, which can influence the state of the little
/// state machine.
///
/// Finally, after all attributes on an item have been seen, and possibly been accepted,
/// the [`finalize`](AttributeParser::finalize) functions for all attribute parsers are called. Each can then report
/// whether it has seen the attribute it has been looking for.
///
/// The state machine is automatically reset to parse attributes on the next item.
///
/// For a simpler attribute parsing interface, consider using [`SingleAttributeParser`]
/// or [`CombineAttributeParser`] instead.
pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
    /// The symbols for the attributes that this parser is interested in.
    ///
    /// If an attribute has this symbol, the `accept` function will be called on it.
    const ATTRIBUTES: AcceptMapping<Self, S>;

    /// The parser has gotten a chance to accept the attributes on an item,
    /// here it can produce an attribute.
    ///
    /// All finalize methods of all parsers are unconditionally called.
    /// This means you can't unconditionally return `Some` here,
    /// that'd be equivalent to unconditionally applying an attribute to
    /// every single syntax item that could have attributes applied to it.
    /// Your accept mappings should determine whether this returns something.
    fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind>;
}

/// Alternative to [`AttributeParser`] that automatically handles state management.
/// A slightly simpler and more restricted way to convert attributes.
/// Assumes that an attribute can only appear a single time on an item,
/// and errors when it sees more.
///
/// [`Single<T> where T: SingleAttributeParser`](Single) implements [`AttributeParser`].
///
/// [`SingleAttributeParser`] can only convert attributes one-to-one, and cannot combine multiple
/// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
    /// The single path of the attribute this parser accepts.
    ///
    /// If you need the parser to accept more than one path, use [`AttributeParser`] instead
    const PATH: &[Symbol];

    /// Configures the precedence of attributes with the same `PATH` on a syntax node.
    const ATTRIBUTE_ORDER: AttributeOrder;

    /// Configures what to do when when the same attribute is
    /// applied more than once on the same syntax node.
    ///
    /// [`ATTRIBUTE_ORDER`](Self::ATTRIBUTE_ORDER) specified which one is assumed to be correct,
    /// and this specified whether to, for example, warn or error on the other one.
    const ON_DUPLICATE: OnDuplicate<S>;

    /// The template this attribute parser should implement. Used for diagnostics.
    const TEMPLATE: AttributeTemplate;

    /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
}

/// Use in combination with [`SingleAttributeParser`].
/// `Single<T: SingleAttributeParser>` implements [`AttributeParser`].
pub(crate) struct Single<T: SingleAttributeParser<S>, S: Stage>(
    PhantomData<(S, T)>,
    Option<(AttributeKind, Span)>,
);

impl<T: SingleAttributeParser<S>, S: Stage> Default for Single<T, S> {
    fn default() -> Self {
        Self(Default::default(), Default::default())
    }
}

impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S> {
    const ATTRIBUTES: AcceptMapping<Self, S> = &[(
        T::PATH,
        <T as SingleAttributeParser<S>>::TEMPLATE,
        |group: &mut Single<T, S>, cx, args| {
            if let Some(pa) = T::convert(cx, args) {
                match T::ATTRIBUTE_ORDER {
                    // keep the first and report immediately. ignore this attribute
                    AttributeOrder::KeepInnermost => {
                        if let Some((_, unused)) = group.1 {
                            T::ON_DUPLICATE.exec::<T>(cx, cx.attr_span, unused);
                            return;
                        }
                    }
                    // keep the new one and warn about the previous,
                    // then replace
                    AttributeOrder::KeepOutermost => {
                        if let Some((_, used)) = group.1 {
                            T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
                        }
                    }
                }

                group.1 = Some((pa, cx.attr_span));
            }
        },
    )];

    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
        Some(self.1?.0)
    }
}

pub(crate) enum OnDuplicate<S: Stage> {
    /// Give a default warning
    Warn,

    /// Duplicates will be a warning, with a note that this will be an error in the future.
    WarnButFutureError,

    /// Give a default error
    Error,

    /// Ignore duplicates
    Ignore,

    /// Custom function called when a duplicate attribute is found.
    ///
    /// - `unused` is the span of the attribute that was unused or bad because of some
    ///   duplicate reason (see [`AttributeOrder`])
    /// - `used` is the span of the attribute that was used in favor of the unused attribute
    Custom(fn(cx: &AcceptContext<'_, '_, S>, used: Span, unused: Span)),
}

impl<S: Stage> OnDuplicate<S> {
    fn exec<P: SingleAttributeParser<S>>(
        &self,
        cx: &mut AcceptContext<'_, '_, S>,
        used: Span,
        unused: Span,
    ) {
        match self {
            OnDuplicate::Warn => cx.warn_unused_duplicate(used, unused),
            OnDuplicate::WarnButFutureError => cx.warn_unused_duplicate_future_error(used, unused),
            OnDuplicate::Error => {
                cx.emit_err(UnusedMultiple {
                    this: used,
                    other: unused,
                    name: Symbol::intern(
                        &P::PATH.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(".."),
                    ),
                });
            }
            OnDuplicate::Ignore => {}
            OnDuplicate::Custom(f) => f(cx, used, unused),
        }
    }
}

pub(crate) enum AttributeOrder {
    /// Duplicates after the innermost instance of the attribute will be an error/warning.
    /// Only keep the lowest attribute.
    ///
    /// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
    /// further above the lowest one:
    /// ```
    /// #[stable(since="1.0")] //~ WARNING duplicated attribute
    /// #[stable(since="2.0")]
    /// ```
    KeepInnermost,

    /// Duplicates before the outermost instance of the attribute will be an error/warning.
    /// Only keep the highest attribute.
    ///
    /// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
    /// below the highest one:
    /// ```
    /// #[path="foo.rs"]
    /// #[path="bar.rs"] //~ WARNING duplicated attribute
    /// ```
    KeepOutermost,
}

/// An even simpler version of [`SingleAttributeParser`]:
/// now automatically check that there are no arguments provided to the attribute.
///
/// [`WithoutArgs<T> where T: NoArgsAttributeParser`](WithoutArgs) implements [`SingleAttributeParser`].
//
pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
    const PATH: &[Symbol];
    const ON_DUPLICATE: OnDuplicate<S>;

    /// Create the [`AttributeKind`] given attribute's [`Span`].
    const CREATE: fn(Span) -> AttributeKind;
}

pub(crate) struct WithoutArgs<T: NoArgsAttributeParser<S>, S: Stage>(PhantomData<(S, T)>);

impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {
    fn default() -> Self {
        Self(Default::default())
    }
}

impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
    const PATH: &[Symbol] = T::PATH;
    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
    const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
    const TEMPLATE: AttributeTemplate = template!(Word);

    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
        if let Err(span) = args.no_args() {
            cx.expected_no_args(span);
        }
        Some(T::CREATE(cx.attr_span))
    }
}

type ConvertFn<E> = fn(ThinVec<E>, Span) -> AttributeKind;

/// Alternative to [`AttributeParser`] that automatically handles state management.
/// If multiple attributes appear on an element, combines the values of each into a
/// [`ThinVec`].
/// [`Combine<T> where T: CombineAttributeParser`](Combine) implements [`AttributeParser`].
///
/// [`CombineAttributeParser`] can only convert a single kind of attribute, and cannot combine multiple
/// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
    const PATH: &[rustc_span::Symbol];

    type Item;
    /// A function that converts individual items (of type [`Item`](Self::Item)) into the final attribute.
    ///
    /// For example, individual representations fomr `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`,
    ///  where `x` is a vec of these individual reprs.
    const CONVERT: ConvertFn<Self::Item>;

    /// The template this attribute parser should implement. Used for diagnostics.
    const TEMPLATE: AttributeTemplate;

    /// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
    fn extend<'c>(
        cx: &'c mut AcceptContext<'_, '_, S>,
        args: &'c ArgParser<'_>,
    ) -> impl IntoIterator<Item = Self::Item> + 'c;
}

/// Use in combination with [`CombineAttributeParser`].
/// `Combine<T: CombineAttributeParser>` implements [`AttributeParser`].
pub(crate) struct Combine<T: CombineAttributeParser<S>, S: Stage> {
    phantom: PhantomData<(S, T)>,
    /// A list of all items produced by parsing attributes so far. One attribute can produce any amount of items.
    items: ThinVec<<T as CombineAttributeParser<S>>::Item>,
    /// The full span of the first attribute that was encountered.
    first_span: Option<Span>,
}

impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> {
    fn default() -> Self {
        Self {
            phantom: Default::default(),
            items: Default::default(),
            first_span: Default::default(),
        }
    }
}

impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S> {
    const ATTRIBUTES: AcceptMapping<Self, S> = &[(
        T::PATH,
        <T as CombineAttributeParser<S>>::TEMPLATE,
        |group: &mut Combine<T, S>, cx, args| {
            // Keep track of the span of the first attribute, for diagnostics
            group.first_span.get_or_insert(cx.attr_span);
            group.items.extend(T::extend(cx, args))
        },
    )];

    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
        if let Some(first_span) = self.first_span {
            Some(T::CONVERT(self.items, first_span))
        } else {
            None
        }
    }
}
