@@ -5,14 +5,15 @@ use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc};
55use fst:: { self , Streamer } ;
66use indexmap:: { map:: Entry , IndexMap } ;
77use ra_db:: CrateId ;
8- use rustc_hash:: FxHasher ;
8+ use rustc_hash:: { FxHashMap , FxHasher } ;
9+ use smallvec:: SmallVec ;
910
1011use crate :: {
1112 db:: DefDatabase ,
1213 item_scope:: ItemInNs ,
1314 path:: { ModPath , PathKind } ,
1415 visibility:: Visibility ,
15- ModuleDefId , ModuleId ,
16+ AssocItemId , ModuleDefId , ModuleId , TraitId ,
1617} ;
1718
1819type FxIndexMap < K , V > = IndexMap < K , V , BuildHasherDefault < FxHasher > > ;
@@ -34,6 +35,7 @@ pub struct ImportInfo {
3435///
3536/// Note that all paths are relative to the containing crate's root, so the crate name still needs
3637/// to be prepended to the `ModPath` before the path is valid.
38+ #[ derive( Default ) ]
3739pub struct ImportMap {
3840 map : FxIndexMap < ItemInNs , ImportInfo > ,
3941
@@ -45,13 +47,17 @@ pub struct ImportMap {
4547 /// the index of the first one.
4648 importables : Vec < ItemInNs > ,
4749 fst : fst:: Map < Vec < u8 > > ,
50+
51+ /// Maps names of associated items to the item's ID. Only includes items whose defining trait is
52+ /// exported.
53+ assoc_map : FxHashMap < String , SmallVec < [ AssocItemId ; 1 ] > > ,
4854}
4955
5056impl ImportMap {
5157 pub fn import_map_query ( db : & dyn DefDatabase , krate : CrateId ) -> Arc < Self > {
5258 let _p = ra_prof:: profile ( "import_map_query" ) ;
5359 let def_map = db. crate_def_map ( krate) ;
54- let mut import_map = FxIndexMap :: with_capacity_and_hasher ( 64 , Default :: default ( ) ) ;
60+ let mut import_map = Self :: default ( ) ;
5561
5662 // We look only into modules that are public(ly reexported), starting with the crate root.
5763 let empty = ModPath { kind : PathKind :: Plain , segments : vec ! [ ] } ;
@@ -85,7 +91,7 @@ impl ImportMap {
8591
8692 for item in per_ns. iter_items ( ) {
8793 let path = mk_path ( ) ;
88- match import_map. entry ( item) {
94+ match import_map. map . entry ( item) {
8995 Entry :: Vacant ( entry) => {
9096 entry. insert ( ImportInfo { path, container : module } ) ;
9197 }
@@ -105,11 +111,16 @@ impl ImportMap {
105111 if let Some ( ModuleDefId :: ModuleId ( mod_id) ) = item. as_module_def_id ( ) {
106112 worklist. push ( ( mod_id, mk_path ( ) ) ) ;
107113 }
114+
115+ // If we've added a path to a trait, add the trait's methods to the method map.
116+ if let Some ( ModuleDefId :: TraitId ( tr) ) = item. as_module_def_id ( ) {
117+ import_map. collect_trait_methods ( db, tr) ;
118+ }
108119 }
109120 }
110121 }
111122
112- let mut importables = import_map. iter ( ) . collect :: < Vec < _ > > ( ) ;
123+ let mut importables = import_map. map . iter ( ) . collect :: < Vec < _ > > ( ) ;
113124
114125 importables. sort_by ( cmp) ;
115126
@@ -133,10 +144,10 @@ impl ImportMap {
133144 builder. insert ( key, start as u64 ) . unwrap ( ) ;
134145 }
135146
136- let fst = fst:: Map :: new ( builder. into_inner ( ) . unwrap ( ) ) . unwrap ( ) ;
137- let importables = importables. iter ( ) . map ( |( item, _) | * * item) . collect ( ) ;
147+ import_map . fst = fst:: Map :: new ( builder. into_inner ( ) . unwrap ( ) ) . unwrap ( ) ;
148+ import_map . importables = importables. iter ( ) . map ( |( item, _) | * * item) . collect ( ) ;
138149
139- Arc :: new ( Self { map : import_map, fst , importables } )
150+ Arc :: new ( import_map)
140151 }
141152
142153 /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root.
@@ -147,6 +158,13 @@ impl ImportMap {
147158 pub fn import_info_for ( & self , item : ItemInNs ) -> Option < & ImportInfo > {
148159 self . map . get ( & item)
149160 }
161+
162+ fn collect_trait_methods ( & mut self , db : & dyn DefDatabase , tr : TraitId ) {
163+ let data = db. trait_data ( tr) ;
164+ for ( name, item) in data. items . iter ( ) {
165+ self . assoc_map . entry ( name. to_string ( ) ) . or_default ( ) . push ( * item) ;
166+ }
167+ }
150168}
151169
152170impl PartialEq for ImportMap {
@@ -290,6 +308,19 @@ pub fn search_dependencies<'a>(
290308 }
291309 }
292310
311+ // Add all exported associated items whose names match the query (exactly).
312+ for map in & import_maps {
313+ if let Some ( v) = map. assoc_map . get ( & query. query ) {
314+ res. extend ( v. iter ( ) . map ( |& assoc| {
315+ ItemInNs :: Types ( match assoc {
316+ AssocItemId :: FunctionId ( it) => it. into ( ) ,
317+ AssocItemId :: ConstId ( it) => it. into ( ) ,
318+ AssocItemId :: TypeAliasId ( it) => it. into ( ) ,
319+ } )
320+ } ) ) ;
321+ }
322+ }
323+
293324 res
294325}
295326
0 commit comments