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

use std::{borrow::Cow, 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},
};
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 filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs {
        Attrs(raw_attrs.filter(db, krate))
    }
}

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 {
    pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> {
        AttrQuery { attrs: self, key }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    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.
                    match src.value.get(it.local_id()) {
                        Some(val) => RawAttrs::from_attrs_owner(
                            db,
                            src.with_value(val),
                            db.span_map(src.file_id).as_ref(),
                        ),
                        None => RawAttrs::EMPTY,
                    }
                }
                GenericParamId::TypeParamId(it) => {
                    let src = it.parent().child_source(db);
                    // FIXME: We should be never getting `None` here.
                    match src.value.get(it.local_id()) {
                        Some(val) => RawAttrs::from_attrs_owner(
                            db,
                            src.with_value(val),
                            db.span_map(src.file_id).as_ref(),
                        ),
                        None => RawAttrs::EMPTY,
                    }
                }
                GenericParamId::LifetimeParamId(it) => {
                    let src = it.parent.child_source(db);
                    // FIXME: We should be never getting `None` here.
                    match src.value.get(it.local_id) {
                        Some(val) => RawAttrs::from_attrs_owner(
                            db,
                            src.with_value(val),
                            db.span_map(src.file_id).as_ref(),
                        ),
                        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.filter(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, Copy)]
pub struct AttrQuery<'attr> {
    attrs: &'attr Attrs,
    key: &'attr Symbol,
}

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

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

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

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

    pub fn exists(self) -> bool {
        self.attrs().next().is_some()
    }

    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
    /// ```
    pub fn find_string_value_in_tt(self, key: &'attr 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()),
        );
    }
}
