@@ -85,6 +85,74 @@ impl fmt::Debug for RawVisibilityId {
8585 }
8686}
8787
88+ #[ salsa_macros:: tracked( returns( ref) ) ]
89+ pub ( crate ) fn file_item_tree_query ( db : & dyn DefDatabase , file_id : HirFileId ) -> ItemTree {
90+ let _p = tracing:: info_span!( "file_item_tree_query" , ?file_id) . entered ( ) ;
91+
92+ let ctx = lower:: Ctx :: new ( db, file_id) ;
93+ let syntax = db. parse_or_expand ( file_id) ;
94+ let mut item_tree = match_ast ! {
95+ match syntax {
96+ ast:: SourceFile ( file) => {
97+ let top_attrs = RawAttrs :: new( db, & file, ctx. span_map( ) ) ;
98+ let mut item_tree = ctx. lower_module_items( & file) ;
99+ item_tree. top_attrs = top_attrs;
100+ item_tree
101+ } ,
102+ ast:: MacroItems ( items) => {
103+ ctx. lower_module_items( & items)
104+ } ,
105+ ast:: MacroStmts ( stmts) => {
106+ // The produced statements can include items, which should be added as top-level
107+ // items.
108+ ctx. lower_macro_stmts( stmts)
109+ } ,
110+ _ => {
111+ if never!( syntax. kind( ) == SyntaxKind :: ERROR , "{:?} from {:?} {}" , file_id, syntax, syntax) {
112+ return Default :: default ( ) ;
113+ }
114+ panic!( "cannot create item tree for file {file_id:?} from {syntax:?} {syntax}" ) ;
115+ } ,
116+ }
117+ } ;
118+
119+ item_tree. shrink_to_fit ( ) ;
120+ item_tree
121+ }
122+
123+ #[ salsa_macros:: tracked( returns( ref) ) ]
124+ pub ( crate ) fn block_item_tree_query ( db : & dyn DefDatabase , block : BlockId ) -> Arc < ItemTree > {
125+ let _p = tracing:: info_span!( "block_item_tree_query" , ?block) . entered ( ) ;
126+ // Blocks have a tendency to be empty due to macro calls that do not expand to items,
127+ // so deduplicate this case via `Arc` to reduce the size of the query storage here.
128+ static EMPTY : OnceLock < Arc < ItemTree > > = OnceLock :: new ( ) ;
129+
130+ let loc = block. lookup ( db) ;
131+ let block = loc. ast_id . to_node ( db) ;
132+
133+ let ctx = lower:: Ctx :: new ( db, loc. ast_id . file_id ) ;
134+ let mut item_tree = ctx. lower_block ( & block) ;
135+ if item_tree. data . is_empty ( )
136+ && item_tree. top_level . is_empty ( )
137+ && item_tree. attrs . is_empty ( )
138+ && item_tree. top_attrs . is_empty ( )
139+ {
140+ EMPTY
141+ . get_or_init ( || {
142+ Arc :: new ( ItemTree {
143+ top_level : Box :: new ( [ ] ) ,
144+ attrs : FxHashMap :: default ( ) ,
145+ data : FxHashMap :: default ( ) ,
146+ top_attrs : RawAttrs :: EMPTY ,
147+ vis : ItemVisibilities { arena : Box :: new ( [ ] ) } ,
148+ } )
149+ } )
150+ . clone ( )
151+ } else {
152+ item_tree. shrink_to_fit ( ) ;
153+ Arc :: new ( item_tree)
154+ }
155+ }
88156/// The item tree of a source file.
89157#[ derive( Debug , Default , Eq , PartialEq ) ]
90158pub struct ItemTree {
@@ -97,90 +165,6 @@ pub struct ItemTree {
97165}
98166
99167impl ItemTree {
100- pub ( crate ) fn file_item_tree_query ( db : & dyn DefDatabase , file_id : HirFileId ) -> Arc < ItemTree > {
101- let _p = tracing:: info_span!( "file_item_tree_query" , ?file_id) . entered ( ) ;
102- static EMPTY : OnceLock < Arc < ItemTree > > = OnceLock :: new ( ) ;
103-
104- let ctx = lower:: Ctx :: new ( db, file_id) ;
105- let syntax = db. parse_or_expand ( file_id) ;
106- let mut item_tree = match_ast ! {
107- match syntax {
108- ast:: SourceFile ( file) => {
109- let top_attrs = RawAttrs :: new( db, & file, ctx. span_map( ) ) ;
110- let mut item_tree = ctx. lower_module_items( & file) ;
111- item_tree. top_attrs = top_attrs;
112- item_tree
113- } ,
114- ast:: MacroItems ( items) => {
115- ctx. lower_module_items( & items)
116- } ,
117- ast:: MacroStmts ( stmts) => {
118- // The produced statements can include items, which should be added as top-level
119- // items.
120- ctx. lower_macro_stmts( stmts)
121- } ,
122- _ => {
123- if never!( syntax. kind( ) == SyntaxKind :: ERROR , "{:?} from {:?} {}" , file_id, syntax, syntax) {
124- return Default :: default ( ) ;
125- }
126- panic!( "cannot create item tree for file {file_id:?} from {syntax:?} {syntax}" ) ;
127- } ,
128- }
129- } ;
130-
131- if item_tree. data . is_empty ( )
132- && item_tree. top_level . is_empty ( )
133- && item_tree. attrs . is_empty ( )
134- && item_tree. top_attrs . is_empty ( )
135- {
136- EMPTY
137- . get_or_init ( || {
138- Arc :: new ( ItemTree {
139- top_level : Box :: new ( [ ] ) ,
140- attrs : FxHashMap :: default ( ) ,
141- data : FxHashMap :: default ( ) ,
142- top_attrs : RawAttrs :: EMPTY ,
143- vis : ItemVisibilities { arena : Box :: new ( [ ] ) } ,
144- } )
145- } )
146- . clone ( )
147- } else {
148- item_tree. shrink_to_fit ( ) ;
149- Arc :: new ( item_tree)
150- }
151- }
152-
153- pub ( crate ) fn block_item_tree_query ( db : & dyn DefDatabase , block : BlockId ) -> Arc < ItemTree > {
154- let _p = tracing:: info_span!( "block_item_tree_query" , ?block) . entered ( ) ;
155- static EMPTY : OnceLock < Arc < ItemTree > > = OnceLock :: new ( ) ;
156-
157- let loc = block. lookup ( db) ;
158- let block = loc. ast_id . to_node ( db) ;
159-
160- let ctx = lower:: Ctx :: new ( db, loc. ast_id . file_id ) ;
161- let mut item_tree = ctx. lower_block ( & block) ;
162- if item_tree. data . is_empty ( )
163- && item_tree. top_level . is_empty ( )
164- && item_tree. attrs . is_empty ( )
165- && item_tree. top_attrs . is_empty ( )
166- {
167- EMPTY
168- . get_or_init ( || {
169- Arc :: new ( ItemTree {
170- top_level : Box :: new ( [ ] ) ,
171- attrs : FxHashMap :: default ( ) ,
172- data : FxHashMap :: default ( ) ,
173- top_attrs : RawAttrs :: EMPTY ,
174- vis : ItemVisibilities { arena : Box :: new ( [ ] ) } ,
175- } )
176- } )
177- . clone ( )
178- } else {
179- item_tree. shrink_to_fit ( ) ;
180- Arc :: new ( item_tree)
181- }
182- }
183-
184168 /// Returns an iterator over all items located at the top level of the `HirFileId` this
185169 /// `ItemTree` was created from.
186170 pub ( crate ) fn top_level_items ( & self ) -> & [ ModItemId ] {
@@ -297,10 +281,10 @@ impl TreeId {
297281 Self { file, block }
298282 }
299283
300- pub ( crate ) fn item_tree ( & self , db : & dyn DefDatabase ) -> Arc < ItemTree > {
284+ pub ( crate ) fn item_tree < ' db > ( & self , db : & ' db dyn DefDatabase ) -> & ' db ItemTree {
301285 match self . block {
302- Some ( block) => db . block_item_tree ( block) ,
303- None => db . file_item_tree ( self . file ) ,
286+ Some ( block) => block_item_tree_query ( db , block) ,
287+ None => file_item_tree_query ( db , self . file ) ,
304288 }
305289 }
306290
0 commit comments