1
1
//! Look up accessible paths for items.
2
2
use hir:: {
3
3
AsAssocItem , AssocItem , AssocItemContainer , Crate , ItemInNs , MacroDef , ModPath , Module ,
4
- ModuleDef , Name , PathResolution , PrefixKind , ScopeDef , Semantics , Type ,
4
+ ModuleDef , PathResolution , PrefixKind , ScopeDef , Semantics , Type ,
5
5
} ;
6
6
use itertools:: Itertools ;
7
7
use rustc_hash:: FxHashSet ;
@@ -14,11 +14,16 @@ use crate::{
14
14
15
15
use super :: item_name;
16
16
17
+ /// A candidate for import, derived during various IDE activities:
18
+ /// * completion with imports on the fly proposals
19
+ /// * completion edit resolve requests
20
+ /// * assists
21
+ /// * etc.
17
22
#[ derive( Debug ) ]
18
23
pub enum ImportCandidate {
19
- // A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
24
+ /// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
20
25
Path ( PathImportCandidate ) ,
21
- /// A trait associated function (with no self parameter) or associated constant.
26
+ /// A trait associated function (with no self parameter) or an associated constant.
22
27
/// For 'test_mod::TestEnum::test_function', `ty` is the `test_mod::TestEnum` expression type
23
28
/// and `name` is the `test_function`
24
29
TraitAssocItem ( TraitImportCandidate ) ,
@@ -28,27 +33,40 @@ pub enum ImportCandidate {
28
33
TraitMethod ( TraitImportCandidate ) ,
29
34
}
30
35
36
+ /// A trait import needed for a given associated item access.
37
+ /// For `some::path::SomeStruct::ASSOC_`, contains the
38
+ /// type of `some::path::SomeStruct` and `ASSOC_` as the item name.
31
39
#[ derive( Debug ) ]
32
40
pub struct TraitImportCandidate {
41
+ /// A type of the item that has the associated item accessed at.
33
42
pub receiver_ty : Type ,
34
- pub name : NameToImport ,
43
+ /// The associated item name that the trait to import should contain.
44
+ pub assoc_item_name : NameToImport ,
35
45
}
36
46
47
+ /// Path import for a given name, qualified or not.
37
48
#[ derive( Debug ) ]
38
49
pub struct PathImportCandidate {
39
- pub qualifier : Qualifier ,
50
+ /// Optional qualifier before name.
51
+ pub qualifier : Option < FirstSegmentUnresolved > ,
52
+ /// The name the item (struct, trait, enum, etc.) should have.
40
53
pub name : NameToImport ,
41
54
}
42
55
56
+ /// A qualifier that has a first segment and it's unresolved.
43
57
#[ derive( Debug ) ]
44
- pub enum Qualifier {
45
- Absent ,
46
- FirstSegmentUnresolved ( ast :: NameRef , ModPath ) ,
58
+ pub struct FirstSegmentUnresolved {
59
+ fist_segment : ast :: NameRef ,
60
+ full_qualifier : ModPath ,
47
61
}
48
62
63
+ /// A name that will be used during item lookups.
49
64
#[ derive( Debug ) ]
50
65
pub enum NameToImport {
66
+ /// Requires items with names that exactly match the given string, case-sensitive.
51
67
Exact ( String ) ,
68
+ /// Requires items with names that case-insensitively contain all letters from the string,
69
+ /// in the same order, but not necessary adjacent.
52
70
Fuzzy ( String ) ,
53
71
}
54
72
@@ -61,6 +79,7 @@ impl NameToImport {
61
79
}
62
80
}
63
81
82
+ /// A struct to find imports in the project, given a certain name (or its part) and the context.
64
83
#[ derive( Debug ) ]
65
84
pub struct ImportAssets {
66
85
import_candidate : ImportCandidate ,
@@ -119,19 +138,30 @@ impl ImportAssets {
119
138
Some ( Self {
120
139
import_candidate : ImportCandidate :: TraitMethod ( TraitImportCandidate {
121
140
receiver_ty,
122
- name : NameToImport :: Fuzzy ( fuzzy_method_name) ,
141
+ assoc_item_name : NameToImport :: Fuzzy ( fuzzy_method_name) ,
123
142
} ) ,
124
143
module_with_candidate : module_with_method_call,
125
144
candidate_node,
126
145
} )
127
146
}
128
147
}
129
148
149
+ /// An import (not necessary the only one) that corresponds a certain given [`PathImportCandidate`].
150
+ /// (the structure is not entirely correct, since there can be situations requiring two imports, see FIXME below for the details)
130
151
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
131
152
pub struct LocatedImport {
153
+ /// The path to use in the `use` statement for a given candidate to be imported.
132
154
pub import_path : ModPath ,
155
+ /// An item that will be imported with the import path given.
133
156
pub item_to_import : ItemInNs ,
157
+ /// The path import candidate, resolved.
158
+ ///
159
+ /// Not necessary matches the import:
160
+ /// For any associated constant from the trait, we try to access as `some::path::SomeStruct::ASSOC_`
161
+ /// the original item is the associated constant, but the import has to be a trait that
162
+ /// defines this constant.
134
163
pub original_item : ItemInNs ,
164
+ /// A path of the original item.
135
165
pub original_path : Option < ModPath > ,
136
166
}
137
167
@@ -144,15 +174,6 @@ impl LocatedImport {
144
174
) -> Self {
145
175
Self { import_path, item_to_import, original_item, original_path }
146
176
}
147
-
148
- pub fn original_item_name ( & self , db : & RootDatabase ) -> Option < Name > {
149
- match self . original_item {
150
- ItemInNs :: Types ( module_def_id) | ItemInNs :: Values ( module_def_id) => {
151
- ModuleDef :: from ( module_def_id) . name ( db)
152
- }
153
- ItemInNs :: Macros ( macro_def_id) => MacroDef :: from ( macro_def_id) . name ( db) ,
154
- }
155
- }
156
177
}
157
178
158
179
impl ImportAssets {
@@ -229,7 +250,7 @@ impl ImportAssets {
229
250
match & self . import_candidate {
230
251
ImportCandidate :: Path ( candidate) => & candidate. name ,
231
252
ImportCandidate :: TraitAssocItem ( candidate)
232
- | ImportCandidate :: TraitMethod ( candidate) => & candidate. name ,
253
+ | ImportCandidate :: TraitMethod ( candidate) => & candidate. assoc_item_name ,
233
254
}
234
255
}
235
256
@@ -279,17 +300,18 @@ fn path_applicable_imports(
279
300
let _p = profile:: span ( "import_assets::path_applicable_imports" ) ;
280
301
281
302
let ( unresolved_first_segment, unresolved_qualifier) = match & path_candidate. qualifier {
282
- Qualifier :: Absent => {
303
+ None => {
283
304
return items_with_candidate_name
284
305
. into_iter ( )
285
306
. filter_map ( |item| {
286
307
Some ( LocatedImport :: new ( mod_path ( item) ?, item, item, mod_path ( item) ) )
287
308
} )
288
309
. collect ( ) ;
289
310
}
290
- Qualifier :: FirstSegmentUnresolved ( first_segment, qualifier) => {
291
- ( first_segment. to_string ( ) , qualifier. to_string ( ) )
292
- }
311
+ Some ( first_segment_unresolved) => (
312
+ first_segment_unresolved. fist_segment . to_string ( ) ,
313
+ first_segment_unresolved. full_qualifier . to_string ( ) ,
314
+ ) ,
293
315
} ;
294
316
295
317
items_with_candidate_name
@@ -516,7 +538,7 @@ impl ImportCandidate {
516
538
Some ( _) => None ,
517
539
None => Some ( Self :: TraitMethod ( TraitImportCandidate {
518
540
receiver_ty : sema. type_of_expr ( & method_call. receiver ( ) ?) ?,
519
- name : NameToImport :: Exact ( method_call. name_ref ( ) ?. to_string ( ) ) ,
541
+ assoc_item_name : NameToImport :: Exact ( method_call. name_ref ( ) ?. to_string ( ) ) ,
520
542
} ) ) ,
521
543
}
522
544
}
@@ -559,10 +581,10 @@ fn path_import_candidate(
559
581
qualifier_start. syntax ( ) . ancestors ( ) . find_map ( ast:: Path :: cast) ?;
560
582
if sema. resolve_path ( & qualifier_start_path) . is_none ( ) {
561
583
ImportCandidate :: Path ( PathImportCandidate {
562
- qualifier : Qualifier :: FirstSegmentUnresolved (
563
- qualifier_start,
564
- ModPath :: from_src_unhygienic ( qualifier) ?,
565
- ) ,
584
+ qualifier : Some ( FirstSegmentUnresolved {
585
+ fist_segment : qualifier_start,
586
+ full_qualifier : ModPath :: from_src_unhygienic ( qualifier) ?,
587
+ } ) ,
566
588
name,
567
589
} )
568
590
} else {
@@ -572,12 +594,12 @@ fn path_import_candidate(
572
594
Some ( PathResolution :: Def ( ModuleDef :: Adt ( assoc_item_path) ) ) => {
573
595
ImportCandidate :: TraitAssocItem ( TraitImportCandidate {
574
596
receiver_ty : assoc_item_path. ty ( sema. db ) ,
575
- name,
597
+ assoc_item_name : name,
576
598
} )
577
599
}
578
600
Some ( _) => return None ,
579
601
} ,
580
- None => ImportCandidate :: Path ( PathImportCandidate { qualifier : Qualifier :: Absent , name } ) ,
602
+ None => ImportCandidate :: Path ( PathImportCandidate { qualifier : None , name } ) ,
581
603
} )
582
604
}
583
605
0 commit comments