Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/symbols.rs')
| -rw-r--r-- | crates/hir/src/symbols.rs | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 073142670d..c088f3aa0c 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -5,10 +5,11 @@ use std::marker::PhantomData; use base_db::FxIndexSet; use either::Either; use hir_def::{ - AdtId, AssocItemId, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, + AdtId, AssocItemId, AstIdLoc, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId, + Lookup, MacroId, ModuleDefId, ModuleId, TraitId, db::DefDatabase, item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob}, + nameres::crate_def_map, per_ns::Item, src::{HasChildSource, HasSource}, visibility::{Visibility, VisibilityExplicitness}, @@ -22,7 +23,7 @@ use intern::Symbol; use rustc_hash::FxHashMap; use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName}; -use crate::{HasCrate, Module, ModuleDef, Semantics}; +use crate::{Crate, HasCrate, Module, ModuleDef, Semantics}; /// The actual data that is stored in the index. It should be as compact as /// possible. @@ -40,14 +41,14 @@ pub struct FileSymbol<'db> { _marker: PhantomData<&'db ()>, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct DeclarationLocation { /// The file id for both the `ptr` and `name_ptr`. pub hir_file_id: HirFileId, /// This points to the whole syntax node of the declaration. pub ptr: SyntaxNodePtr, /// This points to the [`syntax::ast::Name`] identifier of the declaration. - pub name_ptr: AstPtr<Either<syntax::ast::Name, syntax::ast::NameRef>>, + pub name_ptr: Option<AstPtr<Either<syntax::ast::Name, syntax::ast::NameRef>>>, } impl DeclarationLocation { @@ -108,6 +109,51 @@ impl<'a> SymbolCollector<'a> { } } + /// Push a symbol for a crate's root module. + /// This allows crate roots to appear in the symbol index for queries like `::` or `::foo`. + pub fn push_crate_root(&mut self, krate: Crate) { + let Some(display_name) = krate.display_name(self.db) else { return }; + let crate_name = display_name.crate_name(); + let canonical_name = display_name.canonical_name(); + + let def_map = crate_def_map(self.db, krate.into()); + let module_data = &def_map[def_map.crate_root(self.db)]; + + let definition = module_data.origin.definition_source(self.db); + let hir_file_id = definition.file_id; + let syntax_node = definition.value.node(); + let ptr = SyntaxNodePtr::new(&syntax_node); + + let loc = DeclarationLocation { hir_file_id, ptr, name_ptr: None }; + let root_module = krate.root_module(self.db); + + self.symbols.insert(FileSymbol { + name: crate_name.symbol().clone(), + def: ModuleDef::Module(root_module), + loc, + container_name: None, + is_alias: false, + is_assoc: false, + is_import: false, + do_not_complete: Complete::Yes, + _marker: PhantomData, + }); + + if canonical_name != crate_name.symbol() { + self.symbols.insert(FileSymbol { + name: canonical_name.clone(), + def: ModuleDef::Module(root_module), + loc, + container_name: None, + is_alias: false, + is_assoc: false, + is_import: false, + do_not_complete: Complete::Yes, + _marker: PhantomData, + }); + } + } + pub fn finish(self) -> Box<[FileSymbol<'a>]> { self.symbols.into_iter().collect() } @@ -123,6 +169,7 @@ impl<'a> SymbolCollector<'a> { fn collect_from_module(&mut self, module_id: ModuleId) { let collect_pub_only = self.collect_pub_only; + let is_block_module = module_id.is_block_module(self.db); let push_decl = |this: &mut Self, def: ModuleDefId, name, vis| { if collect_pub_only && vis != Visibility::Public { return; @@ -194,6 +241,10 @@ impl<'a> SymbolCollector<'a> { let source = import_child_source_cache .entry(i.use_) .or_insert_with(|| i.use_.child_source(this.db)); + if is_block_module && source.file_id.is_macro() { + // Macros tend to generate a lot of imports, the user really won't care about them + return; + } let Some(use_tree_src) = source.value.get(i.idx) else { return }; let rename = use_tree_src.rename().and_then(|rename| rename.name()); let name_syntax = match rename { @@ -209,7 +260,7 @@ impl<'a> SymbolCollector<'a> { let dec_loc = DeclarationLocation { hir_file_id: source.file_id, ptr: SyntaxNodePtr::new(use_tree_src.syntax()), - name_ptr: AstPtr::new(&name_syntax), + name_ptr: Some(AstPtr::new(&name_syntax)), }; this.symbols.insert(FileSymbol { name: name.symbol().clone(), @@ -230,6 +281,12 @@ impl<'a> SymbolCollector<'a> { return; } let loc = i.lookup(this.db); + if is_block_module && loc.ast_id().file_id.is_macro() { + // Macros (especially derivves) tend to generate renamed extern crate items, + // the user really won't care about them + return; + } + let source = loc.source(this.db); let rename = source.value.rename().and_then(|rename| rename.name()); @@ -244,7 +301,7 @@ impl<'a> SymbolCollector<'a> { let dec_loc = DeclarationLocation { hir_file_id: source.file_id, ptr: SyntaxNodePtr::new(source.value.syntax()), - name_ptr: AstPtr::new(&name_syntax), + name_ptr: Some(AstPtr::new(&name_syntax)), }; this.symbols.insert(FileSymbol { name: name.symbol().clone(), @@ -409,10 +466,10 @@ impl<'a> SymbolCollector<'a> { let source = loc.source(self.db); let Some(name_node) = source.value.name() else { return Complete::Yes }; let def = ModuleDef::from(id.into()); - let dec_loc = DeclarationLocation { + let loc = DeclarationLocation { hir_file_id: source.file_id, ptr: SyntaxNodePtr::new(source.value.syntax()), - name_ptr: AstPtr::new(&name_node).wrap_left(), + name_ptr: Some(AstPtr::new(&name_node).wrap_left()), }; let mut do_not_complete = Complete::Yes; @@ -427,7 +484,7 @@ impl<'a> SymbolCollector<'a> { self.symbols.insert(FileSymbol { name: alias.clone(), def, - loc: dec_loc.clone(), + loc, container_name: self.current_container_name.clone(), is_alias: true, is_assoc, @@ -442,7 +499,7 @@ impl<'a> SymbolCollector<'a> { name: name.symbol().clone(), def, container_name: self.current_container_name.clone(), - loc: dec_loc, + loc, is_alias: false, is_assoc, is_import: false, @@ -459,10 +516,10 @@ impl<'a> SymbolCollector<'a> { let Some(declaration) = module_data.origin.declaration() else { return }; let module = declaration.to_node(self.db); let Some(name_node) = module.name() else { return }; - let dec_loc = DeclarationLocation { + let loc = DeclarationLocation { hir_file_id: declaration.file_id, ptr: SyntaxNodePtr::new(module.syntax()), - name_ptr: AstPtr::new(&name_node).wrap_left(), + name_ptr: Some(AstPtr::new(&name_node).wrap_left()), }; let def = ModuleDef::Module(module_id.into()); @@ -475,7 +532,7 @@ impl<'a> SymbolCollector<'a> { self.symbols.insert(FileSymbol { name: alias.clone(), def, - loc: dec_loc.clone(), + loc, container_name: self.current_container_name.clone(), is_alias: true, is_assoc: false, @@ -490,7 +547,7 @@ impl<'a> SymbolCollector<'a> { name: name.symbol().clone(), def: ModuleDef::Module(module_id.into()), container_name: self.current_container_name.clone(), - loc: dec_loc, + loc, is_alias: false, is_assoc: false, is_import: false, |