@@ -12,18 +12,29 @@ use crate::assist_config::InsertUseConfig;
1212#[ derive( Debug ) ]
1313pub ( crate ) enum ImportCandidate {
1414 /// Simple name like 'HashMap'
15- UnqualifiedName ( String ) ,
15+ UnqualifiedName ( PathImportCandidate ) ,
1616 /// First part of the qualified name.
1717 /// For 'std::collections::HashMap', that will be 'std'.
18- QualifierStart ( String ) ,
18+ QualifierStart ( PathImportCandidate ) ,
1919 /// A trait associated function (with no self parameter) or associated constant.
20- /// For 'test_mod::TestEnum::test_function', `Type ` is the `test_mod::TestEnum` expression type
21- /// and `String ` is the `test_function`
22- TraitAssocItem ( hir :: Type , String ) ,
20+ /// For 'test_mod::TestEnum::test_function', `ty ` is the `test_mod::TestEnum` expression type
21+ /// and `name ` is the `test_function`
22+ TraitAssocItem ( TraitImportCandidate ) ,
2323 /// A trait method with self parameter.
24- /// For 'test_enum.test_method()', `Type` is the `test_enum` expression type
25- /// and `String` is the `test_method`
26- TraitMethod ( hir:: Type , String ) ,
24+ /// For 'test_enum.test_method()', `ty` is the `test_enum` expression type
25+ /// and `name` is the `test_method`
26+ TraitMethod ( TraitImportCandidate ) ,
27+ }
28+
29+ #[ derive( Debug ) ]
30+ pub ( crate ) struct TraitImportCandidate {
31+ pub ty : hir:: Type ,
32+ pub name : String ,
33+ }
34+
35+ #[ derive( Debug ) ]
36+ pub ( crate ) struct PathImportCandidate {
37+ pub name : String ,
2738}
2839
2940#[ derive( Debug ) ]
@@ -74,10 +85,10 @@ impl ImportAssets {
7485
7586 fn get_search_query ( & self ) -> & str {
7687 match & self . import_candidate {
77- ImportCandidate :: UnqualifiedName ( name ) => name ,
78- ImportCandidate :: QualifierStart ( qualifier_start ) => qualifier_start ,
79- ImportCandidate :: TraitAssocItem ( _ , trait_assoc_item_name ) => trait_assoc_item_name ,
80- ImportCandidate :: TraitMethod ( _ , trait_method_name ) => trait_method_name ,
88+ ImportCandidate :: UnqualifiedName ( candidate )
89+ | ImportCandidate :: QualifierStart ( candidate ) => & candidate . name ,
90+ ImportCandidate :: TraitAssocItem ( candidate )
91+ | ImportCandidate :: TraitMethod ( candidate ) => & candidate . name ,
8192 }
8293 }
8394
@@ -106,27 +117,29 @@ impl ImportAssets {
106117 prefixed : Option < hir:: PrefixKind > ,
107118 ) -> BTreeSet < hir:: ModPath > {
108119 let db = sema. db ;
120+ let mut trait_candidates = FxHashSet :: default ( ) ;
109121 let current_crate = self . module_with_name_to_import . krate ( ) ;
110- imports_locator:: find_imports ( sema, current_crate, & self . get_search_query ( ) )
111- . into_iter ( )
112- . filter_map ( |candidate| match & self . import_candidate {
113- ImportCandidate :: TraitAssocItem ( assoc_item_type, _) => {
122+
123+ let filter = |candidate : Either < hir:: ModuleDef , hir:: MacroDef > | {
124+ trait_candidates. clear ( ) ;
125+ match & self . import_candidate {
126+ ImportCandidate :: TraitAssocItem ( trait_candidate) => {
114127 let located_assoc_item = match candidate {
115- Either :: Left ( ModuleDef :: Function ( located_function) ) => located_function
116- . as_assoc_item ( db)
117- . map ( |assoc| assoc. container ( db) )
118- . and_then ( Self :: assoc_to_trait) ,
119- Either :: Left ( ModuleDef :: Const ( located_const) ) => located_const
120- . as_assoc_item ( db)
121- . map ( |assoc| assoc. container ( db) )
122- . and_then ( Self :: assoc_to_trait) ,
128+ Either :: Left ( ModuleDef :: Function ( located_function) ) => {
129+ located_function. as_assoc_item ( db)
130+ }
131+ Either :: Left ( ModuleDef :: Const ( located_const) ) => {
132+ located_const. as_assoc_item ( db)
133+ }
123134 _ => None ,
124- } ?;
135+ }
136+ . map ( |assoc| assoc. container ( db) )
137+ . and_then ( Self :: assoc_to_trait) ?;
125138
126- let mut trait_candidates = FxHashSet :: default ( ) ;
127139 trait_candidates. insert ( located_assoc_item. into ( ) ) ;
128140
129- assoc_item_type
141+ trait_candidate
142+ . ty
130143 . iterate_path_candidates (
131144 db,
132145 current_crate,
@@ -137,7 +150,7 @@ impl ImportAssets {
137150 . map ( ModuleDef :: from)
138151 . map ( Either :: Left )
139152 }
140- ImportCandidate :: TraitMethod ( function_callee , _ ) => {
153+ ImportCandidate :: TraitMethod ( trait_candidate ) => {
141154 let located_assoc_item =
142155 if let Either :: Left ( ModuleDef :: Function ( located_function) ) = candidate {
143156 located_function
@@ -148,10 +161,10 @@ impl ImportAssets {
148161 None
149162 } ?;
150163
151- let mut trait_candidates = FxHashSet :: default ( ) ;
152164 trait_candidates. insert ( located_assoc_item. into ( ) ) ;
153165
154- function_callee
166+ trait_candidate
167+ . ty
155168 . iterate_method_candidates (
156169 db,
157170 current_crate,
@@ -165,12 +178,14 @@ impl ImportAssets {
165178 . map ( Either :: Left )
166179 }
167180 _ => Some ( candidate) ,
168- } )
181+ }
182+ } ;
183+
184+ imports_locator:: find_imports ( sema, current_crate, & self . get_search_query ( ) )
185+ . into_iter ( )
186+ . filter_map ( filter)
169187 . filter_map ( |candidate| {
170- let item: hir:: ItemInNs = match candidate {
171- Either :: Left ( module_def) => module_def. into ( ) ,
172- Either :: Right ( macro_def) => macro_def. into ( ) ,
173- } ;
188+ let item: hir:: ItemInNs = candidate. either ( Into :: into, Into :: into) ;
174189 if let Some ( prefix_kind) = prefixed {
175190 self . module_with_name_to_import . find_use_path_prefixed ( db, item, prefix_kind)
176191 } else {
@@ -196,13 +211,13 @@ impl ImportCandidate {
196211 sema : & Semantics < RootDatabase > ,
197212 method_call : & ast:: MethodCallExpr ,
198213 ) -> Option < Self > {
199- if sema. resolve_method_call ( method_call) . is_some ( ) {
200- return None ;
214+ match sema. resolve_method_call ( method_call) {
215+ Some ( _) => None ,
216+ None => Some ( Self :: TraitMethod ( TraitImportCandidate {
217+ ty : sema. type_of_expr ( & method_call. receiver ( ) ?) ?,
218+ name : method_call. name_ref ( ) ?. syntax ( ) . to_string ( ) ,
219+ } ) ) ,
201220 }
202- Some ( Self :: TraitMethod (
203- sema. type_of_expr ( & method_call. receiver ( ) ?) ?,
204- method_call. name_ref ( ) ?. syntax ( ) . to_string ( ) ,
205- ) )
206221 }
207222
208223 fn for_regular_path (
@@ -214,7 +229,7 @@ impl ImportCandidate {
214229 }
215230
216231 let segment = path_under_caret. segment ( ) ?;
217- if let Some ( qualifier) = path_under_caret. qualifier ( ) {
232+ let candidate = if let Some ( qualifier) = path_under_caret. qualifier ( ) {
218233 let qualifier_start = qualifier. syntax ( ) . descendants ( ) . find_map ( ast:: NameRef :: cast) ?;
219234 let qualifier_start_path =
220235 qualifier_start. syntax ( ) . ancestors ( ) . find_map ( ast:: Path :: cast) ?;
@@ -224,23 +239,30 @@ impl ImportCandidate {
224239 } else {
225240 sema. resolve_path ( & qualifier) ?
226241 } ;
227- if let hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( assoc_item_path) ) =
228- qualifier_resolution
229- {
230- Some ( ImportCandidate :: TraitAssocItem (
231- assoc_item_path. ty ( sema. db ) ,
232- segment. syntax ( ) . to_string ( ) ,
233- ) )
234- } else {
235- None
242+ match qualifier_resolution {
243+ hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( assoc_item_path) ) => {
244+ ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
245+ ty : assoc_item_path. ty ( sema. db ) ,
246+ name : segment. syntax ( ) . to_string ( ) ,
247+ } )
248+ }
249+ _ => return None ,
236250 }
237251 } else {
238- Some ( ImportCandidate :: QualifierStart ( qualifier_start. syntax ( ) . to_string ( ) ) )
252+ ImportCandidate :: QualifierStart ( PathImportCandidate {
253+ name : qualifier_start. syntax ( ) . to_string ( ) ,
254+ } )
239255 }
240256 } else {
241- Some ( ImportCandidate :: UnqualifiedName (
242- segment. syntax ( ) . descendants ( ) . find_map ( ast:: NameRef :: cast) ?. syntax ( ) . to_string ( ) ,
243- ) )
244- }
257+ ImportCandidate :: UnqualifiedName ( PathImportCandidate {
258+ name : segment
259+ . syntax ( )
260+ . descendants ( )
261+ . find_map ( ast:: NameRef :: cast) ?
262+ . syntax ( )
263+ . to_string ( ) ,
264+ } )
265+ } ;
266+ Some ( candidate)
245267 }
246268}
0 commit comments