@@ -9,6 +9,7 @@ use indexmap::IndexMap;
99use itertools:: Itertools ;
1010use rustc_hash:: { FxHashSet , FxHasher } ;
1111use smallvec:: SmallVec ;
12+ use stdx:: format_to;
1213use triomphe:: Arc ;
1314
1415use crate :: {
@@ -53,13 +54,25 @@ pub struct ImportMap {
5354 fst : fst:: Map < Vec < u8 > > ,
5455}
5556
56- #[ derive( Copy , Clone , PartialEq , Eq ) ]
57+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Ord , PartialOrd ) ]
5758enum IsTraitAssocItem {
5859 Yes ,
5960 No ,
6061}
6162
6263impl ImportMap {
64+ pub fn dump ( & self , db : & dyn DefDatabase ) -> String {
65+ let mut out = String :: new ( ) ;
66+ for ( k, v) in self . map . iter ( ) {
67+ format_to ! ( out, "{:?} ({:?}) -> " , k, v. 1 ) ;
68+ for v in & v. 0 {
69+ format_to ! ( out, "{}:{:?}, " , v. name. display( db. upcast( ) ) , v. container) ;
70+ }
71+ format_to ! ( out, "\n " ) ;
72+ }
73+ out
74+ }
75+
6376 pub ( crate ) fn import_map_query ( db : & dyn DefDatabase , krate : CrateId ) -> Arc < Self > {
6477 let _p = profile:: span ( "import_map_query" ) ;
6578
@@ -68,26 +81,31 @@ impl ImportMap {
6881 let mut importables: Vec < _ > = map
6982 . iter ( )
7083 // We've only collected items, whose name cannot be tuple field.
71- . flat_map ( |( & item, ( info, _) ) | {
72- info. iter ( )
73- . map ( move |info| ( item, info. name . as_str ( ) . unwrap ( ) . to_ascii_lowercase ( ) ) )
84+ . flat_map ( |( & item, ( info, is_assoc) ) | {
85+ info. iter ( ) . map ( move |info| {
86+ ( item, * is_assoc, info. name . as_str ( ) . unwrap ( ) . to_ascii_lowercase ( ) )
87+ } )
7488 } )
7589 . collect ( ) ;
76- importables. sort_by ( |( _, lhs_name) , ( _, rhs_name) | lhs_name. cmp ( rhs_name) ) ;
90+ importables. sort_by ( |( _, l_is_assoc, lhs_name) , ( _, r_is_assoc, rhs_name) | {
91+ lhs_name. cmp ( rhs_name) . then_with ( || l_is_assoc. cmp ( r_is_assoc) )
92+ } ) ;
7793 importables. dedup ( ) ;
7894
7995 // Build the FST, taking care not to insert duplicate values.
8096 let mut builder = fst:: MapBuilder :: memory ( ) ;
81- let iter =
82- importables. iter ( ) . enumerate ( ) . dedup_by ( |( _, ( _, lhs) ) , ( _, ( _, rhs) ) | lhs == rhs) ;
83- for ( start_idx, ( _, name) ) in iter {
97+ let iter = importables
98+ . iter ( )
99+ . enumerate ( )
100+ . dedup_by ( |( _, ( _, _, lhs) ) , ( _, ( _, _, rhs) ) | lhs == rhs) ;
101+ for ( start_idx, ( _, _, name) ) in iter {
84102 let _ = builder. insert ( name, start_idx as u64 ) ;
85103 }
86104
87105 Arc :: new ( ImportMap {
88106 map,
89107 fst : builder. into_map ( ) ,
90- importables : importables. into_iter ( ) . map ( |( item, _) | item) . collect ( ) ,
108+ importables : importables. into_iter ( ) . map ( |( item, _, _ ) | item) . collect ( ) ,
91109 } )
92110 }
93111
@@ -332,20 +350,20 @@ impl Query {
332350 }
333351
334352 /// Checks whether the import map entry matches the query.
335- fn import_matches (
336- & self ,
337- db : & dyn DefDatabase ,
338- import : & ImportInfo ,
339- enforce_lowercase : bool ,
340- ) -> bool {
353+ fn import_matches ( & self , import : & ImportInfo , enforce_lowercase : bool ) -> bool {
341354 let _p = profile:: span ( "import_map::Query::import_matches" ) ;
342355
343356 // FIXME: Can we get rid of the alloc here?
344- let mut input = import. name . display ( db. upcast ( ) ) . to_string ( ) ;
357+ let input = import. name . to_smol_str ( ) ;
358+ let mut _s_slot;
345359 let case_insensitive = enforce_lowercase || !self . case_sensitive ;
346- if case_insensitive {
347- input. make_ascii_lowercase ( ) ;
348- }
360+ let input = if case_insensitive {
361+ _s_slot = String :: from ( input) ;
362+ _s_slot. make_ascii_lowercase ( ) ;
363+ & * _s_slot
364+ } else {
365+ & * input
366+ } ;
349367
350368 let query_string = if case_insensitive { & self . lowercased } else { & self . query } ;
351369
@@ -355,7 +373,7 @@ impl Query {
355373 SearchMode :: Fuzzy => {
356374 let mut input_chars = input. chars ( ) ;
357375 for query_char in query_string. chars ( ) {
358- if input_chars. find ( | & it| it == query_char) . is_none ( ) {
376+ if ! input_chars. any ( | it| it == query_char) {
359377 return false ;
360378 }
361379 }
@@ -376,6 +394,7 @@ pub fn search_dependencies(
376394 let _p = profile:: span ( "search_dependencies" ) . detail ( || format ! ( "{query:?}" ) ) ;
377395
378396 let graph = db. crate_graph ( ) ;
397+
379398 let import_maps: Vec < _ > =
380399 graph[ krate] . dependencies . iter ( ) . map ( |dep| db. import_map ( dep. crate_id ) ) . collect ( ) ;
381400
@@ -390,22 +409,28 @@ pub fn search_dependencies(
390409
391410 let mut res = FxHashSet :: default ( ) ;
392411 let mut common_importable_data_scratch = vec ! [ ] ;
412+ // FIXME: Improve this, its rather unreadable and does duplicate amount of work
393413 while let Some ( ( _, indexed_values) ) = stream. next ( ) {
394414 for & IndexedValue { index, value } in indexed_values {
395415 let import_map = & import_maps[ index] ;
396- let importables @ [ importable, ..] = & import_map. importables [ value as usize ..] else {
416+ let importables = & import_map. importables [ value as usize ..] ;
417+
418+ // Find the first item in this group that has a matching assoc mode and slice the rest away
419+ let Some ( importable) =
420+ importables. iter ( ) . position ( |it| query. matches_assoc_mode ( import_map. map [ it] . 1 ) )
421+ else {
397422 continue ;
398423 } ;
399-
400- let & ( ref importable_data, is_trait_assoc_item) = & import_map. map [ importable] ;
401- if !query. matches_assoc_mode ( is_trait_assoc_item) {
424+ let importables @ [ importable, ..] = & importables[ importable..] else {
402425 continue ;
403- }
426+ } ;
404427
428+ // Fetch all the known names of this importable item (to handle import aliases/renames)
405429 common_importable_data_scratch. extend (
406- importable_data
430+ import_map. map [ importable]
431+ . 0
407432 . iter ( )
408- . filter ( |& info| query. import_matches ( db , info, true ) )
433+ . filter ( |& info| query. import_matches ( info, true ) )
409434 // Name shared by the importable items in this group.
410435 . map ( |info| info. name . to_smol_str ( ) ) ,
411436 ) ;
@@ -419,6 +444,7 @@ pub fn search_dependencies(
419444 common_importable_data_scratch. drain ( ..) . flat_map ( |common_importable_name| {
420445 // Add the items from this name group. Those are all subsequent items in
421446 // `importables` whose name match `common_importable_name`.
447+
422448 importables
423449 . iter ( )
424450 . copied ( )
@@ -434,11 +460,8 @@ pub fn search_dependencies(
434460 . filter ( move |item| {
435461 !query. case_sensitive || {
436462 // we've already checked the common importables name case-insensitively
437- let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
438- query. matches_assoc_mode ( assoc_mode)
439- && import_infos
440- . iter ( )
441- . any ( |info| query. import_matches ( db, info, false ) )
463+ let & ( ref import_infos, _) = & import_map. map [ item] ;
464+ import_infos. iter ( ) . any ( |info| query. import_matches ( info, false ) )
442465 }
443466 } )
444467 } ) ;
0 commit comments