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.rs72
1 files changed, 70 insertions, 2 deletions
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 073142670d..544c759ed3 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -9,6 +9,7 @@ use hir_def::{
ModuleDefId, ModuleId, TraitId,
db::DefDatabase,
item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob},
+ nameres::crate_def_map,
per_ns::Item,
src::{HasChildSource, HasSource},
visibility::{Visibility, VisibilityExplicitness},
@@ -20,9 +21,12 @@ use hir_ty::{
};
use intern::Symbol;
use rustc_hash::FxHashMap;
-use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName};
+use syntax::{
+ AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr,
+ ast::{HasModuleItem, 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.
@@ -57,6 +61,70 @@ 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 {