Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_scope.rs')
| -rw-r--r-- | crates/hir-def/src/item_scope.rs | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 77ed664f44..9e7868b273 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -1,23 +1,23 @@ //! Describes items defined or visible (ie, imported) in a certain scope. //! This is shared between modules and blocks. -use std::sync::LazyLock; +use std::{fmt, sync::LazyLock}; use base_db::Crate; -use hir_expand::{AstId, MacroCallId, attrs::AttrId, db::ExpandDatabase, name::Name}; +use hir_expand::{AstId, MacroCallId, attrs::AttrId, name::Name}; use indexmap::map::Entry; use itertools::Itertools; use la_arena::Idx; use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::{SmallVec, smallvec}; +use smallvec::SmallVec; use span::Edition; use stdx::format_to; use syntax::ast; use thin_vec::ThinVec; use crate::{ - AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, - LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, + AdtId, BuiltinDeriveImplId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, + HasModule, ImplId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId, db::DefDatabase, per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem}, visibility::Visibility, @@ -25,9 +25,9 @@ use crate::{ #[derive(Debug, Default)] pub struct PerNsGlobImports { - types: FxHashSet<(LocalModuleId, Name)>, - values: FxHashSet<(LocalModuleId, Name)>, - macros: FxHashSet<(LocalModuleId, Name)>, + types: FxHashSet<(ModuleId, Name)>, + values: FxHashSet<(ModuleId, Name)>, + macros: FxHashSet<(ModuleId, Name)>, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -133,13 +133,13 @@ pub struct GlobId { } impl PerNsGlobImports { - pub(crate) fn contains_type(&self, module_id: LocalModuleId, name: Name) -> bool { + pub(crate) fn contains_type(&self, module_id: ModuleId, name: Name) -> bool { self.types.contains(&(module_id, name)) } - pub(crate) fn contains_value(&self, module_id: LocalModuleId, name: Name) -> bool { + pub(crate) fn contains_value(&self, module_id: ModuleId, name: Name) -> bool { self.values.contains(&(module_id, name)) } - pub(crate) fn contains_macro(&self, module_id: LocalModuleId, name: Name) -> bool { + pub(crate) fn contains_macro(&self, module_id: ModuleId, name: Name) -> bool { self.macros.contains(&(module_id, name)) } } @@ -159,6 +159,7 @@ pub struct ItemScope { declarations: ThinVec<ModuleDefId>, impls: ThinVec<ImplId>, + builtin_derive_impls: ThinVec<BuiltinDeriveImplId>, extern_blocks: ThinVec<ExternBlockId>, unnamed_consts: ThinVec<ConstId>, /// Traits imported via `use Trait as _;`. @@ -261,14 +262,12 @@ impl ItemScope { pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs { let mut res = PerNs::none(); - let mut def_map; let mut scope = self; while let Some(&m) = scope.use_imports_macros.get(&ImportOrExternCrate::Import(import)) { match m { ImportOrDef::Import(i) => { let module_id = i.use_.lookup(db).container; - def_map = module_id.def_map(db); - scope = &def_map[module_id.local_id].scope; + scope = &module_id.def_map(db)[module_id].scope; import = i; } ImportOrDef::Def(ModuleDefId::MacroId(def)) => { @@ -283,8 +282,7 @@ impl ItemScope { match m { ImportOrDef::Import(i) => { let module_id = i.use_.lookup(db).container; - def_map = module_id.def_map(db); - scope = &def_map[module_id.local_id].scope; + scope = &module_id.def_map(db)[module_id].scope; import = i; } ImportOrDef::Def(def) => { @@ -299,8 +297,7 @@ impl ItemScope { match m { ImportOrDef::Import(i) => { let module_id = i.use_.lookup(db).container; - def_map = module_id.def_map(db); - scope = &def_map[module_id.local_id].scope; + scope = &module_id.def_map(db)[module_id].scope; import = i; } ImportOrDef::Def(def) => { @@ -333,6 +330,10 @@ impl ItemScope { self.impls.iter().copied() } + pub fn builtin_derive_impls(&self) -> impl ExactSizeIterator<Item = BuiltinDeriveImplId> + '_ { + self.builtin_derive_impls.iter().copied() + } + pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ { self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain( self.derive_macros.values().flat_map(|it| { @@ -475,6 +476,10 @@ impl ItemScope { self.impls.push(imp); } + pub(crate) fn define_builtin_derive_impl(&mut self, imp: BuiltinDeriveImplId) { + self.builtin_derive_impls.push(imp); + } + pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) { self.extern_blocks.push(extern_block); } @@ -526,12 +531,13 @@ impl ItemScope { adt: AstId<ast::Adt>, attr_id: AttrId, attr_call_id: MacroCallId, - len: usize, + mut derive_call_ids: SmallVec<[Option<MacroCallId>; 4]>, ) { + derive_call_ids.shrink_to_fit(); self.derive_macros.entry(adt).or_default().push(DeriveMacroInvocation { attr_id, attr_call_id, - derive_call_ids: smallvec![None; len], + derive_call_ids, }); } @@ -578,7 +584,7 @@ impl ItemScope { pub(crate) fn push_res_with_import( &mut self, glob_imports: &mut PerNsGlobImports, - lookup: (LocalModuleId, Name), + lookup: (ModuleId, Name), def: PerNs, import: Option<ImportOrExternCrate>, ) -> bool { @@ -735,40 +741,51 @@ impl ItemScope { } } - pub(crate) fn dump(&self, db: &dyn ExpandDatabase, buf: &mut String) { + pub(crate) fn dump(&self, db: &dyn DefDatabase, buf: &mut String) { let mut entries: Vec<_> = self.resolutions().collect(); entries.sort_by_key(|(name, _)| name.clone()); + let print_macro_sub_ns = |buf: &mut String, macro_id: MacroId| { + let styles = crate::nameres::macro_styles_from_id(db, macro_id); + if styles.contains(MacroCallStyles::FN_LIKE) { + buf.push('!'); + } + if styles.contains(MacroCallStyles::ATTR) || styles.contains(MacroCallStyles::DERIVE) { + buf.push('#'); + } + }; + for (name, def) in entries { - format_to!( - buf, - "{}:", - name.map_or("_".to_owned(), |name| name.display(db, Edition::LATEST).to_string()) - ); + let display_name: &dyn fmt::Display = match &name { + Some(name) => &name.display(db, Edition::LATEST), + None => &"_", + }; + format_to!(buf, "- {display_name} :"); if let Some(Item { import, .. }) = def.types { - buf.push_str(" t"); + buf.push_str(" type"); match import { - Some(ImportOrExternCrate::Import(_)) => buf.push('i'), - Some(ImportOrExternCrate::Glob(_)) => buf.push('g'), - Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'), + Some(ImportOrExternCrate::Import(_)) => buf.push_str(" (import)"), + Some(ImportOrExternCrate::Glob(_)) => buf.push_str(" (glob)"), + Some(ImportOrExternCrate::ExternCrate(_)) => buf.push_str(" (extern)"), None => (), } } if let Some(Item { import, .. }) = def.values { - buf.push_str(" v"); + buf.push_str(" value"); match import { - Some(ImportOrGlob::Import(_)) => buf.push('i'), - Some(ImportOrGlob::Glob(_)) => buf.push('g'), + Some(ImportOrGlob::Import(_)) => buf.push_str(" (import)"), + Some(ImportOrGlob::Glob(_)) => buf.push_str(" (glob)"), None => (), } } - if let Some(Item { import, .. }) = def.macros { - buf.push_str(" m"); + if let Some(Item { def: macro_id, import, .. }) = def.macros { + buf.push_str(" macro"); + print_macro_sub_ns(buf, macro_id); match import { - Some(ImportOrExternCrate::Import(_)) => buf.push('i'), - Some(ImportOrExternCrate::Glob(_)) => buf.push('g'), - Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'), + Some(ImportOrExternCrate::Import(_)) => buf.push_str(" (import)"), + Some(ImportOrExternCrate::Glob(_)) => buf.push_str(" (glob)"), + Some(ImportOrExternCrate::ExternCrate(_)) => buf.push_str(" (extern)"), None => (), } } @@ -778,6 +795,21 @@ impl ItemScope { buf.push('\n'); } + + // Also dump legacy-textual-scope macros visible at the _end_ of the scope. + // + // For tests involving a cursor position, this might include macros that + // are _not_ visible at the cursor position. + let mut legacy_macros = self.legacy_macros().collect::<Vec<_>>(); + legacy_macros.sort_by(|(a, _), (b, _)| Ord::cmp(a, b)); + for (name, macros) in legacy_macros { + format_to!(buf, "- (legacy) {} :", name.display(db, Edition::LATEST)); + for ¯o_id in macros { + buf.push_str(" macro"); + print_macro_sub_ns(buf, macro_id); + } + buf.push('\n'); + } } pub(crate) fn shrink_to_fit(&mut self) { @@ -789,6 +821,7 @@ impl ItemScope { unresolved, declarations, impls, + builtin_derive_impls, unnamed_consts, unnamed_trait_imports, legacy_macros, @@ -812,6 +845,7 @@ impl ItemScope { unresolved.shrink_to_fit(); declarations.shrink_to_fit(); impls.shrink_to_fit(); + builtin_derive_impls.shrink_to_fit(); unnamed_consts.shrink_to_fit(); unnamed_trait_imports.shrink_to_fit(); legacy_macros.shrink_to_fit(); @@ -896,10 +930,7 @@ impl ItemInNs { /// Returns the crate defining this item (or `None` if `self` is built-in). pub fn krate(&self, db: &dyn DefDatabase) -> Option<Crate> { - match self { - ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate), - ItemInNs::Macros(id) => Some(id.module(db).krate), - } + self.module(db).map(|module_id| module_id.krate(db)) } pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> { |