1
1
//! A map of all publicly exported items in a crate.
2
2
3
- use std:: { collections :: hash_map :: Entry , fmt, hash:: BuildHasherDefault } ;
3
+ use std:: { fmt, hash:: BuildHasherDefault } ;
4
4
5
5
use base_db:: CrateId ;
6
6
use fst:: { self , raw:: IndexedValue , Streamer } ;
7
7
use hir_expand:: name:: Name ;
8
8
use indexmap:: IndexMap ;
9
9
use itertools:: Itertools ;
10
- use rustc_hash:: { FxHashMap , FxHashSet , FxHasher } ;
11
- use smallvec:: { smallvec , SmallVec } ;
10
+ use rustc_hash:: { FxHashSet , FxHasher } ;
11
+ use smallvec:: SmallVec ;
12
12
use triomphe:: Arc ;
13
13
14
14
use crate :: {
@@ -103,11 +103,13 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
103
103
104
104
// We look only into modules that are public(ly reexported), starting with the crate root.
105
105
let root = def_map. module_id ( DefMap :: ROOT ) ;
106
- let mut worklist = vec ! [ ( root, 0u32 ) ] ;
107
- // Records items' minimum module depth.
108
- let mut depth_map = FxHashMap :: default ( ) ;
106
+ let mut worklist = vec ! [ root] ;
107
+ let mut visited = FxHashSet :: default ( ) ;
109
108
110
- while let Some ( ( module, depth) ) = worklist. pop ( ) {
109
+ while let Some ( module) = worklist. pop ( ) {
110
+ if !visited. insert ( module) {
111
+ continue ;
112
+ }
111
113
let ext_def_map;
112
114
let mod_data = if module. krate == krate {
113
115
& def_map[ module. local_id ]
@@ -126,6 +128,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
126
128
}
127
129
} ) ;
128
130
131
+ // FIXME: This loop might add the same entry up to 3 times per item! dedup
129
132
for ( name, per_ns) in visible_items {
130
133
for ( item, import) in per_ns. iter_items ( ) {
131
134
let attr_id = if let Some ( import) = import {
@@ -139,11 +142,10 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
139
142
ItemInNs :: Macros ( id) => Some ( id. into ( ) ) ,
140
143
}
141
144
} ;
142
- let status @ ( is_doc_hidden, is_unstable) =
143
- attr_id. map_or ( ( false , false ) , |attr_id| {
144
- let attrs = db. attrs ( attr_id) ;
145
- ( attrs. has_doc_hidden ( ) , attrs. is_unstable ( ) )
146
- } ) ;
145
+ let ( is_doc_hidden, is_unstable) = attr_id. map_or ( ( false , false ) , |attr_id| {
146
+ let attrs = db. attrs ( attr_id) ;
147
+ ( attrs. has_doc_hidden ( ) , attrs. is_unstable ( ) )
148
+ } ) ;
147
149
148
150
let import_info = ImportInfo {
149
151
name : name. clone ( ) ,
@@ -152,50 +154,6 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
152
154
is_unstable,
153
155
} ;
154
156
155
- match depth_map. entry ( item) {
156
- Entry :: Vacant ( entry) => _ = entry. insert ( ( depth, status) ) ,
157
- Entry :: Occupied ( mut entry) => {
158
- let & ( occ_depth, ( occ_is_doc_hidden, occ_is_unstable) ) = entry. get ( ) ;
159
- ( depth, occ_depth) ;
160
- let overwrite = match (
161
- is_doc_hidden,
162
- occ_is_doc_hidden,
163
- is_unstable,
164
- occ_is_unstable,
165
- ) {
166
- // no change of hiddeness or unstableness
167
- ( true , true , true , true )
168
- | ( true , true , false , false )
169
- | ( false , false , true , true )
170
- | ( false , false , false , false ) => depth < occ_depth,
171
-
172
- // either less hidden or less unstable, accept
173
- ( true , true , false , true )
174
- | ( false , true , true , true )
175
- | ( false , true , false , true )
176
- | ( false , true , false , false )
177
- | ( false , false , false , true ) => true ,
178
- // more hidden or unstable, discard
179
- ( true , true , true , false )
180
- | ( true , false , true , true )
181
- | ( true , false , true , false )
182
- | ( true , false , false , false )
183
- | ( false , false , true , false ) => false ,
184
-
185
- // exchanges doc(hidden) for unstable (and vice-versa),
186
- ( true , false , false , true ) | ( false , true , true , false ) => {
187
- depth < occ_depth
188
- }
189
- } ;
190
- // FIXME: Remove the overwrite rules as we can now record exports and
191
- // aliases for the same item
192
- if !overwrite {
193
- continue ;
194
- }
195
- entry. insert ( ( depth, status) ) ;
196
- }
197
- }
198
-
199
157
if let Some ( ModuleDefId :: TraitId ( tr) ) = item. as_module_def_id ( ) {
200
158
collect_trait_assoc_items (
201
159
db,
@@ -206,13 +164,14 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
206
164
) ;
207
165
}
208
166
209
- map. insert ( item, ( smallvec ! [ import_info] , IsTraitAssocItem :: No ) ) ;
167
+ map. entry ( item)
168
+ . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: No ) )
169
+ . 0
170
+ . push ( import_info) ;
210
171
211
- // If we've just added a module, descend into it. We might traverse modules
212
- // multiple times, but only if the module depth is smaller (else we `continue`
213
- // above).
172
+ // If we've just added a module, descend into it.
214
173
if let Some ( ModuleDefId :: ModuleId ( mod_id) ) = item. as_module_def_id ( ) {
215
- worklist. push ( ( mod_id, depth + 1 ) ) ;
174
+ worklist. push ( mod_id) ;
216
175
}
217
176
}
218
177
}
@@ -253,7 +212,11 @@ fn collect_trait_assoc_items(
253
212
is_doc_hidden : attrs. has_doc_hidden ( ) ,
254
213
is_unstable : attrs. is_unstable ( ) ,
255
214
} ;
256
- map. insert ( assoc_item, ( smallvec ! [ assoc_item_info] , IsTraitAssocItem :: Yes ) ) ;
215
+
216
+ map. entry ( assoc_item)
217
+ . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: Yes ) )
218
+ . 0
219
+ . push ( assoc_item_info) ;
257
220
}
258
221
}
259
222
@@ -284,7 +247,7 @@ impl fmt::Debug for ImportMap {
284
247
}
285
248
286
249
/// A way to match import map contents against the search query.
287
- #[ derive( Debug ) ]
250
+ #[ derive( Copy , Clone , Debug ) ]
288
251
enum SearchMode {
289
252
/// Import map entry should strictly match the query string.
290
253
Exact ,
@@ -426,7 +389,7 @@ pub fn search_dependencies(
426
389
while let Some ( ( _, indexed_values) ) = stream. next ( ) {
427
390
for & IndexedValue { index, value } in indexed_values {
428
391
let import_map = & import_maps[ index] ;
429
- let [ importable , importables @ ..] = & import_map. importables [ value as usize ..] else {
392
+ let importables @ [ importable , ..] = & import_map. importables [ value as usize ..] else {
430
393
continue ;
431
394
} ;
432
395
@@ -441,38 +404,32 @@ pub fn search_dependencies(
441
404
else {
442
405
continue ;
443
406
} ;
444
- res. insert ( * importable) ;
445
-
446
- if !importables. is_empty ( ) {
447
- // FIXME: so many allocs...
448
- // Name shared by the importable items in this group.
449
- let common_importable_name =
450
- common_importable_data. name . to_smol_str ( ) . to_ascii_lowercase ( ) ;
451
- // Add the items from this name group. Those are all subsequent items in
452
- // `importables` whose name match `common_importable_name`.
453
- let iter = importables
454
- . iter ( )
455
- . copied ( )
456
- . take_while ( |item| {
407
+
408
+ // FIXME: so many allocs...
409
+ // Name shared by the importable items in this group.
410
+ let common_importable_name =
411
+ common_importable_data. name . to_smol_str ( ) . to_ascii_lowercase ( ) ;
412
+ // Add the items from this name group. Those are all subsequent items in
413
+ // `importables` whose name match `common_importable_name`.
414
+ let iter = importables
415
+ . iter ( )
416
+ . copied ( )
417
+ . take_while ( |item| {
418
+ let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
419
+ query. matches_assoc_mode ( assoc_mode)
420
+ && import_infos. iter ( ) . any ( |info| {
421
+ info. name . to_smol_str ( ) . to_ascii_lowercase ( ) == common_importable_name
422
+ } )
423
+ } )
424
+ . filter ( |item| {
425
+ !query. case_sensitive || {
426
+ // we've already checked the common importables name case-insensitively
457
427
let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
458
428
query. matches_assoc_mode ( assoc_mode)
459
- && import_infos. iter ( ) . any ( |info| {
460
- info. name . to_smol_str ( ) . to_ascii_lowercase ( )
461
- == common_importable_name
462
- } )
463
- } )
464
- . filter ( |item| {
465
- !query. case_sensitive || {
466
- // we've already checked the common importables name case-insensitively
467
- let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
468
- query. matches_assoc_mode ( assoc_mode)
469
- && import_infos
470
- . iter ( )
471
- . any ( |info| query. import_matches ( db, info, false ) )
472
- }
473
- } ) ;
474
- res. extend ( iter) ;
475
- }
429
+ && import_infos. iter ( ) . any ( |info| query. import_matches ( db, info, false ) )
430
+ }
431
+ } ) ;
432
+ res. extend ( iter) ;
476
433
477
434
if res. len ( ) >= query. limit {
478
435
return res;
@@ -665,6 +622,7 @@ mod tests {
665
622
main:
666
623
- publ1 (t)
667
624
- real_pu2 (t)
625
+ - real_pu2::Pub (t)
668
626
- real_pub (t)
669
627
- real_pub::Pub (t)
670
628
"# ] ] ,
@@ -690,6 +648,7 @@ mod tests {
690
648
- sub (t)
691
649
- sub::Def (t)
692
650
- sub::subsub (t)
651
+ - sub::subsub::Def (t)
693
652
"# ] ] ,
694
653
) ;
695
654
}
@@ -789,7 +748,9 @@ mod tests {
789
748
- module (t)
790
749
- module::S (t)
791
750
- module::S (v)
751
+ - module::module (t)
792
752
- sub (t)
753
+ - sub::module (t)
793
754
"# ] ] ,
794
755
) ;
795
756
}
0 commit comments