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.rs117
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 &macro_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> {