//! Functions dealing with attributes and meta items.

pub mod data_structures;
pub mod version;

use std::fmt::Debug;
use std::sync::atomic::{AtomicU32, Ordering};

use rustc_index::bit_set::GrowableBitSet;
use rustc_span::{Ident, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};
use thin_vec::{ThinVec, thin_vec};

use crate::AttrItemKind;
use crate::ast::{
    AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,
    Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
    PathSegment, Safety,
};
use crate::token::{
    self, CommentKind, Delimiter, DocFragmentKind, InvisibleOrigin, MetaVarKind, Token,
};
use crate::tokenstream::{
    DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenStreamIter, TokenTree,
};
use crate::util::comments;
use crate::util::literal::escape_string_symbol;

pub struct MarkedAttrs(GrowableBitSet<AttrId>);

impl MarkedAttrs {
    pub fn new() -> Self {
        // We have no idea how many attributes there will be, so just
        // initiate the vectors with 0 bits. We'll grow them as necessary.
        MarkedAttrs(GrowableBitSet::new_empty())
    }

    pub fn mark(&mut self, attr: &Attribute) {
        self.0.insert(attr.id);
    }

    pub fn is_marked(&self, attr: &Attribute) -> bool {
        self.0.contains(attr.id)
    }
}

pub struct AttrIdGenerator(AtomicU32);

impl AttrIdGenerator {
    pub fn new() -> Self {
        AttrIdGenerator(AtomicU32::new(0))
    }

    pub fn mk_attr_id(&self) -> AttrId {
        let id = self.0.fetch_add(1, Ordering::Relaxed);
        assert!(id != u32::MAX);
        AttrId::from_u32(id)
    }
}

impl Attribute {
    pub fn get_normal_item(&self) -> &AttrItem {
        match &self.kind {
            AttrKind::Normal(normal) => &normal.item,
            AttrKind::DocComment(..) => panic!("unexpected doc comment"),
        }
    }

    /// Replaces the arguments of this attribute with new arguments `AttrItemKind`.
    /// This is useful for making this attribute into a trace attribute, and should otherwise be avoided.
    pub fn replace_args(&mut self, new_args: AttrItemKind) {
        match &mut self.kind {
            AttrKind::Normal(normal) => normal.item.args = new_args,
            AttrKind::DocComment(..) => panic!("unexpected doc comment"),
        }
    }

    pub fn unwrap_normal_item(self) -> AttrItem {
        match self.kind {
            AttrKind::Normal(normal) => normal.item,
            AttrKind::DocComment(..) => panic!("unexpected doc comment"),
        }
    }
}

impl AttributeExt for Attribute {
    fn id(&self) -> AttrId {
        self.id
    }

    fn value_span(&self) -> Option<Span> {
        match &self.kind {
            AttrKind::Normal(normal) => match &normal.item.args.unparsed_ref()? {
                AttrArgs::Eq { expr, .. } => Some(expr.span),
                _ => None,
            },
            AttrKind::DocComment(..) => None,
        }
    }

    /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
    /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
    /// a doc comment) will return `false`.
    fn is_doc_comment(&self) -> Option<Span> {
        match self.kind {
            AttrKind::Normal(..) => None,
            AttrKind::DocComment(..) => Some(self.span),
        }
    }

    /// For a single-segment attribute, returns its name; otherwise, returns `None`.
    fn name(&self) -> Option<Symbol> {
        match &self.kind {
            AttrKind::Normal(normal) => {
                if let [ident] = &*normal.item.path.segments {
                    Some(ident.ident.name)
                } else {
                    None
                }
            }
            AttrKind::DocComment(..) => None,
        }
    }

    fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>> {
        match &self.kind {
            AttrKind::Normal(p) => {
                Some(p.item.path.segments.iter().map(|i| i.ident.name).collect())
            }
            AttrKind::DocComment(_, _) => None,
        }
    }

    fn path_span(&self) -> Option<Span> {
        match &self.kind {
            AttrKind::Normal(attr) => Some(attr.item.path.span),
            AttrKind::DocComment(_, _) => None,
        }
    }

    fn path_matches(&self, name: &[Symbol]) -> bool {
        match &self.kind {
            AttrKind::Normal(normal) => {
                normal.item.path.segments.len() == name.len()
                    && normal
                        .item
                        .path
                        .segments
                        .iter()
                        .zip(name)
                        .all(|(s, n)| s.args.is_none() && s.ident.name == *n)
            }
            AttrKind::DocComment(..) => false,
        }
    }

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

    fn is_word(&self) -> bool {
        if let AttrKind::Normal(normal) = &self.kind {
            matches!(normal.item.args, AttrItemKind::Unparsed(AttrArgs::Empty))
        } else {
            false
        }
    }

    /// Returns a list of meta items if the attribute is delimited with parenthesis:
    ///
    /// ```text
    /// #[attr(a, b = "c")] // Returns `Some()`.
    /// #[attr = ""] // Returns `None`.
    /// #[attr] // Returns `None`.
    /// ```
    fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
        match &self.kind {
            AttrKind::Normal(normal) => normal.item.meta_item_list(),
            AttrKind::DocComment(..) => None,
        }
    }

    /// Returns the string value in:
    ///
    /// ```text
    /// #[attribute = "value"]
    ///               ^^^^^^^
    /// ```
    ///
    /// It returns `None` in any other cases, including doc comments if they
    /// are not under the form `#[doc = "..."]`.
    ///
    /// It also returns `None` for:
    ///
    /// ```text
    /// #[attr("value")]
    /// ```
    fn value_str(&self) -> Option<Symbol> {
        match &self.kind {
            AttrKind::Normal(normal) => normal.item.value_str(),
            AttrKind::DocComment(..) => None,
        }
    }

    /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
    /// * `///doc` returns `Some(("doc", DocFragmentKind::Sugared(CommentKind::Line)))`.
    /// * `/** doc */` returns `Some(("doc", DocFragmentKind::Sugared(CommentKind::Block)))`.
    /// * `#[doc = "doc"]` returns `Some(("doc", DocFragmentKind::Raw))`.
    /// * `#[doc(...)]` returns `None`.
    fn doc_str_and_fragment_kind(&self) -> Option<(Symbol, DocFragmentKind)> {
        match &self.kind {
            AttrKind::DocComment(kind, data) => Some((*data, DocFragmentKind::Sugared(*kind))),
            AttrKind::Normal(normal) if normal.item.path == sym::doc => {
                if let Some(value) = normal.item.value_str()
                    && let Some(value_span) = normal.item.value_span()
                {
                    Some((value, DocFragmentKind::Raw(value_span)))
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    /// Returns the documentation if this is a doc comment or a sugared doc comment.
    /// * `///doc` returns `Some("doc")`.
    /// * `#[doc = "doc"]` returns `Some("doc")`.
    /// * `#[doc(...)]` returns `None`.
    fn doc_str(&self) -> Option<Symbol> {
        match &self.kind {
            AttrKind::DocComment(.., data) => Some(*data),
            AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
            _ => None,
        }
    }

    fn deprecation_note(&self) -> Option<Ident> {
        match &self.kind {
            AttrKind::Normal(normal) if normal.item.path == sym::deprecated => {
                let meta = &normal.item;

                // #[deprecated = "..."]
                if let Some(s) = meta.value_str() {
                    return Some(Ident { name: s, span: meta.span() });
                }

                // #[deprecated(note = "...")]
                if let Some(list) = meta.meta_item_list() {
                    for nested in list {
                        if let Some(mi) = nested.meta_item()
                            && mi.path == sym::note
                            && let Some(s) = mi.value_str()
                        {
                            return Some(Ident { name: s, span: mi.span });
                        }
                    }
                }

                None
            }
            _ => None,
        }
    }

    fn doc_resolution_scope(&self) -> Option<AttrStyle> {
        match &self.kind {
            AttrKind::DocComment(..) => Some(self.style),
            AttrKind::Normal(normal)
                if normal.item.path == sym::doc && normal.item.value_str().is_some() =>
            {
                Some(self.style)
            }
            _ => None,
        }
    }

    fn is_automatically_derived_attr(&self) -> bool {
        self.has_name(sym::automatically_derived)
    }

    fn is_doc_hidden(&self) -> bool {
        self.has_name(sym::doc)
            && self.meta_item_list().is_some_and(|l| list_contains_name(&l, sym::hidden))
    }

    fn is_doc_keyword_or_attribute(&self) -> bool {
        if self.has_name(sym::doc)
            && let Some(items) = self.meta_item_list()
        {
            for item in items {
                if item.has_name(sym::keyword) || item.has_name(sym::attribute) {
                    return true;
                }
            }
        }
        false
    }

    fn is_rustc_doc_primitive(&self) -> bool {
        self.has_name(sym::rustc_doc_primitive)
    }
}

impl Attribute {
    pub fn style(&self) -> AttrStyle {
        self.style
    }

    pub fn may_have_doc_links(&self) -> bool {
        self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
            || self.deprecation_note().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
    }

    /// Extracts the MetaItem from inside this Attribute.
    pub fn meta(&self) -> Option<MetaItem> {
        match &self.kind {
            AttrKind::Normal(normal) => normal.item.meta(self.span),
            AttrKind::DocComment(..) => None,
        }
    }

    pub fn meta_kind(&self) -> Option<MetaItemKind> {
        match &self.kind {
            AttrKind::Normal(normal) => normal.item.meta_kind(),
            AttrKind::DocComment(..) => None,
        }
    }

    pub fn token_trees(&self) -> Vec<TokenTree> {
        match self.kind {
            AttrKind::Normal(ref normal) => normal
                .tokens
                .as_ref()
                .unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
                .to_attr_token_stream()
                .to_token_trees(),
            AttrKind::DocComment(comment_kind, data) => vec![TokenTree::token_alone(
                token::DocComment(comment_kind, self.style, data),
                self.span,
            )],
        }
    }
}

impl AttrItem {
    pub fn span(&self) -> Span {
        self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
    }

    pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
        match &self.args.unparsed_ref()? {
            AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
                MetaItemKind::list_from_tokens(args.tokens.clone())
            }
            AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None,
        }
    }

    /// Returns the string value in:
    ///
    /// ```text
    /// #[attribute = "value"]
    ///               ^^^^^^^
    /// ```
    ///
    /// It returns `None` in any other cases like:
    ///
    /// ```text
    /// #[attr("value")]
    /// ```
    fn value_str(&self) -> Option<Symbol> {
        match &self.args.unparsed_ref()? {
            AttrArgs::Eq { expr, .. } => match expr.kind {
                ExprKind::Lit(token_lit) => {
                    LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
                }
                _ => None,
            },
            AttrArgs::Delimited(_) | AttrArgs::Empty => None,
        }
    }

    /// Returns the span in:
    ///
    /// ```text
    /// #[attribute = "value"]
    ///               ^^^^^^^
    /// ```
    ///
    /// It returns `None` in any other cases like:
    ///
    /// ```text
    /// #[attr("value")]
    /// ```
    fn value_span(&self) -> Option<Span> {
        match &self.args.unparsed_ref()? {
            AttrArgs::Eq { expr, .. } => Some(expr.span),
            AttrArgs::Delimited(_) | AttrArgs::Empty => None,
        }
    }

    pub fn meta(&self, span: Span) -> Option<MetaItem> {
        Some(MetaItem {
            unsafety: Safety::Default,
            path: self.path.clone(),
            kind: self.meta_kind()?,
            span,
        })
    }

    pub fn meta_kind(&self) -> Option<MetaItemKind> {
        MetaItemKind::from_attr_args(self.args.unparsed_ref()?)
    }
}

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

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

    pub fn has_name(&self, name: Symbol) -> bool {
        self.path == name
    }

    pub fn is_word(&self) -> bool {
        matches!(self.kind, MetaItemKind::Word)
    }

    pub fn meta_item_list(&self) -> Option<&[MetaItemInner]> {
        match &self.kind {
            MetaItemKind::List(l) => Some(&**l),
            _ => None,
        }
    }

    /// ```text
    /// Example:
    ///     #[attribute(name = "value")]
    ///                 ^^^^^^^^^^^^^^
    /// ```
    pub fn name_value_literal(&self) -> Option<&MetaItemLit> {
        match &self.kind {
            MetaItemKind::NameValue(v) => Some(v),
            _ => None,
        }
    }

    /// This is used in case you want the value span instead of the whole attribute. Example:
    ///
    /// ```text
    /// #[doc(alias = "foo")]
    /// ```
    ///
    /// In here, it'll return a span for `"foo"`.
    pub fn name_value_literal_span(&self) -> Option<Span> {
        Some(self.name_value_literal()?.span)
    }

    /// Returns the string value in:
    ///
    /// ```text
    /// #[attribute = "value"]
    ///               ^^^^^^^
    /// ```
    ///
    /// It returns `None` in any other cases like:
    ///
    /// ```text
    /// #[attr("value")]
    /// ```
    pub fn value_str(&self) -> Option<Symbol> {
        match &self.kind {
            MetaItemKind::NameValue(v) => v.kind.str(),
            _ => None,
        }
    }

    fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option<MetaItem> {
        // FIXME: Share code with `parse_path`.
        let tt = iter.next().map(|tt| TokenTree::uninterpolate(tt));
        let path = match tt.as_deref() {
            Some(&TokenTree::Token(
                Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span },
                _,
            )) => 'arm: {
                let mut segments = if let &token::Ident(name, _) = kind {
                    if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
                        iter.peek()
                    {
                        iter.next();
                        thin_vec![PathSegment::from_ident(Ident::new(name, span))]
                    } else {
                        break 'arm Path::from_ident(Ident::new(name, span));
                    }
                } else {
                    thin_vec![PathSegment::path_root(span)]
                };
                loop {
                    let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
                        iter.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
                    else {
                        return None;
                    };
                    segments.push(PathSegment::from_ident(Ident::new(name, span)));
                    let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = iter.peek()
                    else {
                        break;
                    };
                    iter.next();
                }
                let span = span.with_hi(segments.last().unwrap().ident.span.hi());
                Path { span, segments, tokens: None }
            }
            Some(TokenTree::Delimited(
                _span,
                _spacing,
                Delimiter::Invisible(InvisibleOrigin::MetaVar(
                    MetaVarKind::Meta { .. } | MetaVarKind::Path,
                )),
                _stream,
            )) => {
                // This path is currently unreachable in the test suite.
                unreachable!()
            }
            Some(TokenTree::Token(Token { kind, .. }, _)) if kind.is_delim() => {
                panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tt);
            }
            _ => return None,
        };
        let list_closing_paren_pos = iter.peek().map(|tt| tt.span().hi());
        let kind = MetaItemKind::from_tokens(iter)?;
        let hi = match &kind {
            MetaItemKind::NameValue(lit) => lit.span.hi(),
            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
            _ => path.span.hi(),
        };
        let span = path.span.with_hi(hi);
        // FIXME: This parses `unsafe()` not as unsafe attribute syntax in `MetaItem`,
        // but as a parenthesized list. This (and likely `MetaItem`) should be changed in
        // such a way that builtin macros don't accept extraneous `unsafe()`.
        Some(MetaItem { unsafety: Safety::Default, path, kind, span })
    }
}

impl MetaItemKind {
    // public because it can be called in the hir
    pub fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<MetaItemInner>> {
        let mut iter = tokens.iter();
        let mut result = ThinVec::new();
        while iter.peek().is_some() {
            let item = MetaItemInner::from_tokens(&mut iter)?;
            result.push(item);
            match iter.next() {
                None | Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) => {}
                _ => return None,
            }
        }
        Some(result)
    }

    fn name_value_from_tokens(iter: &mut TokenStreamIter<'_>) -> Option<MetaItemKind> {
        match iter.next() {
            Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => {
                MetaItemKind::name_value_from_tokens(&mut inner_tokens.iter())
            }
            Some(TokenTree::Token(token, _)) => {
                MetaItemLit::from_token(token).map(MetaItemKind::NameValue)
            }
            _ => None,
        }
    }

    fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option<MetaItemKind> {
        match iter.peek() {
            Some(TokenTree::Delimited(.., Delimiter::Parenthesis, inner_tokens)) => {
                let inner_tokens = inner_tokens.clone();
                iter.next();
                MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
            }
            Some(TokenTree::Delimited(..)) => None,
            Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
                iter.next();
                MetaItemKind::name_value_from_tokens(iter)
            }
            _ => Some(MetaItemKind::Word),
        }
    }

    fn from_attr_args(args: &AttrArgs) -> Option<MetaItemKind> {
        match args {
            AttrArgs::Empty => Some(MetaItemKind::Word),
            AttrArgs::Delimited(DelimArgs { dspan: _, delim: Delimiter::Parenthesis, tokens }) => {
                MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
            }
            AttrArgs::Delimited(..) => None,
            AttrArgs::Eq { expr, .. } => match expr.kind {
                ExprKind::Lit(token_lit) => {
                    // Turn failures to `None`, we'll get parse errors elsewhere.
                    MetaItemLit::from_token_lit(token_lit, expr.span)
                        .ok()
                        .map(|lit| MetaItemKind::NameValue(lit))
                }
                _ => None,
            },
        }
    }
}

impl MetaItemInner {
    pub fn span(&self) -> Span {
        match self {
            MetaItemInner::MetaItem(item) => item.span,
            MetaItemInner::Lit(lit) => lit.span,
        }
    }

    /// For a single-segment meta item, returns its identifier; otherwise, returns `None`.
    pub fn ident(&self) -> Option<Ident> {
        self.meta_item().and_then(|meta_item| meta_item.ident())
    }

    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
    pub fn name(&self) -> Option<Symbol> {
        self.ident().map(|ident| ident.name)
    }

    /// Returns `true` if this list item is a MetaItem with a name of `name`.
    pub fn has_name(&self, name: Symbol) -> bool {
        self.meta_item().is_some_and(|meta_item| meta_item.has_name(name))
    }

    /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
    pub fn is_word(&self) -> bool {
        self.meta_item().is_some_and(|meta_item| meta_item.is_word())
    }

    /// Gets a list of inner meta items from a list `MetaItem` type.
    pub fn meta_item_list(&self) -> Option<&[MetaItemInner]> {
        self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
    }

    /// If it's a singleton list of the form `foo(lit)`, returns the `foo` and
    /// the `lit`.
    pub fn singleton_lit_list(&self) -> Option<(Symbol, &MetaItemLit)> {
        self.meta_item().and_then(|meta_item| {
            meta_item.meta_item_list().and_then(|meta_item_list| {
                if meta_item_list.len() == 1
                    && let Some(ident) = meta_item.ident()
                    && let Some(lit) = meta_item_list[0].lit()
                {
                    return Some((ident.name, lit));
                }
                None
            })
        })
    }

    /// See [`MetaItem::name_value_literal_span`].
    pub fn name_value_literal_span(&self) -> Option<Span> {
        self.meta_item()?.name_value_literal_span()
    }

    /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
    /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
    pub fn value_str(&self) -> Option<Symbol> {
        self.meta_item().and_then(|meta_item| meta_item.value_str())
    }

    /// Returns the `MetaItemLit` if `self` is a `MetaItemInner::Literal`s.
    pub fn lit(&self) -> Option<&MetaItemLit> {
        match self {
            MetaItemInner::Lit(lit) => Some(lit),
            _ => None,
        }
    }

    /// Returns the bool if `self` is a boolean `MetaItemInner::Literal`.
    pub fn boolean_literal(&self) -> Option<bool> {
        match self {
            MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => Some(*b),
            _ => None,
        }
    }

    /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem` or if it's
    /// `MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`.
    pub fn meta_item_or_bool(&self) -> Option<&MetaItemInner> {
        match self {
            MetaItemInner::MetaItem(_item) => Some(self),
            MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. }) => Some(self),
            _ => None,
        }
    }

    /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem`.
    pub fn meta_item(&self) -> Option<&MetaItem> {
        match self {
            MetaItemInner::MetaItem(item) => Some(item),
            _ => None,
        }
    }

    /// Returns `true` if the variant is `MetaItem`.
    pub fn is_meta_item(&self) -> bool {
        self.meta_item().is_some()
    }

    fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option<MetaItemInner> {
        match iter.peek() {
            Some(TokenTree::Token(token, _)) if let Some(lit) = MetaItemLit::from_token(token) => {
                iter.next();
                return Some(MetaItemInner::Lit(lit));
            }
            Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => {
                iter.next();
                return MetaItemInner::from_tokens(&mut inner_tokens.iter());
            }
            _ => {}
        }
        MetaItem::from_tokens(iter).map(MetaItemInner::MetaItem)
    }
}

pub fn mk_doc_comment(
    g: &AttrIdGenerator,
    comment_kind: CommentKind,
    style: AttrStyle,
    data: Symbol,
    span: Span,
) -> Attribute {
    Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
}

fn mk_attr(
    g: &AttrIdGenerator,
    style: AttrStyle,
    unsafety: Safety,
    path: Path,
    args: AttrArgs,
    span: Span,
) -> Attribute {
    mk_attr_from_item(
        g,
        AttrItem { unsafety, path, args: AttrItemKind::Unparsed(args), tokens: None },
        None,
        style,
        span,
    )
}

pub fn mk_attr_from_item(
    g: &AttrIdGenerator,
    item: AttrItem,
    tokens: Option<LazyAttrTokenStream>,
    style: AttrStyle,
    span: Span,
) -> Attribute {
    Attribute {
        kind: AttrKind::Normal(Box::new(NormalAttr { item, tokens })),
        id: g.mk_attr_id(),
        style,
        span,
    }
}

pub fn mk_attr_word(
    g: &AttrIdGenerator,
    style: AttrStyle,
    unsafety: Safety,
    name: Symbol,
    span: Span,
) -> Attribute {
    let path = Path::from_ident(Ident::new(name, span));
    let args = AttrArgs::Empty;
    mk_attr(g, style, unsafety, path, args, span)
}

pub fn mk_attr_nested_word(
    g: &AttrIdGenerator,
    style: AttrStyle,
    unsafety: Safety,
    outer: Symbol,
    inner: Symbol,
    span: Span,
) -> Attribute {
    let inner_tokens = TokenStream::new(vec![TokenTree::Token(
        Token::from_ast_ident(Ident::new(inner, span)),
        Spacing::Alone,
    )]);
    let outer_ident = Ident::new(outer, span);
    let path = Path::from_ident(outer_ident);
    let attr_args = AttrArgs::Delimited(DelimArgs {
        dspan: DelimSpan::from_single(span),
        delim: Delimiter::Parenthesis,
        tokens: inner_tokens,
    });
    mk_attr(g, style, unsafety, path, attr_args, span)
}

pub fn mk_attr_name_value_str(
    g: &AttrIdGenerator,
    style: AttrStyle,
    unsafety: Safety,
    name: Symbol,
    val: Symbol,
    span: Span,
) -> Attribute {
    let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
    let expr = Box::new(Expr {
        id: DUMMY_NODE_ID,
        kind: ExprKind::Lit(lit),
        span,
        attrs: AttrVec::new(),
        tokens: None,
    });
    let path = Path::from_ident(Ident::new(name, span));
    let args = AttrArgs::Eq { eq_span: span, expr };
    mk_attr(g, style, unsafety, path, args, span)
}

pub fn filter_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> impl Iterator<Item = &A> {
    attrs.iter().filter(move |attr| attr.has_name(name))
}

pub fn find_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> Option<&A> {
    filter_by_name(attrs, name).next()
}

pub fn first_attr_value_str_by_name(attrs: &[impl AttributeExt], name: Symbol) -> Option<Symbol> {
    find_by_name(attrs, name).and_then(|attr| attr.value_str())
}

pub fn contains_name(attrs: &[impl AttributeExt], name: Symbol) -> bool {
    find_by_name(attrs, name).is_some()
}

pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool {
    items.iter().any(|item| item.has_name(name))
}

impl MetaItemLit {
    pub fn value_str(&self) -> Option<Symbol> {
        LitKind::from_token_lit(self.as_token_lit()).ok().and_then(|lit| lit.str())
    }
}

pub trait AttributeExt: Debug {
    fn id(&self) -> AttrId;

    /// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
    /// return the name of the attribute; otherwise, returns `None`.
    fn name(&self) -> Option<Symbol>;

    /// Get the meta item list, `#[attr(meta item list)]`
    fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>>;

    /// Gets the value literal, as string, when using `#[attr = value]`
    fn value_str(&self) -> Option<Symbol>;

    /// Gets the span of the value literal, as string, when using `#[attr = value]`
    fn value_span(&self) -> Option<Span>;

    /// Checks whether the path of this attribute matches the name.
    ///
    /// Matches one segment of the path to each element in `name`
    fn path_matches(&self, name: &[Symbol]) -> bool;

    /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
    /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
    /// a doc comment) will return `false`.
    fn is_doc_comment(&self) -> Option<Span>;

    #[inline]
    fn has_name(&self, name: Symbol) -> bool {
        self.name().map(|x| x == name).unwrap_or(false)
    }

    #[inline]
    fn has_any_name(&self, names: &[Symbol]) -> bool {
        names.iter().any(|&name| self.has_name(name))
    }

    /// get the span of the entire attribute
    fn span(&self) -> Span;

    fn is_word(&self) -> bool;

    fn path(&self) -> SmallVec<[Symbol; 1]> {
        self.symbol_path().unwrap_or(smallvec![sym::doc])
    }

    fn path_span(&self) -> Option<Span>;

    /// Returns None for doc comments
    fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>>;

    /// Returns the documentation if this is a doc comment or a sugared doc comment.
    /// * `///doc` returns `Some("doc")`.
    /// * `#[doc = "doc"]` returns `Some("doc")`.
    /// * `#[doc(...)]` returns `None`.
    fn doc_str(&self) -> Option<Symbol>;

    /// Returns the deprecation note if this is deprecation attribute.
    /// * `#[deprecated = "note"]` returns `Some("note")`.
    /// * `#[deprecated(note = "note", ...)]` returns `Some("note")`.
    fn deprecation_note(&self) -> Option<Ident>;

    fn is_proc_macro_attr(&self) -> bool {
        [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
            .iter()
            .any(|kind| self.has_name(*kind))
    }
    fn is_automatically_derived_attr(&self) -> bool;

    /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
    /// * `///doc` returns `Some(("doc", CommentKind::Line))`.
    /// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
    /// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
    /// * `#[doc(...)]` returns `None`.
    fn doc_str_and_fragment_kind(&self) -> Option<(Symbol, DocFragmentKind)>;

    /// Returns outer or inner if this is a doc attribute or a sugared doc
    /// comment, otherwise None.
    ///
    /// This is used in the case of doc comments on modules, to decide whether
    /// to resolve intra-doc links against the symbols in scope within the
    /// commented module (for inner doc) vs within its parent module (for outer
    /// doc).
    fn doc_resolution_scope(&self) -> Option<AttrStyle>;

    /// Returns `true` if this attribute contains `doc(hidden)`.
    fn is_doc_hidden(&self) -> bool;

    /// Returns `true` is this attribute contains `doc(keyword)` or `doc(attribute)`.
    fn is_doc_keyword_or_attribute(&self) -> bool;

    /// Returns `true` if this is a `#[rustc_doc_primitive]` attribute.
    fn is_rustc_doc_primitive(&self) -> bool;
}

// FIXME(fn_delegation): use function delegation instead of manually forwarding

impl Attribute {
    pub fn id(&self) -> AttrId {
        AttributeExt::id(self)
    }

    pub fn name(&self) -> Option<Symbol> {
        AttributeExt::name(self)
    }

    pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
        AttributeExt::meta_item_list(self)
    }

    pub fn value_str(&self) -> Option<Symbol> {
        AttributeExt::value_str(self)
    }

    pub fn value_span(&self) -> Option<Span> {
        AttributeExt::value_span(self)
    }

    pub fn path_matches(&self, name: &[Symbol]) -> bool {
        AttributeExt::path_matches(self, name)
    }

    // on ast attributes we return a bool since that's what most code already expects
    pub fn is_doc_comment(&self) -> bool {
        AttributeExt::is_doc_comment(self).is_some()
    }

    #[inline]
    pub fn has_name(&self, name: Symbol) -> bool {
        AttributeExt::has_name(self, name)
    }

    #[inline]
    pub fn has_any_name(&self, names: &[Symbol]) -> bool {
        AttributeExt::has_any_name(self, names)
    }

    pub fn span(&self) -> Span {
        AttributeExt::span(self)
    }

    pub fn is_word(&self) -> bool {
        AttributeExt::is_word(self)
    }

    pub fn path(&self) -> SmallVec<[Symbol; 1]> {
        AttributeExt::path(self)
    }

    pub fn doc_str(&self) -> Option<Symbol> {
        AttributeExt::doc_str(self)
    }

    pub fn is_proc_macro_attr(&self) -> bool {
        AttributeExt::is_proc_macro_attr(self)
    }

    pub fn doc_str_and_fragment_kind(&self) -> Option<(Symbol, DocFragmentKind)> {
        AttributeExt::doc_str_and_fragment_kind(self)
    }
}
