@@ -12,18 +12,29 @@ use crate::assist_config::InsertUseConfig;
12
12
#[ derive( Debug ) ]
13
13
pub ( crate ) enum ImportCandidate {
14
14
/// Simple name like 'HashMap'
15
- UnqualifiedName ( String ) ,
15
+ UnqualifiedName ( PathImportCandidate ) ,
16
16
/// First part of the qualified name.
17
17
/// For 'std::collections::HashMap', that will be 'std'.
18
- QualifierStart ( String ) ,
18
+ QualifierStart ( PathImportCandidate ) ,
19
19
/// 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 ) ,
23
23
/// 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 ,
27
38
}
28
39
29
40
#[ derive( Debug ) ]
@@ -74,10 +85,10 @@ impl ImportAssets {
74
85
75
86
fn get_search_query ( & self ) -> & str {
76
87
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 ,
81
92
}
82
93
}
83
94
@@ -106,27 +117,29 @@ impl ImportAssets {
106
117
prefixed : Option < hir:: PrefixKind > ,
107
118
) -> BTreeSet < hir:: ModPath > {
108
119
let db = sema. db ;
120
+ let mut trait_candidates = FxHashSet :: default ( ) ;
109
121
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) => {
114
127
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
+ }
123
134
_ => None ,
124
- } ?;
135
+ }
136
+ . map ( |assoc| assoc. container ( db) )
137
+ . and_then ( Self :: assoc_to_trait) ?;
125
138
126
- let mut trait_candidates = FxHashSet :: default ( ) ;
127
139
trait_candidates. insert ( located_assoc_item. into ( ) ) ;
128
140
129
- assoc_item_type
141
+ trait_candidate
142
+ . ty
130
143
. iterate_path_candidates (
131
144
db,
132
145
current_crate,
@@ -137,7 +150,7 @@ impl ImportAssets {
137
150
. map ( ModuleDef :: from)
138
151
. map ( Either :: Left )
139
152
}
140
- ImportCandidate :: TraitMethod ( function_callee , _ ) => {
153
+ ImportCandidate :: TraitMethod ( trait_candidate ) => {
141
154
let located_assoc_item =
142
155
if let Either :: Left ( ModuleDef :: Function ( located_function) ) = candidate {
143
156
located_function
@@ -148,10 +161,10 @@ impl ImportAssets {
148
161
None
149
162
} ?;
150
163
151
- let mut trait_candidates = FxHashSet :: default ( ) ;
152
164
trait_candidates. insert ( located_assoc_item. into ( ) ) ;
153
165
154
- function_callee
166
+ trait_candidate
167
+ . ty
155
168
. iterate_method_candidates (
156
169
db,
157
170
current_crate,
@@ -165,12 +178,14 @@ impl ImportAssets {
165
178
. map ( Either :: Left )
166
179
}
167
180
_ => 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)
169
187
. 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) ;
174
189
if let Some ( prefix_kind) = prefixed {
175
190
self . module_with_name_to_import . find_use_path_prefixed ( db, item, prefix_kind)
176
191
} else {
@@ -196,13 +211,13 @@ impl ImportCandidate {
196
211
sema : & Semantics < RootDatabase > ,
197
212
method_call : & ast:: MethodCallExpr ,
198
213
) -> 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
+ } ) ) ,
201
220
}
202
- Some ( Self :: TraitMethod (
203
- sema. type_of_expr ( & method_call. receiver ( ) ?) ?,
204
- method_call. name_ref ( ) ?. syntax ( ) . to_string ( ) ,
205
- ) )
206
221
}
207
222
208
223
fn for_regular_path (
@@ -214,7 +229,7 @@ impl ImportCandidate {
214
229
}
215
230
216
231
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 ( ) {
218
233
let qualifier_start = qualifier. syntax ( ) . descendants ( ) . find_map ( ast:: NameRef :: cast) ?;
219
234
let qualifier_start_path =
220
235
qualifier_start. syntax ( ) . ancestors ( ) . find_map ( ast:: Path :: cast) ?;
@@ -224,23 +239,30 @@ impl ImportCandidate {
224
239
} else {
225
240
sema. resolve_path ( & qualifier) ?
226
241
} ;
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 ,
236
250
}
237
251
} else {
238
- Some ( ImportCandidate :: QualifierStart ( qualifier_start. syntax ( ) . to_string ( ) ) )
252
+ ImportCandidate :: QualifierStart ( PathImportCandidate {
253
+ name : qualifier_start. syntax ( ) . to_string ( ) ,
254
+ } )
239
255
}
240
256
} 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)
245
267
}
246
268
}
0 commit comments