//! Contains basic data about various HIR declarations.

pub mod adt;

use base_db::CrateId;
use hir_expand::{
    name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
};
use intern::{sym, Symbol};
use la_arena::{Idx, RawIdx};
use smallvec::SmallVec;
use syntax::{ast, Parse};
use triomphe::Arc;
use tt::iter::TtElement;

use crate::{
    db::DefDatabase,
    expander::{Expander, Mark},
    item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId},
    macro_call_as_call_id,
    nameres::{
        attr_resolution::ResolvedAttr,
        diagnostics::{DefDiagnostic, DefDiagnostics},
        proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
        DefMap, MacroSubNs,
    },
    path::ImportAlias,
    type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap},
    visibility::RawVisibility,
    AssocItemId, AstIdWithPath, ConstId, ConstLoc, ExternCrateId, FunctionId, FunctionLoc,
    HasModule, ImplId, Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId,
    ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, TypeAliasLoc,
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionData {
    pub name: Name,
    pub params: Box<[TypeRefId]>,
    pub ret_type: TypeRefId,
    pub visibility: RawVisibility,
    pub abi: Option<Symbol>,
    pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>,
    pub rustc_allow_incoherent_impl: bool,
    pub types_map: Arc<TypesMap>,
    flags: FnFlags,
}

impl FunctionData {
    pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
        let loc = func.lookup(db);
        let krate = loc.container.module(db).krate;
        let item_tree = loc.id.item_tree(db);
        let func = &item_tree[loc.id.value];
        let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
            trait_vis(db, trait_id)
        } else {
            item_tree[func.visibility].clone()
        };

        let crate_graph = db.crate_graph();
        let cfg_options = &crate_graph[krate].cfg_options;
        let attr_owner = |idx| {
            item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
        };

        let mut flags = func.flags;
        if flags.contains(FnFlags::HAS_SELF_PARAM) {
            // If there's a self param in the syntax, but it is cfg'd out, remove the flag.
            let is_cfgd_out =
                !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
            if is_cfgd_out {
                cov_mark::hit!(cfgd_out_self_param);
                flags.remove(FnFlags::HAS_SELF_PARAM);
            }
        }
        if flags.contains(FnFlags::IS_VARARGS) {
            if let Some((_, param)) = func.params.iter().enumerate().rev().find(|&(idx, _)| {
                item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
            }) {
                if param.type_ref.is_some() {
                    flags.remove(FnFlags::IS_VARARGS);
                }
            } else {
                flags.remove(FnFlags::IS_VARARGS);
            }
        }

        let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
        let legacy_const_generics_indices = attrs
            .by_key(&sym::rustc_legacy_const_generics)
            .tt_values()
            .next()
            .map(parse_rustc_legacy_const_generics)
            .filter(|it| !it.is_empty())
            .map(Box::new);
        let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
        if flags.contains(FnFlags::HAS_UNSAFE_KW)
            && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
        {
            flags.remove(FnFlags::HAS_UNSAFE_KW);
            flags.insert(FnFlags::DEPRECATED_SAFE_2024);
        }

        if attrs.by_key(&sym::target_feature).exists() {
            flags.insert(FnFlags::HAS_TARGET_FEATURE);
        }

        Arc::new(FunctionData {
            name: func.name.clone(),
            params: func
                .params
                .iter()
                .enumerate()
                .filter(|&(idx, _)| {
                    item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
                })
                .filter_map(|(_, param)| param.type_ref)
                .collect(),
            ret_type: func.ret_type,
            visibility,
            abi: func.abi.clone(),
            legacy_const_generics_indices,
            types_map: func.types_map.clone(),
            flags,
            rustc_allow_incoherent_impl,
        })
    }

    pub fn has_body(&self) -> bool {
        self.flags.contains(FnFlags::HAS_BODY)
    }

    /// True if the first param is `self`. This is relevant to decide whether this
    /// can be called as a method.
    pub fn has_self_param(&self) -> bool {
        self.flags.contains(FnFlags::HAS_SELF_PARAM)
    }

    pub fn is_default(&self) -> bool {
        self.flags.contains(FnFlags::HAS_DEFAULT_KW)
    }

    pub fn is_const(&self) -> bool {
        self.flags.contains(FnFlags::HAS_CONST_KW)
    }

    pub fn is_async(&self) -> bool {
        self.flags.contains(FnFlags::HAS_ASYNC_KW)
    }

    pub fn is_unsafe(&self) -> bool {
        self.flags.contains(FnFlags::HAS_UNSAFE_KW)
    }

    pub fn is_deprecated_safe_2024(&self) -> bool {
        self.flags.contains(FnFlags::DEPRECATED_SAFE_2024)
    }

    pub fn is_safe(&self) -> bool {
        self.flags.contains(FnFlags::HAS_SAFE_KW)
    }

    pub fn is_varargs(&self) -> bool {
        self.flags.contains(FnFlags::IS_VARARGS)
    }

    pub fn has_target_feature(&self) -> bool {
        self.flags.contains(FnFlags::HAS_TARGET_FEATURE)
    }
}

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

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeAliasData {
    pub name: Name,
    pub type_ref: Option<TypeRefId>,
    pub visibility: RawVisibility,
    pub is_extern: bool,
    pub rustc_has_incoherent_inherent_impls: bool,
    pub rustc_allow_incoherent_impl: bool,
    /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
    pub bounds: Box<[TypeBound]>,
    pub types_map: Arc<TypesMap>,
}

impl TypeAliasData {
    pub(crate) fn type_alias_data_query(
        db: &dyn DefDatabase,
        typ: TypeAliasId,
    ) -> Arc<TypeAliasData> {
        let loc = typ.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let typ = &item_tree[loc.id.value];
        let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
            trait_vis(db, trait_id)
        } else {
            item_tree[typ.visibility].clone()
        };

        let attrs = item_tree.attrs(
            db,
            loc.container.module(db).krate(),
            ModItem::from(loc.id.value).into(),
        );
        let rustc_has_incoherent_inherent_impls =
            attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
        let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();

        Arc::new(TypeAliasData {
            name: typ.name.clone(),
            type_ref: typ.type_ref,
            visibility,
            is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
            rustc_has_incoherent_inherent_impls,
            rustc_allow_incoherent_impl,
            bounds: typ.bounds.clone(),
            types_map: typ.types_map.clone(),
        })
    }
}

bitflags::bitflags! {
    #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
    pub struct TraitFlags: u8 {
        const IS_AUTO = 1 << 0;
        const IS_UNSAFE = 1 << 1;
        const IS_FUNDAMENTAL = 1 << 2;
        const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 3;
        const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 4;
        const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 5;
        const RUSTC_PAREN_SUGAR = 1 << 6;
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TraitData {
    pub name: Name,
    pub items: Box<[(Name, AssocItemId)]>,
    pub flags: TraitFlags,
    pub visibility: RawVisibility,
    // box it as the vec is usually empty anyways
    pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
}

impl TraitData {
    #[inline]
    pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
        db.trait_data_with_diagnostics(tr).0
    }

    pub(crate) fn trait_data_with_diagnostics_query(
        db: &dyn DefDatabase,
        tr: TraitId,
    ) -> (Arc<TraitData>, DefDiagnostics) {
        let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
        let item_tree = tree_id.item_tree(db);
        let tr_def = &item_tree[tree_id.value];
        let name = tr_def.name.clone();
        let visibility = item_tree[tr_def.visibility].clone();
        let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());

        let mut flags = TraitFlags::empty();

        if tr_def.is_auto {
            flags |= TraitFlags::IS_AUTO;
        }
        if tr_def.is_unsafe {
            flags |= TraitFlags::IS_UNSAFE;
        }
        if attrs.by_key(&sym::fundamental).exists() {
            flags |= TraitFlags::IS_FUNDAMENTAL;
        }
        if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
            flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS;
        }
        if attrs.by_key(&sym::rustc_paren_sugar).exists() {
            flags |= TraitFlags::RUSTC_PAREN_SUGAR;
        }

        let mut skip_array_during_method_dispatch =
            attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
        let mut skip_boxed_slice_during_method_dispatch = false;
        for tt in attrs.by_key(&sym::rustc_skip_during_method_dispatch).tt_values() {
            for tt in tt.iter() {
                if let tt::iter::TtElement::Leaf(tt::Leaf::Ident(ident)) = tt {
                    skip_array_during_method_dispatch |= ident.sym == sym::array;
                    skip_boxed_slice_during_method_dispatch |= ident.sym == sym::boxed_slice;
                }
            }
        }

        if skip_array_during_method_dispatch {
            flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH;
        }
        if skip_boxed_slice_during_method_dispatch {
            flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH;
        }

        let mut collector =
            AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
        collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
        let (items, macro_calls, diagnostics) = collector.finish();

        (
            Arc::new(TraitData { name, macro_calls, items, visibility, flags }),
            DefDiagnostics::new(diagnostics),
        )
    }

    pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
        self.items.iter().filter_map(|(_name, item)| match item {
            AssocItemId::TypeAliasId(t) => Some(*t),
            _ => None,
        })
    }

    pub fn associated_type_by_name(&self, name: &Name) -> Option<TypeAliasId> {
        self.items.iter().find_map(|(item_name, item)| match item {
            AssocItemId::TypeAliasId(t) if item_name == name => Some(*t),
            _ => None,
        })
    }

    pub fn method_by_name(&self, name: &Name) -> Option<FunctionId> {
        self.items.iter().find_map(|(item_name, item)| match item {
            AssocItemId::FunctionId(t) if item_name == name => Some(*t),
            _ => None,
        })
    }

    pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
        self.macro_calls.iter().flat_map(|it| it.iter()).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TraitAliasData {
    pub name: Name,
    pub visibility: RawVisibility,
}

impl TraitAliasData {
    pub(crate) fn trait_alias_query(db: &dyn DefDatabase, id: TraitAliasId) -> Arc<TraitAliasData> {
        let loc = id.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let alias = &item_tree[loc.id.value];
        let visibility = item_tree[alias.visibility].clone();

        Arc::new(TraitAliasData { name: alias.name.clone(), visibility })
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct ImplData {
    pub target_trait: Option<TraitRef>,
    pub self_ty: TypeRefId,
    pub items: Box<[(Name, AssocItemId)]>,
    pub is_negative: bool,
    pub is_unsafe: bool,
    // box it as the vec is usually empty anyways
    pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
    pub types_map: Arc<TypesMap>,
}

impl ImplData {
    #[inline]
    pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
        db.impl_data_with_diagnostics(id).0
    }

    pub(crate) fn impl_data_with_diagnostics_query(
        db: &dyn DefDatabase,
        id: ImplId,
    ) -> (Arc<ImplData>, DefDiagnostics) {
        let _p = tracing::info_span!("impl_data_with_diagnostics_query").entered();
        let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);

        let item_tree = tree_id.item_tree(db);
        let impl_def = &item_tree[tree_id.value];
        let target_trait = impl_def.target_trait;
        let self_ty = impl_def.self_ty;
        let is_negative = impl_def.is_negative;
        let is_unsafe = impl_def.is_unsafe;

        let mut collector =
            AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
        collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);

        let (items, macro_calls, diagnostics) = collector.finish();

        (
            Arc::new(ImplData {
                target_trait,
                self_ty,
                items,
                is_negative,
                is_unsafe,
                macro_calls,
                types_map: impl_def.types_map.clone(),
            }),
            DefDiagnostics::new(diagnostics),
        )
    }

    pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
        self.macro_calls.iter().flat_map(|it| it.iter()).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Macro2Data {
    pub name: Name,
    pub visibility: RawVisibility,
    // It's a bit wasteful as currently this is only for builtin `Default` derive macro, but macro2
    // are rarely used in practice so I think it's okay for now.
    /// Derive helpers, if this is a derive rustc_builtin_macro
    pub helpers: Option<Box<[Name]>>,
}

impl Macro2Data {
    pub(crate) fn macro2_data_query(db: &dyn DefDatabase, makro: Macro2Id) -> Arc<Macro2Data> {
        let loc = makro.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let makro = &item_tree[loc.id.value];

        let helpers = item_tree
            .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
            .by_key(&sym::rustc_builtin_macro)
            .tt_values()
            .next()
            .and_then(parse_macro_name_and_helper_attrs)
            .map(|(_, helpers)| helpers);

        Arc::new(Macro2Data {
            name: makro.name.clone(),
            visibility: item_tree[makro.visibility].clone(),
            helpers,
        })
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MacroRulesData {
    pub name: Name,
    pub macro_export: bool,
}

impl MacroRulesData {
    pub(crate) fn macro_rules_data_query(
        db: &dyn DefDatabase,
        makro: MacroRulesId,
    ) -> Arc<MacroRulesData> {
        let loc = makro.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let makro = &item_tree[loc.id.value];

        let macro_export = item_tree
            .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
            .by_key(&sym::macro_export)
            .exists();

        Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProcMacroData {
    pub name: Name,
    /// Derive helpers, if this is a derive
    pub helpers: Option<Box<[Name]>>,
}

impl ProcMacroData {
    pub(crate) fn proc_macro_data_query(
        db: &dyn DefDatabase,
        makro: ProcMacroId,
    ) -> Arc<ProcMacroData> {
        let loc = makro.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let makro = &item_tree[loc.id.value];

        let (name, helpers) = if let Some(def) = item_tree
            .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
            .parse_proc_macro_decl(&makro.name)
        {
            (
                def.name,
                match def.kind {
                    ProcMacroKind::Derive { helpers } => Some(helpers),
                    ProcMacroKind::Bang | ProcMacroKind::Attr => None,
                },
            )
        } else {
            // eeeh...
            stdx::never!("proc macro declaration is not a proc macro");
            (makro.name.clone(), None)
        };
        Arc::new(ProcMacroData { name, helpers })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExternCrateDeclData {
    pub name: Name,
    pub alias: Option<ImportAlias>,
    pub visibility: RawVisibility,
    pub crate_id: Option<CrateId>,
}

impl ExternCrateDeclData {
    pub(crate) fn extern_crate_decl_data_query(
        db: &dyn DefDatabase,
        extern_crate: ExternCrateId,
    ) -> Arc<ExternCrateDeclData> {
        let loc = extern_crate.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let extern_crate = &item_tree[loc.id.value];

        let name = extern_crate.name.clone();
        let krate = loc.container.krate();
        let crate_id = if name == sym::self_.clone() {
            Some(krate)
        } else {
            db.crate_graph()[krate].dependencies.iter().find_map(|dep| {
                if dep.name.symbol() == name.symbol() {
                    Some(dep.crate_id)
                } else {
                    None
                }
            })
        };

        Arc::new(Self {
            name,
            visibility: item_tree[extern_crate.visibility].clone(),
            alias: extern_crate.alias.clone(),
            crate_id,
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstData {
    /// `None` for `const _: () = ();`
    pub name: Option<Name>,
    pub type_ref: TypeRefId,
    pub visibility: RawVisibility,
    pub rustc_allow_incoherent_impl: bool,
    pub has_body: bool,
    pub types_map: Arc<TypesMap>,
}

impl ConstData {
    pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> {
        let loc = konst.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let konst = &item_tree[loc.id.value];
        let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
            trait_vis(db, trait_id)
        } else {
            item_tree[konst.visibility].clone()
        };

        let rustc_allow_incoherent_impl = item_tree
            .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
            .by_key(&sym::rustc_allow_incoherent_impl)
            .exists();

        Arc::new(ConstData {
            name: konst.name.clone(),
            type_ref: konst.type_ref,
            visibility,
            rustc_allow_incoherent_impl,
            has_body: konst.has_body,
            types_map: konst.types_map.clone(),
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StaticData {
    pub name: Name,
    pub type_ref: TypeRefId,
    pub visibility: RawVisibility,
    pub mutable: bool,
    pub is_extern: bool,
    pub has_safe_kw: bool,
    pub has_unsafe_kw: bool,
    pub types_map: Arc<TypesMap>,
}

impl StaticData {
    pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
        let loc = konst.lookup(db);
        let item_tree = loc.id.item_tree(db);
        let statik = &item_tree[loc.id.value];

        Arc::new(StaticData {
            name: statik.name.clone(),
            type_ref: statik.type_ref,
            visibility: item_tree[statik.visibility].clone(),
            mutable: statik.mutable,
            is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
            has_safe_kw: statik.has_safe_kw,
            has_unsafe_kw: statik.has_unsafe_kw,
            types_map: statik.types_map.clone(),
        })
    }
}

struct AssocItemCollector<'a> {
    db: &'a dyn DefDatabase,
    module_id: ModuleId,
    def_map: Arc<DefMap>,
    diagnostics: Vec<DefDiagnostic>,
    container: ItemContainerId,
    expander: Expander,

    items: Vec<(Name, AssocItemId)>,
    macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
}

impl<'a> AssocItemCollector<'a> {
    fn new(
        db: &'a dyn DefDatabase,
        module_id: ModuleId,
        file_id: HirFileId,
        container: ItemContainerId,
    ) -> Self {
        Self {
            db,
            module_id,
            def_map: module_id.def_map(db),
            container,
            expander: Expander::new(db, file_id, module_id),
            items: Vec::new(),
            macro_calls: Vec::new(),
            diagnostics: Vec::new(),
        }
    }

    fn finish(
        self,
    ) -> (
        Box<[(Name, AssocItemId)]>,
        Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
        Vec<DefDiagnostic>,
    ) {
        (
            self.items.into_boxed_slice(),
            if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
            self.diagnostics,
        )
    }

    fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) {
        let container = self.container;
        self.items.reserve(assoc_items.len());

        'items: for &item in assoc_items {
            let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
            if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
                self.diagnostics.push(DefDiagnostic::unconfigured_code(
                    self.module_id.local_id,
                    tree_id,
                    ModItem::from(item).into(),
                    attrs.cfg().unwrap(),
                    self.expander.cfg_options().clone(),
                ));
                continue;
            }

            'attrs: for attr in &*attrs {
                let ast_id =
                    AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast());
                let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id };

                match self.def_map.resolve_attr_macro(
                    self.db,
                    self.module_id.local_id,
                    ast_id_with_path,
                    attr,
                ) {
                    Ok(ResolvedAttr::Macro(call_id)) => {
                        let loc = self.db.lookup_intern_macro_call(call_id);
                        if let MacroDefKind::ProcMacro(_, exp, _) = loc.def.kind {
                            // If there's no expander for the proc macro (e.g. the
                            // proc macro is ignored, or building the proc macro
                            // crate failed), skip expansion like we would if it was
                            // disabled. This is analogous to the handling in
                            // `DefCollector::collect_macros`.
                            if let Some(err) = exp.as_expand_error(self.module_id.krate) {
                                self.diagnostics.push(DefDiagnostic::macro_error(
                                    self.module_id.local_id,
                                    ast_id,
                                    (*attr.path).clone(),
                                    err,
                                ));
                                continue 'attrs;
                            }
                        }

                        self.macro_calls.push((ast_id, call_id));
                        let res =
                            self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
                        self.collect_macro_items(res);
                        continue 'items;
                    }
                    Ok(_) => (),
                    Err(_) => {
                        self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
                            self.module_id.local_id,
                            MacroCallKind::Attr {
                                ast_id,
                                attr_args: None,
                                invoc_attr_index: attr.id,
                            },
                            attr.path().clone(),
                        ));
                    }
                }
            }

            self.collect_item(item_tree, tree_id, container, item);
        }
    }

    fn collect_item(
        &mut self,
        item_tree: &ItemTree,
        tree_id: TreeId,
        container: ItemContainerId,
        item: AssocItem,
    ) {
        match item {
            AssocItem::Function(id) => {
                let item = &item_tree[id];
                let def =
                    FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
                self.items.push((item.name.clone(), def.into()));
            }
            AssocItem::TypeAlias(id) => {
                let item = &item_tree[id];
                let def =
                    TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
                self.items.push((item.name.clone(), def.into()));
            }
            AssocItem::Const(id) => {
                let item = &item_tree[id];
                let Some(name) = item.name.clone() else { return };
                let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
                self.items.push((name, def.into()));
            }
            AssocItem::MacroCall(call) => {
                let file_id = self.expander.current_file_id();
                let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call];
                let module = self.expander.module.local_id;

                let resolver = |path: &_| {
                    self.def_map
                        .resolve_path(
                            self.db,
                            module,
                            path,
                            crate::item_scope::BuiltinShadowMode::Other,
                            Some(MacroSubNs::Bang),
                        )
                        .0
                        .take_macros()
                        .map(|it| self.db.macro_def(it))
                };
                match macro_call_as_call_id(
                    self.db.upcast(),
                    &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)),
                    ctxt,
                    expand_to,
                    self.expander.krate(),
                    resolver,
                ) {
                    Ok(Some(call_id)) => {
                        let res =
                            self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
                        self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id));
                        self.collect_macro_items(res);
                    }
                    Ok(None) => (),
                    Err(_) => {
                        self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
                            self.module_id.local_id,
                            MacroCallKind::FnLike {
                                ast_id: InFile::new(file_id, ast_id),
                                expand_to,
                                eager: None,
                            },
                            Clone::clone(path),
                        ));
                    }
                }
            }
        }
    }

    fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) {
        let Some((mark, _parse)) = res.value else { return };

        let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
        let item_tree = tree_id.item_tree(self.db);
        let iter: SmallVec<[_; 2]> =
            item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item).collect();

        self.collect(&item_tree, tree_id, &iter);

        self.expander.exit(mark);
    }
}

fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility {
    let ItemLoc { id: tree_id, .. } = trait_id.lookup(db);
    let item_tree = tree_id.item_tree(db);
    let tr_def = &item_tree[tree_id.value];
    item_tree[tr_def.visibility].clone()
}
