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 | 145 |
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, |