2
2
use either:: Either ;
3
3
use hir:: {
4
4
AsAssocItem , AssocItem , AssocItemContainer , Crate , ItemInNs , MacroDef , ModPath , Module ,
5
- ModuleDef , PathResolution , PrefixKind , Semantics , Type ,
5
+ ModuleDef , PathResolution , PrefixKind , ScopeDef , Semantics , SemanticsScope , Type ,
6
6
} ;
7
7
use rustc_hash:: FxHashSet ;
8
8
use syntax:: { ast, AstNode } ;
@@ -62,33 +62,38 @@ impl NameToImport {
62
62
}
63
63
64
64
#[ derive( Debug ) ]
65
- pub struct ImportAssets {
65
+ pub struct ImportAssets < ' a > {
66
66
import_candidate : ImportCandidate ,
67
67
module_with_candidate : Module ,
68
+ scope : SemanticsScope < ' a > ,
68
69
}
69
70
70
- impl ImportAssets {
71
+ impl < ' a > ImportAssets < ' a > {
71
72
pub fn for_method_call (
72
73
method_call : & ast:: MethodCallExpr ,
73
- sema : & Semantics < RootDatabase > ,
74
+ sema : & ' a Semantics < RootDatabase > ,
74
75
) -> Option < Self > {
76
+ let scope = sema. scope ( method_call. syntax ( ) ) ;
75
77
Some ( Self {
76
78
import_candidate : ImportCandidate :: for_method_call ( sema, method_call) ?,
77
- module_with_candidate : sema. scope ( method_call. syntax ( ) ) . module ( ) ?,
79
+ module_with_candidate : scope. module ( ) ?,
80
+ scope,
78
81
} )
79
82
}
80
83
81
84
pub fn for_exact_path (
82
85
fully_qualified_path : & ast:: Path ,
83
- sema : & Semantics < RootDatabase > ,
86
+ sema : & ' a Semantics < RootDatabase > ,
84
87
) -> Option < Self > {
85
88
let syntax_under_caret = fully_qualified_path. syntax ( ) ;
86
89
if syntax_under_caret. ancestors ( ) . find_map ( ast:: Use :: cast) . is_some ( ) {
87
90
return None ;
88
91
}
92
+ let scope = sema. scope ( syntax_under_caret) ;
89
93
Some ( Self {
90
94
import_candidate : ImportCandidate :: for_regular_path ( sema, fully_qualified_path) ?,
91
- module_with_candidate : sema. scope ( syntax_under_caret) . module ( ) ?,
95
+ module_with_candidate : scope. module ( ) ?,
96
+ scope,
92
97
} )
93
98
}
94
99
@@ -97,24 +102,28 @@ impl ImportAssets {
97
102
qualifier : Option < ast:: Path > ,
98
103
fuzzy_name : String ,
99
104
sema : & Semantics < RootDatabase > ,
105
+ scope : SemanticsScope < ' a > ,
100
106
) -> Option < Self > {
101
107
Some ( Self {
102
108
import_candidate : ImportCandidate :: for_fuzzy_path ( qualifier, fuzzy_name, sema) ?,
103
109
module_with_candidate,
110
+ scope,
104
111
} )
105
112
}
106
113
107
114
pub fn for_fuzzy_method_call (
108
115
module_with_method_call : Module ,
109
116
receiver_ty : Type ,
110
117
fuzzy_method_name : String ,
118
+ scope : SemanticsScope < ' a > ,
111
119
) -> Option < Self > {
112
120
Some ( Self {
113
121
import_candidate : ImportCandidate :: TraitMethod ( TraitImportCandidate {
114
122
receiver_ty,
115
123
name : NameToImport :: Fuzzy ( fuzzy_method_name) ,
116
124
} ) ,
117
125
module_with_candidate : module_with_method_call,
126
+ scope,
118
127
} )
119
128
}
120
129
}
@@ -155,7 +164,7 @@ impl LocatedImport {
155
164
}
156
165
}
157
166
158
- impl ImportAssets {
167
+ impl < ' a > ImportAssets < ' a > {
159
168
pub fn import_candidate ( & self ) -> & ImportCandidate {
160
169
& self . import_candidate
161
170
}
@@ -189,6 +198,7 @@ impl ImportAssets {
189
198
prefixed : Option < PrefixKind > ,
190
199
) -> Vec < LocatedImport > {
191
200
let current_crate = self . module_with_candidate . krate ( ) ;
201
+ let scope_definitions = self . scope_definitions ( ) ;
192
202
193
203
let imports_for_candidate_name = match self . name_to_import ( ) {
194
204
NameToImport :: Exact ( exact_name) => {
@@ -219,9 +229,25 @@ impl ImportAssets {
219
229
self . applicable_defs ( sema. db , prefixed, imports_for_candidate_name)
220
230
. into_iter ( )
221
231
. filter ( |import| import. import_path ( ) . len ( ) > 1 )
232
+ . filter ( |import| {
233
+ let proposed_def = match import. item_to_import ( ) {
234
+ ItemInNs :: Types ( id) => ScopeDef :: ModuleDef ( id. into ( ) ) ,
235
+ ItemInNs :: Values ( id) => ScopeDef :: ModuleDef ( id. into ( ) ) ,
236
+ ItemInNs :: Macros ( id) => ScopeDef :: MacroDef ( id. into ( ) ) ,
237
+ } ;
238
+ !scope_definitions. contains ( & proposed_def)
239
+ } )
222
240
. collect ( )
223
241
}
224
242
243
+ fn scope_definitions ( & self ) -> FxHashSet < ScopeDef > {
244
+ let mut scope_definitions = FxHashSet :: default ( ) ;
245
+ self . scope . process_all_names ( & mut |_, scope_def| {
246
+ scope_definitions. insert ( scope_def) ;
247
+ } ) ;
248
+ scope_definitions
249
+ }
250
+
225
251
fn applicable_defs (
226
252
& self ,
227
253
db : & RootDatabase ,
@@ -297,7 +323,6 @@ fn path_applicable_imports(
297
323
Qualifier :: FirstSegmentUnresolved ( first_segment, qualifier) => ( first_segment, qualifier) ,
298
324
} ;
299
325
300
- // TODO kb zz.syntax().ast_node() <- two options are now proposed despite the trait being imported
301
326
let unresolved_qualifier_string = unresolved_qualifier. to_string ( ) ;
302
327
let unresolved_first_segment_string = unresolved_first_segment. to_string ( ) ;
303
328
0 commit comments