//! A higher level attributes based on TokenTree, with also some shortcuts.

use std::{borrow::Cow, convert::identity, hash::Hash, ops};

use base_db::Crate;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{
    HirFileId, InFile,
    attrs::{Attr, AttrId, RawAttrs, collect_attrs},
    span_map::SpanMapRef,
};
use intern::{Symbol, sym};
use la_arena::{ArenaMap, Idx, RawIdx};
use mbe::DelimiterKind;
use rustc_abi::ReprOptions;
use syntax::{
    AstPtr,
    ast::{self, HasAttrs},
};
use triomphe::Arc;
use tt::iter::{TtElement, TtIter};

use crate::{
    AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId,
    VariantId,
    db::DefDatabase,
    item_tree::{AttrOwner, FieldParent, ItemTreeNode},
    lang_item::LangItem,
    nameres::{ModuleOrigin, ModuleSource},
    src::{HasChildSource, HasSource},
};

/// Desugared attributes of an item post `cfg_attr` expansion.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Attrs(RawAttrs);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AttrsWithOwner {
    attrs: Attrs,
    owner: AttrDefId,
}

impl Attrs {
    pub fn get(&self, id: AttrId) -> Option<&Attr> {
        (**self).iter().find(|attr| attr.id == id)
    }

    pub(crate) fn expand_cfg_attr(
        db: &dyn DefDatabase,
        krate: Crate,
        raw_attrs: RawAttrs,
    ) -> Attrs {
        Attrs(raw_attrs.expand_cfg_attr(db, krate))
    }

    pub(crate) fn is_cfg_enabled_for(
        db: &dyn DefDatabase,
        owner: &dyn ast::HasAttrs,
        span_map: SpanMapRef<'_>,
        cfg_options: &CfgOptions,
    ) -> Result<(), CfgExpr> {
        RawAttrs::attrs_iter_expanded::<false>(db, owner, span_map, cfg_options)
            .filter_map(|attr| attr.cfg())
            .find_map(|cfg| match cfg_options.check(&cfg).is_none_or(identity) {
                true => None,
                false => Some(cfg),
            })
            .map_or(Ok(()), Err)
    }
}

impl ops::Deref for Attrs {
    type Target = [Attr];

    fn deref(&self) -> &[Attr] {
        &self.0
    }
}

impl ops::Deref for AttrsWithOwner {
    type Target = Attrs;

    fn deref(&self) -> &Attrs {
        &self.attrs
    }
}

impl Attrs {
    pub const EMPTY: Self = Self(RawAttrs::EMPTY);

    pub(crate) fn fields_attrs_query(
        db: &dyn DefDatabase,
        v: VariantId,
    ) -> Arc<ArenaMap<LocalFieldId, Attrs>> {
        let _p = tracing::info_span!("fields_attrs_query").entered();
        // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
        let mut res = ArenaMap::default();
        let item_tree;
        let (parent, fields, krate) = match v {
            VariantId::EnumVariantId(it) => {
                let loc = it.lookup(db);
                let krate = loc.parent.lookup(db).container.krate;
                item_tree = loc.id.item_tree(db);
                let variant = &item_tree[loc.id.value];
                (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate)
            }
            VariantId::StructId(it) => {
                let loc = it.lookup(db);
                let krate = loc.container.krate;
                item_tree = loc.id.item_tree(db);
                let struct_ = &item_tree[loc.id.value];
                (FieldParent::Struct(loc.id.value), &struct_.fields, krate)
            }
            VariantId::UnionId(it) => {
                let loc = it.lookup(db);
                let krate = loc.container.krate;
                item_tree = loc.id.item_tree(db);
                let union_ = &item_tree[loc.id.value];
                (FieldParent::Union(loc.id.value), &union_.fields, krate)
            }
        };

        let cfg_options = krate.cfg_options(db);

        let mut idx = 0;
        for (id, _field) in fields.iter().enumerate() {
            let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
            if attrs.is_cfg_enabled(cfg_options) {
                res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
                idx += 1;
            }
        }

        Arc::new(res)
    }
}

impl Attrs {
    #[inline]
    pub fn by_key(&self, key: Symbol) -> AttrQuery<'_> {
        AttrQuery { attrs: self, key }
    }

    #[inline]
    pub fn rust_analyzer_tool(&self) -> impl Iterator<Item = &Attr> {
        self.iter()
            .filter(|&attr| attr.path.segments().first().is_some_and(|s| *s == sym::rust_analyzer))
    }

    #[inline]
    pub fn cfg(&self) -> Option<CfgExpr> {
        let mut cfgs = self.by_key(sym::cfg).tt_values().map(CfgExpr::parse);
        let first = cfgs.next()?;
        match cfgs.next() {
            Some(second) => {
                let cfgs = [first, second].into_iter().chain(cfgs);
                Some(CfgExpr::All(cfgs.collect()))
            }
            None => Some(first),
        }
    }

    #[inline]
    pub fn cfgs(&self) -> impl Iterator<Item = CfgExpr> + '_ {
        self.by_key(sym::cfg).tt_values().map(CfgExpr::parse)
    }

    #[inline]
    pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
        match self.cfg() {
            None => true,
            Some(cfg) => cfg_options.check(&cfg) != Some(false),
        }
    }

    #[inline]
    pub fn lang(&self) -> Option<&Symbol> {
        self.by_key(sym::lang).string_value()
    }

    #[inline]
    pub fn lang_item(&self) -> Option<LangItem> {
        self.by_key(sym::lang).string_value().and_then(LangItem::from_symbol)
    }

    #[inline]
    pub fn has_doc_hidden(&self) -> bool {
        self.by_key(sym::doc).tt_values().any(|tt| {
            tt.top_subtree().delimiter.kind == DelimiterKind::Parenthesis &&
                matches!(tt.token_trees().flat_tokens(), [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden)
        })
    }

    #[inline]
    pub fn has_doc_notable_trait(&self) -> bool {
        self.by_key(sym::doc).tt_values().any(|tt| {
            tt.top_subtree().delimiter.kind == DelimiterKind::Parenthesis &&
                matches!(tt.token_trees().flat_tokens(), [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait)
        })
    }

    #[inline]
    pub fn doc_exprs(&self) -> impl Iterator<Item = DocExpr> + '_ {
        self.by_key(sym::doc).tt_values().map(DocExpr::parse)
    }

    #[inline]
    pub fn doc_aliases(&self) -> impl Iterator<Item = Symbol> + '_ {
        self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec())
    }

    #[inline]
    pub fn export_name(&self) -> Option<&Symbol> {
        self.by_key(sym::export_name).string_value()
    }

    #[inline]
    pub fn is_proc_macro(&self) -> bool {
        self.by_key(sym::proc_macro).exists()
    }

    #[inline]
    pub fn is_proc_macro_attribute(&self) -> bool {
        self.by_key(sym::proc_macro_attribute).exists()
    }

    #[inline]
    pub fn is_proc_macro_derive(&self) -> bool {
        self.by_key(sym::proc_macro_derive).exists()
    }

    #[inline]
    pub fn is_test(&self) -> bool {
        self.iter().any(|it| {
            it.path()
                .segments()
                .iter()
                .rev()
                .zip([sym::core, sym::prelude, sym::v1, sym::test].iter().rev())
                .all(|it| it.0 == it.1)
        })
    }

    #[inline]
    pub fn is_ignore(&self) -> bool {
        self.by_key(sym::ignore).exists()
    }

    #[inline]
    pub fn is_bench(&self) -> bool {
        self.by_key(sym::bench).exists()
    }

    #[inline]
    pub fn is_unstable(&self) -> bool {
        self.by_key(sym::unstable).exists()
    }

    #[inline]
    pub fn rustc_legacy_const_generics(&self) -> Option<Box<Box<[u32]>>> {
        self.by_key(sym::rustc_legacy_const_generics)
            .tt_values()
            .next()
            .map(parse_rustc_legacy_const_generics)
            .filter(|it| !it.is_empty())
            .map(Box::new)
    }

    #[inline]
    pub fn repr(&self) -> Option<ReprOptions> {
        self.by_key(sym::repr).tt_values().filter_map(parse_repr_tt).fold(None, |acc, repr| {
            acc.map_or(Some(repr), |mut acc| {
                merge_repr(&mut acc, repr);
                Some(acc)
            })
        })
    }
}

fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> {
    let mut indices = Vec::new();
    let mut iter = tt.iter();
    while let (Some(first), second) = (iter.next(), iter.next()) {
        match first {
            TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() {
                Ok(index) => indices.push(index),
                Err(_) => break,
            },
            _ => break,
        }

        if let Some(comma) = second {
            match comma {
                TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {}
                _ => break,
            }
        }
    }

    indices.into_boxed_slice()
}

fn merge_repr(this: &mut ReprOptions, other: ReprOptions) {
    let ReprOptions { int, align, pack, flags, field_shuffle_seed: _ } = this;
    flags.insert(other.flags);
    *align = (*align).max(other.align);
    *pack = match (*pack, other.pack) {
        (Some(pack), None) | (None, Some(pack)) => Some(pack),
        _ => (*pack).min(other.pack),
    };
    if other.int.is_some() {
        *int = other.int;
    }
}

fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option<ReprOptions> {
    use crate::builtin_type::{BuiltinInt, BuiltinUint};
    use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};

    match tt.top_subtree().delimiter {
        tt::Delimiter { kind: DelimiterKind::Parenthesis, .. } => {}
        _ => return None,
    }

    let mut acc = ReprOptions::default();
    let mut tts = tt.iter();
    while let Some(tt) = tts.next() {
        let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt else {
            continue;
        };
        let repr = match &ident.sym {
            s if *s == sym::packed => {
                let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
                    tts.next();
                    if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() {
                        lit.symbol.as_str().parse().unwrap_or_default()
                    } else {
                        0
                    }
                } else {
                    0
                };
                let pack = Some(Align::from_bytes(pack).unwrap_or(Align::ONE));
                ReprOptions { pack, ..Default::default() }
            }
            s if *s == sym::align => {
                let mut align = None;
                if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
                    tts.next();
                    if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() {
                        if let Ok(a) = lit.symbol.as_str().parse() {
                            align = Align::from_bytes(a).ok();
                        }
                    }
                }
                ReprOptions { align, ..Default::default() }
            }
            s if *s == sym::C => ReprOptions { flags: ReprFlags::IS_C, ..Default::default() },
            s if *s == sym::transparent => {
                ReprOptions { flags: ReprFlags::IS_TRANSPARENT, ..Default::default() }
            }
            s if *s == sym::simd => ReprOptions { flags: ReprFlags::IS_SIMD, ..Default::default() },
            repr => {
                let mut int = None;
                if let Some(builtin) = BuiltinInt::from_suffix_sym(repr)
                    .map(Either::Left)
                    .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right))
                {
                    int = Some(match builtin {
                        Either::Left(bi) => match bi {
                            BuiltinInt::Isize => IntegerType::Pointer(true),
                            BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true),
                            BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true),
                            BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true),
                            BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true),
                            BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true),
                        },
                        Either::Right(bu) => match bu {
                            BuiltinUint::Usize => IntegerType::Pointer(false),
                            BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false),
                            BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false),
                            BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false),
                            BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false),
                            BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false),
                        },
                    });
                }
                ReprOptions { int, ..Default::default() }
            }
        };
        merge_repr(&mut acc, repr);
    }

    Some(acc)
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DocAtom {
    /// eg. `#[doc(hidden)]`
    Flag(Symbol),
    /// eg. `#[doc(alias = "it")]`
    ///
    /// Note that a key can have multiple values that are all considered "active" at the same time.
    /// For example, `#[doc(alias = "x")]` and `#[doc(alias = "y")]`.
    KeyValue { key: Symbol, value: Symbol },
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DocExpr {
    Invalid,
    /// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]`
    Atom(DocAtom),
    /// eg. `#[doc(alias("x", "y"))]`
    Alias(Vec<Symbol>),
}

impl From<DocAtom> for DocExpr {
    fn from(atom: DocAtom) -> Self {
        DocExpr::Atom(atom)
    }
}

impl DocExpr {
    fn parse<S: Copy>(tt: &tt::TopSubtree<S>) -> DocExpr {
        next_doc_expr(tt.iter()).unwrap_or(DocExpr::Invalid)
    }

    pub fn aliases(&self) -> &[Symbol] {
        match self {
            DocExpr::Atom(DocAtom::KeyValue { key, value }) if *key == sym::alias => {
                std::slice::from_ref(value)
            }
            DocExpr::Alias(aliases) => aliases,
            _ => &[],
        }
    }
}

fn next_doc_expr<S: Copy>(mut it: TtIter<'_, S>) -> Option<DocExpr> {
    let name = match it.next() {
        None => return None,
        Some(TtElement::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
        Some(_) => return Some(DocExpr::Invalid),
    };

    // Peek
    let ret = match it.peek() {
        Some(TtElement::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
            it.next();
            match it.next() {
                Some(TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                    symbol: text,
                    kind: tt::LitKind::Str,
                    ..
                }))) => DocAtom::KeyValue { key: name, value: text.clone() }.into(),
                _ => return Some(DocExpr::Invalid),
            }
        }
        Some(TtElement::Subtree(_, subtree_iter)) => {
            it.next();
            let subs = parse_comma_sep(subtree_iter);
            match &name {
                s if *s == sym::alias => DocExpr::Alias(subs),
                _ => DocExpr::Invalid,
            }
        }
        _ => DocAtom::Flag(name).into(),
    };
    Some(ret)
}

fn parse_comma_sep<S>(iter: TtIter<'_, S>) -> Vec<Symbol> {
    iter.filter_map(|tt| match tt {
        TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
            kind: tt::LitKind::Str, symbol, ..
        })) => Some(symbol.clone()),
        _ => None,
    })
    .collect()
}

impl AttrsWithOwner {
    pub fn new(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
        Self { attrs: db.attrs(owner), owner }
    }

    pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
        let _p = tracing::info_span!("attrs_query").entered();
        // FIXME: this should use `Trace` to avoid duplication in `source_map` below
        let raw_attrs = match def {
            AttrDefId::ModuleId(module) => {
                let def_map = module.def_map(db);
                let mod_data = &def_map[module.local_id];

                match mod_data.origin {
                    ModuleOrigin::File { definition, declaration_tree_id, .. } => {
                        let decl_attrs = declaration_tree_id
                            .item_tree(db)
                            .raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into()))
                            .clone();
                        let tree = db.file_item_tree(definition.into());
                        let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone();
                        decl_attrs.merge(def_attrs)
                    }
                    ModuleOrigin::CrateRoot { definition } => {
                        let tree = db.file_item_tree(definition.into());
                        tree.raw_attrs(AttrOwner::TopLevel).clone()
                    }
                    ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id
                        .item_tree(db)
                        .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
                        .clone(),
                    ModuleOrigin::BlockExpr { id, .. } => {
                        let tree = db.block_item_tree(id);
                        tree.raw_attrs(AttrOwner::TopLevel).clone()
                    }
                }
            }
            AttrDefId::FieldId(it) => {
                return db.fields_attrs(it.parent)[it.local_id].clone();
            }
            AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::AdtId(it) => match it {
                AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
                AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it),
                AdtId::UnionId(it) => attrs_from_item_tree_loc(db, it),
            },
            AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::MacroId(it) => match it {
                MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it),
                MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it),
                MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it),
            },
            AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::GenericParamId(it) => match it {
                GenericParamId::ConstParamId(it) => {
                    let src = it.parent().child_source(db);
                    // FIXME: We should be never getting `None` here.
                    return Attrs(match src.value.get(it.local_id()) {
                        Some(val) => RawAttrs::new_expanded(
                            db,
                            val,
                            db.span_map(src.file_id).as_ref(),
                            def.krate(db).cfg_options(db),
                        ),
                        None => RawAttrs::EMPTY,
                    });
                }
                GenericParamId::TypeParamId(it) => {
                    let src = it.parent().child_source(db);
                    // FIXME: We should be never getting `None` here.
                    return Attrs(match src.value.get(it.local_id()) {
                        Some(val) => RawAttrs::new_expanded(
                            db,
                            val,
                            db.span_map(src.file_id).as_ref(),
                            def.krate(db).cfg_options(db),
                        ),
                        None => RawAttrs::EMPTY,
                    });
                }
                GenericParamId::LifetimeParamId(it) => {
                    let src = it.parent.child_source(db);
                    // FIXME: We should be never getting `None` here.
                    return Attrs(match src.value.get(it.local_id) {
                        Some(val) => RawAttrs::new_expanded(
                            db,
                            val,
                            db.span_map(src.file_id).as_ref(),
                            def.krate(db).cfg_options(db),
                        ),
                        None => RawAttrs::EMPTY,
                    });
                }
            },
            AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it),
            AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it),
        };

        let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db));
        Attrs(attrs)
    }

    pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap {
        let owner = match self.owner {
            AttrDefId::ModuleId(module) => {
                // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself).

                let def_map = module.def_map(db);
                let mod_data = &def_map[module.local_id];
                match mod_data.declaration_source(db) {
                    Some(it) => {
                        let mut map = AttrSourceMap::new(InFile::new(it.file_id, &it.value));
                        if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
                            mod_data.definition_source(db)
                        {
                            map.append_module_inline_attrs(AttrSourceMap::new(InFile::new(
                                file_id, &file,
                            )));
                        }
                        return map;
                    }
                    None => {
                        let InFile { file_id, value } = mod_data.definition_source(db);
                        let attrs_owner = match &value {
                            ModuleSource::SourceFile(file) => file as &dyn ast::HasAttrs,
                            ModuleSource::Module(module) => module as &dyn ast::HasAttrs,
                            ModuleSource::BlockExpr(block) => block as &dyn ast::HasAttrs,
                        };
                        return AttrSourceMap::new(InFile::new(file_id, attrs_owner));
                    }
                }
            }
            AttrDefId::FieldId(id) => {
                let map = db.fields_attrs_source_map(id.parent);
                let file_id = id.parent.file_id(db);
                let root = db.parse_or_expand(file_id);
                let owner = ast::AnyHasAttrs::new(map[id.local_id].to_node(&root));
                InFile::new(file_id, owner)
            }
            AttrDefId::AdtId(adt) => match adt {
                AdtId::StructId(id) => any_has_attrs(db, id),
                AdtId::UnionId(id) => any_has_attrs(db, id),
                AdtId::EnumId(id) => any_has_attrs(db, id),
            },
            AttrDefId::FunctionId(id) => any_has_attrs(db, id),
            AttrDefId::EnumVariantId(id) => any_has_attrs(db, id),
            AttrDefId::StaticId(id) => any_has_attrs(db, id),
            AttrDefId::ConstId(id) => any_has_attrs(db, id),
            AttrDefId::TraitId(id) => any_has_attrs(db, id),
            AttrDefId::TraitAliasId(id) => any_has_attrs(db, id),
            AttrDefId::TypeAliasId(id) => any_has_attrs(db, id),
            AttrDefId::MacroId(id) => match id {
                MacroId::Macro2Id(id) => any_has_attrs(db, id),
                MacroId::MacroRulesId(id) => any_has_attrs(db, id),
                MacroId::ProcMacroId(id) => any_has_attrs(db, id),
            },
            AttrDefId::ImplId(id) => any_has_attrs(db, id),
            AttrDefId::GenericParamId(id) => match id {
                GenericParamId::ConstParamId(id) => id
                    .parent()
                    .child_source(db)
                    .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())),
                GenericParamId::TypeParamId(id) => id
                    .parent()
                    .child_source(db)
                    .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())),
                GenericParamId::LifetimeParamId(id) => id
                    .parent
                    .child_source(db)
                    .map(|source| ast::AnyHasAttrs::new(source[id.local_id].clone())),
            },
            AttrDefId::ExternBlockId(id) => any_has_attrs(db, id),
            AttrDefId::ExternCrateId(id) => any_has_attrs(db, id),
            AttrDefId::UseId(id) => any_has_attrs(db, id),
        };

        AttrSourceMap::new(owner.as_ref().map(|node| node as &dyn HasAttrs))
    }
}

#[derive(Debug)]
pub struct AttrSourceMap {
    source: Vec<Either<ast::Attr, ast::Comment>>,
    file_id: HirFileId,
    /// If this map is for a module, this will be the [`HirFileId`] of the module's definition site,
    /// while `file_id` will be the one of the module declaration site.
    /// The usize is the index into `source` from which point on the entries reside in the def site
    /// file.
    mod_def_site_file_id: Option<(HirFileId, usize)>,
}

impl AttrSourceMap {
    fn new(owner: InFile<&dyn ast::HasAttrs>) -> Self {
        Self {
            source: collect_attrs(owner.value).map(|(_, it)| it).collect(),
            file_id: owner.file_id,
            mod_def_site_file_id: None,
        }
    }

    /// Append a second source map to this one, this is required for modules, whose outline and inline
    /// attributes can reside in different files
    fn append_module_inline_attrs(&mut self, other: Self) {
        assert!(self.mod_def_site_file_id.is_none() && other.mod_def_site_file_id.is_none());
        let len = self.source.len();
        self.source.extend(other.source);
        if other.file_id != self.file_id {
            self.mod_def_site_file_id = Some((other.file_id, len));
        }
    }

    /// Maps the lowered `Attr` back to its original syntax node.
    ///
    /// `attr` must come from the `owner` used for AttrSourceMap
    ///
    /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
    /// the attribute represented by `Attr`.
    pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
        self.source_of_id(attr.id)
    }

    pub fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
        let ast_idx = id.ast_index();
        let file_id = match self.mod_def_site_file_id {
            Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
            _ => self.file_id,
        };

        self.source
            .get(ast_idx)
            .map(|it| InFile::new(file_id, it))
            .unwrap_or_else(|| panic!("cannot find attr at index {id:?}"))
    }
}

#[derive(Debug, Clone)]
pub struct AttrQuery<'attr> {
    attrs: &'attr Attrs,
    key: Symbol,
}

impl<'attr> AttrQuery<'attr> {
    #[inline]
    pub fn tt_values(self) -> impl Iterator<Item = &'attr crate::tt::TopSubtree> {
        self.attrs().filter_map(|attr| attr.token_tree_value())
    }

    #[inline]
    pub fn string_value(self) -> Option<&'attr Symbol> {
        self.attrs().find_map(|attr| attr.string_value())
    }

    #[inline]
    pub fn string_value_with_span(self) -> Option<(&'attr Symbol, span::Span)> {
        self.attrs().find_map(|attr| attr.string_value_with_span())
    }

    #[inline]
    pub fn string_value_unescape(self) -> Option<Cow<'attr, str>> {
        self.attrs().find_map(|attr| attr.string_value_unescape())
    }

    #[inline]
    pub fn exists(self) -> bool {
        self.attrs().next().is_some()
    }

    #[inline]
    pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
        let key = self.key;
        self.attrs.iter().filter(move |attr| attr.path.as_ident().is_some_and(|s| *s == key))
    }

    /// Find string value for a specific key inside token tree
    ///
    /// ```ignore
    /// #[doc(html_root_url = "url")]
    ///       ^^^^^^^^^^^^^ key
    /// ```
    #[inline]
    pub fn find_string_value_in_tt(self, key: Symbol) -> Option<&'attr str> {
        self.tt_values().find_map(|tt| {
            let name = tt.iter()
                .skip_while(|tt| !matches!(tt, TtElement::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == key))
                .nth(2);

            match name {
                Some(TtElement::Leaf(tt::Leaf::Literal(tt::Literal{  symbol: text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text.as_str()),
                _ => None
            }
        })
    }
}

fn any_has_attrs<'db>(
    db: &(dyn DefDatabase + 'db),
    id: impl Lookup<Database = dyn DefDatabase, Data = impl HasSource<Value = impl ast::HasAttrs>>,
) -> InFile<ast::AnyHasAttrs> {
    id.lookup(db).source(db).map(ast::AnyHasAttrs::new)
}

fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
    db: &(dyn DefDatabase + 'db),
    lookup: impl Lookup<Database = dyn DefDatabase, Data = impl ItemTreeLoc<Id = N>>,
) -> RawAttrs {
    let id = lookup.lookup(db).item_tree_id();
    let tree = id.item_tree(db);
    let attr_owner = N::attr_owner(id.value);
    tree.raw_attrs(attr_owner).clone()
}

pub(crate) fn fields_attrs_source_map(
    db: &dyn DefDatabase,
    def: VariantId,
) -> Arc<ArenaMap<LocalFieldId, AstPtr<Either<ast::TupleField, ast::RecordField>>>> {
    let mut res = ArenaMap::default();
    let child_source = def.child_source(db);

    for (idx, variant) in child_source.value.iter() {
        res.insert(
            idx,
            variant
                .as_ref()
                .either(|l| AstPtr::new(l).wrap_left(), |r| AstPtr::new(r).wrap_right()),
        );
    }

    Arc::new(res)
}

#[cfg(test)]
mod tests {
    //! This module contains tests for doc-expression parsing.
    //! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`.

    use intern::Symbol;
    use span::EditionedFileId;
    use triomphe::Arc;

    use hir_expand::span_map::{RealSpanMap, SpanMap};
    use span::FileId;
    use syntax::{AstNode, TextRange, ast};
    use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree};

    use crate::attr::{DocAtom, DocExpr};

    fn assert_parse_result(input: &str, expected: DocExpr) {
        let source_file = ast::SourceFile::parse(input, span::Edition::CURRENT).ok().unwrap();
        let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
        let map = SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(
            EditionedFileId::current_edition(FileId::from_raw(0)),
        )));
        let tt = syntax_node_to_token_tree(
            tt.syntax(),
            map.as_ref(),
            map.span_for_range(TextRange::empty(0.into())),
            DocCommentDesugarMode::ProcMacro,
        );
        let cfg = DocExpr::parse(&tt);
        assert_eq!(cfg, expected);
    }

    #[test]
    fn test_doc_expr_parser() {
        assert_parse_result("#![doc(hidden)]", DocAtom::Flag(Symbol::intern("hidden")).into());

        assert_parse_result(
            r#"#![doc(alias = "foo")]"#,
            DocAtom::KeyValue { key: Symbol::intern("alias"), value: Symbol::intern("foo") }.into(),
        );

        assert_parse_result(
            r#"#![doc(alias("foo"))]"#,
            DocExpr::Alias([Symbol::intern("foo")].into()),
        );
        assert_parse_result(
            r#"#![doc(alias("foo", "bar", "baz"))]"#,
            DocExpr::Alias(
                [Symbol::intern("foo"), Symbol::intern("bar"), Symbol::intern("baz")].into(),
            ),
        );

        assert_parse_result(
            r#"
        #[doc(alias("Bar", "Qux"))]
        struct Foo;"#,
            DocExpr::Alias([Symbol::intern("Bar"), Symbol::intern("Qux")].into()),
        );
    }
}
