1
1
//! Look up accessible paths for items.
2
2
use either:: Either ;
3
3
use hir:: {
4
- AsAssocItem , AssocItem , Crate , ItemInNs , MacroDef , ModPath , Module , ModuleDef , Name ,
5
- PrefixKind , Semantics ,
4
+ AsAssocItem , AssocItem , AssocItemContainer , Crate , ItemInNs , MacroDef , ModPath , Module ,
5
+ ModuleDef , PathResolution , PrefixKind , Semantics , Type ,
6
6
} ;
7
7
use rustc_hash:: FxHashSet ;
8
8
use syntax:: { ast, AstNode } ;
@@ -12,6 +12,8 @@ use crate::{
12
12
RootDatabase ,
13
13
} ;
14
14
15
+ use super :: item_name;
16
+
15
17
#[ derive( Debug ) ]
16
18
pub enum ImportCandidate {
17
19
// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
@@ -28,7 +30,7 @@ pub enum ImportCandidate {
28
30
29
31
#[ derive( Debug ) ]
30
32
pub struct TraitImportCandidate {
31
- pub receiver_ty : hir :: Type ,
33
+ pub receiver_ty : Type ,
32
34
pub name : NameToImport ,
33
35
}
34
36
@@ -62,7 +64,7 @@ impl NameToImport {
62
64
#[ derive( Debug ) ]
63
65
pub struct ImportAssets {
64
66
import_candidate : ImportCandidate ,
65
- module_with_candidate : hir :: Module ,
67
+ module_with_candidate : Module ,
66
68
}
67
69
68
70
impl ImportAssets {
@@ -104,7 +106,7 @@ impl ImportAssets {
104
106
105
107
pub fn for_fuzzy_method_call (
106
108
module_with_method_call : Module ,
107
- receiver_ty : hir :: Type ,
109
+ receiver_ty : Type ,
108
110
fuzzy_method_name : String ,
109
111
) -> Option < Self > {
110
112
Some ( Self {
@@ -184,7 +186,7 @@ impl ImportAssets {
184
186
fn search_for (
185
187
& self ,
186
188
sema : & Semantics < RootDatabase > ,
187
- prefixed : Option < hir :: PrefixKind > ,
189
+ prefixed : Option < PrefixKind > ,
188
190
) -> Vec < LocatedImport > {
189
191
let current_crate = self . module_with_candidate . krate ( ) ;
190
192
@@ -223,7 +225,7 @@ impl ImportAssets {
223
225
fn applicable_defs (
224
226
& self ,
225
227
db : & RootDatabase ,
226
- prefixed : Option < hir :: PrefixKind > ,
228
+ prefixed : Option < PrefixKind > ,
227
229
unfiltered_defs : impl Iterator < Item = Either < ModuleDef , MacroDef > > ,
228
230
) -> FxHashSet < LocatedImport > {
229
231
let current_crate = self . module_with_candidate . krate ( ) ;
@@ -266,10 +268,10 @@ fn path_applicable_imports(
266
268
let ( assoc_original, candidate) = match def {
267
269
Either :: Left ( module_def) => match module_def. as_assoc_item ( db) {
268
270
Some ( assoc_item) => match assoc_item. container ( db) {
269
- hir :: AssocItemContainer :: Trait ( trait_) => {
271
+ AssocItemContainer :: Trait ( trait_) => {
270
272
( Some ( module_def) , ItemInNs :: from ( ModuleDef :: from ( trait_) ) )
271
273
}
272
- hir :: AssocItemContainer :: Impl ( impl_) => (
274
+ AssocItemContainer :: Impl ( impl_) => (
273
275
Some ( module_def) ,
274
276
ItemInNs :: from ( ModuleDef :: from ( impl_. target_ty ( db) . as_adt ( ) ?) ) ,
275
277
) ,
@@ -296,6 +298,7 @@ fn path_applicable_imports(
296
298
} ;
297
299
298
300
// TODO kb need to remove turbofish from the qualifier, maybe use the segments instead?
301
+ // TODO kb sorting is changed now, return back?
299
302
let unresolved_qualifier_string = unresolved_qualifier. to_string ( ) ;
300
303
let unresolved_first_segment_string = unresolved_first_segment. to_string ( ) ;
301
304
@@ -305,38 +308,35 @@ fn path_applicable_imports(
305
308
candidate_path_string. contains ( & unresolved_qualifier_string)
306
309
&& candidate_path_string. contains ( & unresolved_first_segment_string)
307
310
} )
308
- // TODO kb need to adjust the return type: I get the results rendered rather badly
309
311
. filter_map ( |( candidate_path, ( assoc_original, candidate) ) | {
310
- if let Some ( assoc_original) = assoc_original {
311
- if item_name ( db, candidate) ?. to_string ( ) == unresolved_first_segment_string {
312
- return Some ( LocatedImport :: new (
313
- candidate_path. clone ( ) ,
314
- ItemInNs :: from ( assoc_original) ,
315
- Some ( ( candidate_path, candidate) ) ,
316
- ) ) ;
317
- }
318
- }
312
+ let found_segment_resolution = item_name ( db, candidate)
313
+ . map ( |name| name. to_string ( ) == unresolved_first_segment_string)
314
+ . unwrap_or ( false ) ;
315
+ let ( import_path, item_to_import) = if found_segment_resolution {
316
+ ( candidate_path. clone ( ) , candidate)
317
+ } else {
318
+ let matching_module =
319
+ module_with_matching_name ( db, & unresolved_first_segment_string, candidate) ?;
320
+ let module_item = ItemInNs :: from ( ModuleDef :: from ( matching_module) ) ;
321
+ ( import_path_locator ( module_item) ?, module_item)
322
+ } ;
319
323
320
- let matching_module =
321
- module_with_matching_name ( db, & unresolved_first_segment_string, candidate) ?;
322
- let item = ItemInNs :: from ( ModuleDef :: from ( matching_module) ) ;
323
- Some ( LocatedImport :: new (
324
- import_path_locator ( item) ?,
325
- item,
326
- Some ( ( candidate_path, candidate) ) ,
327
- ) )
324
+ Some ( match assoc_original {
325
+ Some ( assoc_original) => LocatedImport :: new (
326
+ import_path. clone ( ) ,
327
+ item_to_import,
328
+ Some ( ( import_path, ItemInNs :: from ( assoc_original) ) ) ,
329
+ ) ,
330
+ None => LocatedImport :: new (
331
+ import_path,
332
+ item_to_import,
333
+ if found_segment_resolution { None } else { Some ( ( candidate_path, candidate) ) } ,
334
+ ) ,
335
+ } )
328
336
} )
329
337
. collect ( )
330
338
}
331
339
332
- fn item_name ( db : & RootDatabase , item : ItemInNs ) -> Option < Name > {
333
- match item {
334
- ItemInNs :: Types ( module_def_id) => ModuleDef :: from ( module_def_id) . name ( db) ,
335
- ItemInNs :: Values ( module_def_id) => ModuleDef :: from ( module_def_id) . name ( db) ,
336
- ItemInNs :: Macros ( macro_def_id) => MacroDef :: from ( macro_def_id) . name ( db) ,
337
- }
338
- }
339
-
340
340
fn item_module ( db : & RootDatabase , item : ItemInNs ) -> Option < Module > {
341
341
match item {
342
342
ItemInNs :: Types ( module_def_id) => ModuleDef :: from ( module_def_id) . module ( db) ,
@@ -404,10 +404,20 @@ fn trait_applicable_items(
404
404
}
405
405
406
406
let item = ItemInNs :: from ( ModuleDef :: from ( assoc. containing_trait ( db) ?) ) ;
407
+ let item_path = import_path_locator ( item) ?;
408
+
409
+ let assoc_item = assoc_to_item ( assoc) ;
410
+ let assoc_item_path = match assoc. container ( db) {
411
+ AssocItemContainer :: Trait ( _) => item_path. clone ( ) ,
412
+ AssocItemContainer :: Impl ( impl_) => import_path_locator ( ItemInNs :: from (
413
+ ModuleDef :: from ( impl_. target_ty ( db) . as_adt ( ) ?) ,
414
+ ) ) ?,
415
+ } ;
416
+
407
417
located_imports. insert ( LocatedImport :: new (
408
- import_path_locator ( item ) ? ,
418
+ item_path ,
409
419
item,
410
- None ,
420
+ Some ( ( assoc_item_path , assoc_item ) ) ,
411
421
) ) ;
412
422
}
413
423
None :: < ( ) >
@@ -423,10 +433,20 @@ fn trait_applicable_items(
423
433
let assoc = function. as_assoc_item ( db) ?;
424
434
if required_assoc_items. contains ( & assoc) {
425
435
let item = ItemInNs :: from ( ModuleDef :: from ( assoc. containing_trait ( db) ?) ) ;
436
+ let item_path = import_path_locator ( item) ?;
437
+
438
+ let assoc_item = assoc_to_item ( assoc) ;
439
+ let assoc_item_path = match assoc. container ( db) {
440
+ AssocItemContainer :: Trait ( _) => item_path. clone ( ) ,
441
+ AssocItemContainer :: Impl ( impl_) => import_path_locator ( ItemInNs :: from (
442
+ ModuleDef :: from ( impl_. target_ty ( db) . as_adt ( ) ?) ,
443
+ ) ) ?,
444
+ } ;
445
+
426
446
located_imports. insert ( LocatedImport :: new (
427
- import_path_locator ( item ) ? ,
447
+ item_path ,
428
448
item,
429
- None ,
449
+ Some ( ( assoc_item_path , assoc_item ) ) ,
430
450
) ) ;
431
451
}
432
452
None :: < ( ) >
@@ -437,11 +457,19 @@ fn trait_applicable_items(
437
457
located_imports
438
458
}
439
459
460
+ fn assoc_to_item ( assoc : AssocItem ) -> ItemInNs {
461
+ match assoc {
462
+ AssocItem :: Function ( f) => ItemInNs :: from ( ModuleDef :: from ( f) ) ,
463
+ AssocItem :: Const ( c) => ItemInNs :: from ( ModuleDef :: from ( c) ) ,
464
+ AssocItem :: TypeAlias ( t) => ItemInNs :: from ( ModuleDef :: from ( t) ) ,
465
+ }
466
+ }
467
+
440
468
fn get_mod_path (
441
469
db : & RootDatabase ,
442
470
item_to_search : ItemInNs ,
443
471
module_with_candidate : & Module ,
444
- prefixed : Option < hir :: PrefixKind > ,
472
+ prefixed : Option < PrefixKind > ,
445
473
) -> Option < ModPath > {
446
474
if let Some ( prefix_kind) = prefixed {
447
475
module_with_candidate. find_use_path_prefixed ( db, item_to_search, prefix_kind)
@@ -509,7 +537,7 @@ fn path_import_candidate(
509
537
return None ;
510
538
}
511
539
}
512
- Some ( hir :: PathResolution :: Def ( hir :: ModuleDef :: Adt ( assoc_item_path) ) ) => {
540
+ Some ( PathResolution :: Def ( ModuleDef :: Adt ( assoc_item_path) ) ) => {
513
541
ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
514
542
receiver_ty : assoc_item_path. ty ( sema. db ) ,
515
543
name,
0 commit comments