@@ -31,7 +31,7 @@ pub struct TraitImportCandidate {
31
31
32
32
#[ derive( Debug ) ]
33
33
pub struct PathImportCandidate {
34
- pub qualifier : Option < ast:: Path > ,
34
+ pub unresolved_qualifier : Option < ast:: Path > ,
35
35
pub name : NameToImport ,
36
36
}
37
37
@@ -82,38 +82,14 @@ impl ImportAssets {
82
82
}
83
83
84
84
pub fn for_fuzzy_path (
85
- module_with_path : Module ,
85
+ module_with_candidate : Module ,
86
86
qualifier : Option < ast:: Path > ,
87
87
fuzzy_name : String ,
88
88
sema : & Semantics < RootDatabase > ,
89
89
) -> Option < Self > {
90
- Some ( match qualifier {
91
- Some ( qualifier) => {
92
- let qualifier_resolution = sema. resolve_path ( & qualifier) ?;
93
- match qualifier_resolution {
94
- hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( assoc_item_path) ) => Self {
95
- import_candidate : ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
96
- receiver_ty : assoc_item_path. ty ( sema. db ) ,
97
- name : NameToImport :: Fuzzy ( fuzzy_name) ,
98
- } ) ,
99
- module_with_candidate : module_with_path,
100
- } ,
101
- _ => Self {
102
- import_candidate : ImportCandidate :: Path ( PathImportCandidate {
103
- qualifier : Some ( qualifier) ,
104
- name : NameToImport :: Fuzzy ( fuzzy_name) ,
105
- } ) ,
106
- module_with_candidate : module_with_path,
107
- } ,
108
- }
109
- }
110
- None => Self {
111
- import_candidate : ImportCandidate :: Path ( PathImportCandidate {
112
- qualifier : None ,
113
- name : NameToImport :: Fuzzy ( fuzzy_name) ,
114
- } ) ,
115
- module_with_candidate : module_with_path,
116
- } ,
90
+ Some ( Self {
91
+ import_candidate : ImportCandidate :: for_fuzzy_path ( qualifier, fuzzy_name, sema) ?,
92
+ module_with_candidate,
117
93
} )
118
94
}
119
95
@@ -169,8 +145,9 @@ impl ImportAssets {
169
145
prefixed : Option < hir:: PrefixKind > ,
170
146
) -> Vec < ( hir:: ModPath , hir:: ItemInNs ) > {
171
147
let current_crate = self . module_with_candidate . krate ( ) ;
148
+ let import_candidate = & self . import_candidate ;
172
149
173
- let unfiltered_imports = match self . name_to_import ( ) {
150
+ let imports_for_candidate_name = match self . name_to_import ( ) {
174
151
NameToImport :: Exact ( exact_name) => {
175
152
imports_locator:: find_exact_imports ( sema, current_crate, exact_name. clone ( ) )
176
153
}
@@ -180,11 +157,10 @@ impl ImportAssets {
180
157
// and https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Blanket.20trait.20impls.20lookup
181
158
// for the details
182
159
NameToImport :: Fuzzy ( fuzzy_name) => {
183
- let ( assoc_item_search, limit) = match self . import_candidate {
184
- ImportCandidate :: TraitAssocItem ( _) | ImportCandidate :: TraitMethod ( _) => {
185
- ( AssocItemSearch :: AssocItemsOnly , None )
186
- }
187
- _ => ( AssocItemSearch :: Exclude , Some ( DEFAULT_QUERY_SEARCH_LIMIT ) ) ,
160
+ let ( assoc_item_search, limit) = if import_candidate. is_trait_candidate ( ) {
161
+ ( AssocItemSearch :: AssocItemsOnly , None )
162
+ } else {
163
+ ( AssocItemSearch :: Exclude , Some ( DEFAULT_QUERY_SEARCH_LIMIT ) )
188
164
} ;
189
165
imports_locator:: find_similar_imports (
190
166
sema,
@@ -198,33 +174,32 @@ impl ImportAssets {
198
174
199
175
let db = sema. db ;
200
176
let mut res =
201
- applicable_defs ( self . import_candidate ( ) , current_crate, db, unfiltered_imports )
177
+ applicable_defs ( import_candidate, current_crate, db, imports_for_candidate_name )
202
178
. filter_map ( |candidate| {
203
179
let item: hir:: ItemInNs = candidate. clone ( ) . either ( Into :: into, Into :: into) ;
204
180
205
- let item_to_search = match self . import_candidate {
206
- ImportCandidate :: TraitAssocItem ( _) | ImportCandidate :: TraitMethod ( _) => {
207
- let canidate_trait = match candidate {
208
- Either :: Left ( module_def) => {
209
- module_def. as_assoc_item ( db) ?. containing_trait ( db)
210
- }
211
- _ => None ,
212
- } ?;
213
- ModuleDef :: from ( canidate_trait) . into ( )
214
- }
215
- _ => item,
181
+ let item_to_search = if import_candidate. is_trait_candidate ( ) {
182
+ let canidate_trait = match candidate {
183
+ Either :: Left ( module_def) => {
184
+ module_def. as_assoc_item ( db) ?. containing_trait ( db)
185
+ }
186
+ _ => None ,
187
+ } ?;
188
+ ModuleDef :: from ( canidate_trait) . into ( )
189
+ } else {
190
+ item
216
191
} ;
217
-
218
- if let Some ( prefix_kind) = prefixed {
192
+ let mod_path = if let Some ( prefix_kind) = prefixed {
219
193
self . module_with_candidate . find_use_path_prefixed (
220
194
db,
221
195
item_to_search,
222
196
prefix_kind,
223
197
)
224
198
} else {
225
199
self . module_with_candidate . find_use_path ( db, item_to_search)
226
- }
227
- . map ( |path| ( path, item) )
200
+ } ;
201
+
202
+ mod_path. zip ( Some ( item) )
228
203
} )
229
204
. filter ( |( use_path, _) | use_path. len ( ) > 1 )
230
205
. collect :: < Vec < _ > > ( ) ;
@@ -239,6 +214,7 @@ fn applicable_defs<'a>(
239
214
db : & RootDatabase ,
240
215
unfiltered_imports : Box < dyn Iterator < Item = Either < ModuleDef , MacroDef > > + ' a > ,
241
216
) -> Box < dyn Iterator < Item = Either < ModuleDef , MacroDef > > + ' a > {
217
+ // TODO kb this needs to consider various path prefixes, etc.
242
218
let receiver_ty = match import_candidate {
243
219
ImportCandidate :: Path ( _) => return unfiltered_imports,
244
220
ImportCandidate :: TraitAssocItem ( candidate) | ImportCandidate :: TraitMethod ( candidate) => {
@@ -325,41 +301,45 @@ impl ImportCandidate {
325
301
if sema. resolve_path ( path) . is_some ( ) {
326
302
return None ;
327
303
}
304
+ path_import_candidate (
305
+ sema,
306
+ path. qualifier ( ) ,
307
+ NameToImport :: Exact ( path. segment ( ) ?. name_ref ( ) ?. to_string ( ) ) ,
308
+ )
309
+ }
328
310
329
- let segment = path. segment ( ) ?;
330
- let candidate = if let Some ( qualifier) = path. qualifier ( ) {
331
- let qualifier_start = qualifier. syntax ( ) . descendants ( ) . find_map ( ast:: NameRef :: cast) ?;
332
- let qualifier_start_path =
333
- qualifier_start. syntax ( ) . ancestors ( ) . find_map ( ast:: Path :: cast) ?;
334
- if let Some ( qualifier_start_resolution) = sema. resolve_path ( & qualifier_start_path) {
335
- let qualifier_resolution = if qualifier_start_path == qualifier {
336
- qualifier_start_resolution
337
- } else {
338
- sema. resolve_path ( & qualifier) ?
339
- } ;
340
- match qualifier_resolution {
341
- hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( assoc_item_path) ) => {
342
- ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
343
- receiver_ty : assoc_item_path. ty ( sema. db ) ,
344
- name : NameToImport :: Exact ( segment. name_ref ( ) ?. to_string ( ) ) ,
345
- } )
346
- }
347
- _ => return None ,
348
- }
349
- } else {
350
- ImportCandidate :: Path ( PathImportCandidate {
351
- qualifier : Some ( qualifier) ,
352
- name : NameToImport :: Exact ( qualifier_start. to_string ( ) ) ,
311
+ fn for_fuzzy_path (
312
+ qualifier : Option < ast:: Path > ,
313
+ fuzzy_name : String ,
314
+ sema : & Semantics < RootDatabase > ,
315
+ ) -> Option < Self > {
316
+ path_import_candidate ( sema, qualifier, NameToImport :: Fuzzy ( fuzzy_name) )
317
+ }
318
+
319
+ fn is_trait_candidate ( & self ) -> bool {
320
+ matches ! ( self , ImportCandidate :: TraitAssocItem ( _) | ImportCandidate :: TraitMethod ( _) )
321
+ }
322
+ }
323
+
324
+ fn path_import_candidate (
325
+ sema : & Semantics < RootDatabase > ,
326
+ qualifier : Option < ast:: Path > ,
327
+ name : NameToImport ,
328
+ ) -> Option < ImportCandidate > {
329
+ Some ( match qualifier {
330
+ Some ( qualifier) => match sema. resolve_path ( & qualifier) {
331
+ None => ImportCandidate :: Path ( PathImportCandidate {
332
+ unresolved_qualifier : Some ( qualifier) ,
333
+ name,
334
+ } ) ,
335
+ Some ( hir:: PathResolution :: Def ( hir:: ModuleDef :: Adt ( assoc_item_path) ) ) => {
336
+ ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
337
+ receiver_ty : assoc_item_path. ty ( sema. db ) ,
338
+ name,
353
339
} )
354
340
}
355
- } else {
356
- ImportCandidate :: Path ( PathImportCandidate {
357
- qualifier : None ,
358
- name : NameToImport :: Exact (
359
- segment. syntax ( ) . descendants ( ) . find_map ( ast:: NameRef :: cast) ?. to_string ( ) ,
360
- ) ,
361
- } )
362
- } ;
363
- Some ( candidate)
364
- }
341
+ Some ( _) => return None ,
342
+ } ,
343
+ None => ImportCandidate :: Path ( PathImportCandidate { unresolved_qualifier : None , name } ) ,
344
+ } )
365
345
}
0 commit comments