@@ -21,12 +21,9 @@ use hir_ty::{
2121} ;
2222use intern:: Symbol ;
2323use rustc_hash:: FxHashMap ;
24- use syntax:: {
25- AstNode , AstPtr , SyntaxNode , SyntaxNodePtr , ToSmolStr ,
26- ast:: { HasModuleItem , HasName } ,
27- } ;
24+ use syntax:: { AstNode , AstPtr , SyntaxNode , SyntaxNodePtr , ToSmolStr , ast:: HasName } ;
2825
29- use crate :: { Crate , HasCrate , Module , ModuleDef , Semantics } ;
26+ use crate :: { HasCrate , Module , ModuleDef , Semantics } ;
3027
3128/// The actual data that is stored in the index. It should be as compact as
3229/// possible.
@@ -44,14 +41,14 @@ pub struct FileSymbol<'db> {
4441 _marker : PhantomData < & ' db ( ) > ,
4542}
4643
47- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
44+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
4845pub struct DeclarationLocation {
4946 /// The file id for both the `ptr` and `name_ptr`.
5047 pub hir_file_id : HirFileId ,
5148 /// This points to the whole syntax node of the declaration.
5249 pub ptr : SyntaxNodePtr ,
5350 /// This points to the [`syntax::ast::Name`] identifier of the declaration.
54- pub name_ptr : AstPtr < Either < syntax:: ast:: Name , syntax:: ast:: NameRef > > ,
51+ pub name_ptr : Option < AstPtr < Either < syntax:: ast:: Name , syntax:: ast:: NameRef > > > ,
5552}
5653
5754impl DeclarationLocation {
@@ -61,70 +58,6 @@ impl DeclarationLocation {
6158 }
6259}
6360
64- impl < ' db > FileSymbol < ' db > {
65- /// Create a `FileSymbol` representing a crate's root module.
66- /// This is used for crate search queries like `::` or `::foo`.
67- pub fn for_crate_root ( db : & ' db dyn HirDatabase , krate : Crate ) -> Option < FileSymbol < ' db > > {
68- let display_name = krate. display_name ( db) ?;
69- let crate_name = display_name. crate_name ( ) ;
70- let root_module = krate. root_module ( db) ;
71- let def_map = crate_def_map ( db, krate. into ( ) ) ;
72- let module_data = & def_map[ root_module. into ( ) ] ;
73-
74- // Get the definition source (the source file for crate roots)
75- let definition = module_data. origin . definition_source ( db) ;
76- let hir_file_id = definition. file_id ;
77-
78- // For a crate root, the "declaration" is the source file itself
79- // We use the entire file's syntax node as the location
80- let syntax_node = definition. value . node ( ) ;
81- let ptr = SyntaxNodePtr :: new ( & syntax_node) ;
82-
83- // For the name, we need to create a synthetic name pointer.
84- // We'll use the first token of the file as a placeholder since crate roots
85- // don't have an explicit name in the source.
86- // We create a name_ptr pointing to the start of the file.
87- let name_ptr = match & definition. value {
88- crate :: ModuleSource :: SourceFile ( sf) => {
89- // Try to find the first item with a name as a reasonable location for focus
90- // This is a bit of a hack but works for navigation purposes
91- let first_item: Option < syntax:: ast:: Item > = sf. items ( ) . next ( ) ;
92- if let Some ( item) = first_item {
93- if let Some ( name) = item. syntax ( ) . children ( ) . find_map ( syntax:: ast:: Name :: cast) {
94- AstPtr :: new ( & name) . wrap_left ( )
95- } else {
96- // No name found, try to use a NameRef instead
97- if let Some ( name_ref) =
98- item. syntax ( ) . descendants ( ) . find_map ( syntax:: ast:: NameRef :: cast)
99- {
100- AstPtr :: new ( & name_ref) . wrap_right ( )
101- } else {
102- return None ;
103- }
104- }
105- } else {
106- return None ;
107- }
108- }
109- _ => return None ,
110- } ;
111-
112- let loc = DeclarationLocation { hir_file_id, ptr, name_ptr } ;
113-
114- Some ( FileSymbol {
115- name : Symbol :: intern ( crate_name. as_str ( ) ) ,
116- def : ModuleDef :: Module ( root_module) ,
117- loc,
118- container_name : None ,
119- is_alias : false ,
120- is_assoc : false ,
121- is_import : false ,
122- do_not_complete : Complete :: Yes ,
123- _marker : PhantomData ,
124- } )
125- }
126- }
127-
12861/// Represents an outstanding module that the symbol collector must collect symbols from.
12962#[ derive( Debug ) ]
13063struct SymbolCollectorWork {
@@ -167,6 +100,11 @@ impl<'a> SymbolCollector<'a> {
167100 let _p = tracing:: info_span!( "SymbolCollector::collect" , ?module) . entered ( ) ;
168101 tracing:: info!( ?module, "SymbolCollector::collect" ) ;
169102
103+ // If this is a crate root module, add a symbol for the crate itself
104+ if module. is_crate_root ( self . db ) {
105+ self . push_crate_root ( module) ;
106+ }
107+
170108 // The initial work is the root module we're collecting, additional work will
171109 // be populated as we traverse the module's definitions.
172110 self . work . push ( SymbolCollectorWork { module_id : module. into ( ) , parent : None } ) ;
@@ -176,6 +114,51 @@ impl<'a> SymbolCollector<'a> {
176114 }
177115 }
178116
117+ /// Push a symbol for a crate's root module.
118+ /// This allows crate roots to appear in the symbol index for queries like `::` or `::foo`.
119+ fn push_crate_root ( & mut self , module : Module ) {
120+ let krate = module. krate ( self . db ) ;
121+ let Some ( display_name) = krate. display_name ( self . db ) else { return } ;
122+ let crate_name = display_name. crate_name ( ) ;
123+ let canonical_name = display_name. canonical_name ( ) ;
124+
125+ let def_map = crate_def_map ( self . db , krate. into ( ) ) ;
126+ let module_data = & def_map[ def_map. crate_root ( self . db ) ] ;
127+
128+ let definition = module_data. origin . definition_source ( self . db ) ;
129+ let hir_file_id = definition. file_id ;
130+ let syntax_node = definition. value . node ( ) ;
131+ let ptr = SyntaxNodePtr :: new ( & syntax_node) ;
132+
133+ let loc = DeclarationLocation { hir_file_id, ptr, name_ptr : None } ;
134+
135+ self . symbols . insert ( FileSymbol {
136+ name : crate_name. symbol ( ) . clone ( ) ,
137+ def : ModuleDef :: Module ( module) ,
138+ loc,
139+ container_name : None ,
140+ is_alias : false ,
141+ is_assoc : false ,
142+ is_import : false ,
143+ do_not_complete : Complete :: Yes ,
144+ _marker : PhantomData ,
145+ } ) ;
146+
147+ if canonical_name != crate_name. symbol ( ) {
148+ self . symbols . insert ( FileSymbol {
149+ name : canonical_name. clone ( ) ,
150+ def : ModuleDef :: Module ( module) ,
151+ loc,
152+ container_name : None ,
153+ is_alias : false ,
154+ is_assoc : false ,
155+ is_import : false ,
156+ do_not_complete : Complete :: Yes ,
157+ _marker : PhantomData ,
158+ } ) ;
159+ }
160+ }
161+
179162 pub fn finish ( self ) -> Box < [ FileSymbol < ' a > ] > {
180163 self . symbols . into_iter ( ) . collect ( )
181164 }
@@ -277,7 +260,7 @@ impl<'a> SymbolCollector<'a> {
277260 let dec_loc = DeclarationLocation {
278261 hir_file_id : source. file_id ,
279262 ptr : SyntaxNodePtr :: new ( use_tree_src. syntax ( ) ) ,
280- name_ptr : AstPtr :: new ( & name_syntax) ,
263+ name_ptr : Some ( AstPtr :: new ( & name_syntax) ) ,
281264 } ;
282265 this. symbols . insert ( FileSymbol {
283266 name : name. symbol ( ) . clone ( ) ,
@@ -312,7 +295,7 @@ impl<'a> SymbolCollector<'a> {
312295 let dec_loc = DeclarationLocation {
313296 hir_file_id : source. file_id ,
314297 ptr : SyntaxNodePtr :: new ( source. value . syntax ( ) ) ,
315- name_ptr : AstPtr :: new ( & name_syntax) ,
298+ name_ptr : Some ( AstPtr :: new ( & name_syntax) ) ,
316299 } ;
317300 this. symbols . insert ( FileSymbol {
318301 name : name. symbol ( ) . clone ( ) ,
@@ -477,10 +460,10 @@ impl<'a> SymbolCollector<'a> {
477460 let source = loc. source ( self . db ) ;
478461 let Some ( name_node) = source. value . name ( ) else { return Complete :: Yes } ;
479462 let def = ModuleDef :: from ( id. into ( ) ) ;
480- let dec_loc = DeclarationLocation {
463+ let loc = DeclarationLocation {
481464 hir_file_id : source. file_id ,
482465 ptr : SyntaxNodePtr :: new ( source. value . syntax ( ) ) ,
483- name_ptr : AstPtr :: new ( & name_node) . wrap_left ( ) ,
466+ name_ptr : Some ( AstPtr :: new ( & name_node) . wrap_left ( ) ) ,
484467 } ;
485468
486469 let mut do_not_complete = Complete :: Yes ;
@@ -495,7 +478,7 @@ impl<'a> SymbolCollector<'a> {
495478 self . symbols . insert ( FileSymbol {
496479 name : alias. clone ( ) ,
497480 def,
498- loc : dec_loc . clone ( ) ,
481+ loc,
499482 container_name : self . current_container_name . clone ( ) ,
500483 is_alias : true ,
501484 is_assoc,
@@ -510,7 +493,7 @@ impl<'a> SymbolCollector<'a> {
510493 name : name. symbol ( ) . clone ( ) ,
511494 def,
512495 container_name : self . current_container_name . clone ( ) ,
513- loc : dec_loc ,
496+ loc,
514497 is_alias : false ,
515498 is_assoc,
516499 is_import : false ,
@@ -527,10 +510,10 @@ impl<'a> SymbolCollector<'a> {
527510 let Some ( declaration) = module_data. origin . declaration ( ) else { return } ;
528511 let module = declaration. to_node ( self . db ) ;
529512 let Some ( name_node) = module. name ( ) else { return } ;
530- let dec_loc = DeclarationLocation {
513+ let loc = DeclarationLocation {
531514 hir_file_id : declaration. file_id ,
532515 ptr : SyntaxNodePtr :: new ( module. syntax ( ) ) ,
533- name_ptr : AstPtr :: new ( & name_node) . wrap_left ( ) ,
516+ name_ptr : Some ( AstPtr :: new ( & name_node) . wrap_left ( ) ) ,
534517 } ;
535518
536519 let def = ModuleDef :: Module ( module_id. into ( ) ) ;
@@ -543,7 +526,7 @@ impl<'a> SymbolCollector<'a> {
543526 self . symbols . insert ( FileSymbol {
544527 name : alias. clone ( ) ,
545528 def,
546- loc : dec_loc . clone ( ) ,
529+ loc,
547530 container_name : self . current_container_name . clone ( ) ,
548531 is_alias : true ,
549532 is_assoc : false ,
@@ -558,7 +541,7 @@ impl<'a> SymbolCollector<'a> {
558541 name : name. symbol ( ) . clone ( ) ,
559542 def : ModuleDef :: Module ( module_id. into ( ) ) ,
560543 container_name : self . current_container_name . clone ( ) ,
561- loc : dec_loc ,
544+ loc,
562545 is_alias : false ,
563546 is_assoc : false ,
564547 is_import : false ,
0 commit comments