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.rs87
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,