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.rs145
1 files changed, 64 insertions, 81 deletions
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 544c759ed3..f9002f31fd 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -21,12 +21,9 @@ use hir_ty::{
};
use intern::Symbol;
use rustc_hash::FxHashMap;
-use syntax::{
- AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr,
- ast::{HasModuleItem, HasName},
-};
+use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName};
-use crate::{Crate, HasCrate, Module, ModuleDef, Semantics};
+use crate::{HasCrate, Module, ModuleDef, Semantics};
/// The actual data that is stored in the index. It should be as compact as
/// possible.
@@ -44,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 {
@@ -61,70 +58,6 @@ impl DeclarationLocation {
}
}
-impl<'db> FileSymbol<'db> {
- /// Create a `FileSymbol` representing a crate's root module.
- /// This is used for crate search queries like `::` or `::foo`.
- pub fn for_crate_root(db: &'db dyn HirDatabase, krate: Crate) -> Option<FileSymbol<'db>> {
- let display_name = krate.display_name(db)?;
- let crate_name = display_name.crate_name();
- let root_module = krate.root_module(db);
- let def_map = crate_def_map(db, krate.into());
- let module_data = &def_map[root_module.into()];
-
- // Get the definition source (the source file for crate roots)
- let definition = module_data.origin.definition_source(db);
- let hir_file_id = definition.file_id;
-
- // For a crate root, the "declaration" is the source file itself
- // We use the entire file's syntax node as the location
- let syntax_node = definition.value.node();
- let ptr = SyntaxNodePtr::new(&syntax_node);
-
- // For the name, we need to create a synthetic name pointer.
- // We'll use the first token of the file as a placeholder since crate roots
- // don't have an explicit name in the source.
- // We create a name_ptr pointing to the start of the file.
- let name_ptr = match &definition.value {
- crate::ModuleSource::SourceFile(sf) => {
- // Try to find the first item with a name as a reasonable location for focus
- // This is a bit of a hack but works for navigation purposes
- let first_item: Option<syntax::ast::Item> = sf.items().next();
- if let Some(item) = first_item {
- if let Some(name) = item.syntax().children().find_map(syntax::ast::Name::cast) {
- AstPtr::new(&name).wrap_left()
- } else {
- // No name found, try to use a NameRef instead
- if let Some(name_ref) =
- item.syntax().descendants().find_map(syntax::ast::NameRef::cast)
- {
- AstPtr::new(&name_ref).wrap_right()
- } else {
- return None;
- }
- }
- } else {
- return None;
- }
- }
- _ => return None,
- };
-
- let loc = DeclarationLocation { hir_file_id, ptr, name_ptr };
-
- Some(FileSymbol {
- name: Symbol::intern(crate_name.as_str()),
- 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,
- })
- }
-}
-
/// Represents an outstanding module that the symbol collector must collect symbols from.
#[derive(Debug)]
struct SymbolCollectorWork {
@@ -167,6 +100,11 @@ impl<'a> SymbolCollector<'a> {
let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered();
tracing::info!(?module, "SymbolCollector::collect");
+ // If this is a crate root module, add a symbol for the crate itself
+ if module.is_crate_root(self.db) {
+ self.push_crate_root(module);
+ }
+
// The initial work is the root module we're collecting, additional work will
// be populated as we traverse the module's definitions.
self.work.push(SymbolCollectorWork { module_id: module.into(), parent: None });
@@ -176,6 +114,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`.
+ fn push_crate_root(&mut self, module: Module) {
+ let krate = module.krate(self.db);
+ 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 };
+
+ self.symbols.insert(FileSymbol {
+ name: crate_name.symbol().clone(),
+ def: ModuleDef::Module(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(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()
}
@@ -277,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(),
@@ -312,7 +295,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(),
@@ -477,10 +460,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;
@@ -495,7 +478,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,
@@ -510,7 +493,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,
@@ -527,10 +510,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());
@@ -543,7 +526,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,
@@ -558,7 +541,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,