@@ -162,11 +162,52 @@ impl<'a> CompletionContext<'a> {
162
162
}
163
163
164
164
/// Calculate the expected type and name of the cursor position.
165
- fn expected_type_and_name ( & self ) -> ( Option < Type > , Option < NameOrNameRef > ) {
165
+ fn expected_type_and_name (
166
+ & self ,
167
+ name_like : & ast:: NameLike ,
168
+ ) -> ( Option < Type > , Option < NameOrNameRef > ) {
166
169
let mut node = match self . token . parent ( ) {
167
170
Some ( it) => it,
168
171
None => return ( None , None ) ,
169
172
} ;
173
+
174
+ let strip_refs = |mut ty : Type | match name_like {
175
+ ast:: NameLike :: NameRef ( n) => {
176
+ let p = match n. syntax ( ) . parent ( ) {
177
+ Some ( it) => it,
178
+ None => return ty,
179
+ } ;
180
+ let top_syn = match_ast ! {
181
+ match p {
182
+ ast:: FieldExpr ( e) => e
183
+ . syntax( )
184
+ . ancestors( )
185
+ . map_while( ast:: FieldExpr :: cast)
186
+ . last( )
187
+ . map( |it| it. syntax( ) . clone( ) ) ,
188
+ ast:: PathSegment ( e) => e
189
+ . syntax( )
190
+ . ancestors( )
191
+ . skip( 1 )
192
+ . take_while( |it| ast:: Path :: can_cast( it. kind( ) ) || ast:: PathExpr :: can_cast( it. kind( ) ) )
193
+ . find_map( ast:: PathExpr :: cast)
194
+ . map( |it| it. syntax( ) . clone( ) ) ,
195
+ _ => None
196
+ }
197
+ } ;
198
+ let top_syn = match top_syn {
199
+ Some ( it) => it,
200
+ None => return ty,
201
+ } ;
202
+ for _ in top_syn. ancestors ( ) . skip ( 1 ) . map_while ( ast:: RefExpr :: cast) {
203
+ cov_mark:: hit!( expected_type_fn_param_ref) ;
204
+ ty = ty. strip_reference ( ) ;
205
+ }
206
+ ty
207
+ }
208
+ _ => ty,
209
+ } ;
210
+
170
211
loop {
171
212
break match_ast ! {
172
213
match node {
@@ -199,13 +240,9 @@ impl<'a> CompletionContext<'a> {
199
240
self . token. clone( ) ,
200
241
) . map( |ap| {
201
242
let name = ap. ident( ) . map( NameOrNameRef :: Name ) ;
202
- let ty = if has_ref( & self . token) {
203
- cov_mark:: hit!( expected_type_fn_param_ref) ;
204
- ap. ty. remove_ref( )
205
- } else {
206
- Some ( ap. ty)
207
- } ;
208
- ( ty, name)
243
+
244
+ let ty = strip_refs( ap. ty) ;
245
+ ( Some ( ty) , name)
209
246
} )
210
247
. unwrap_or( ( None , None ) )
211
248
} ,
@@ -330,8 +367,6 @@ impl<'a> CompletionContext<'a> {
330
367
return None ;
331
368
}
332
369
333
- ( self . expected_type , self . expected_name ) = self . expected_type_and_name ( ) ;
334
-
335
370
// Overwrite the path kind for derives
336
371
if let Some ( ( original_file, file_with_fake_ident, offset, origin_attr) ) = derive_ctx {
337
372
if let Some ( ast:: NameLike :: NameRef ( name_ref) ) =
@@ -389,6 +424,7 @@ impl<'a> CompletionContext<'a> {
389
424
return Some ( analysis) ;
390
425
}
391
426
} ;
427
+ ( self . expected_type , self . expected_name ) = self . expected_type_and_name ( & name_like) ;
392
428
let analysis = match name_like {
393
429
ast:: NameLike :: Lifetime ( lifetime) => CompletionAnalysis :: Lifetime (
394
430
Self :: classify_lifetime ( & self . sema , original_file, lifetime) ?,
@@ -1141,19 +1177,6 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
1141
1177
Some ( ( use_tree. path ( ) ?, true ) )
1142
1178
}
1143
1179
1144
- fn has_ref ( token : & SyntaxToken ) -> bool {
1145
- let mut token = token. clone ( ) ;
1146
- for skip in [ SyntaxKind :: IDENT , SyntaxKind :: WHITESPACE , T ! [ mut ] ] {
1147
- if token. kind ( ) == skip {
1148
- token = match token. prev_token ( ) {
1149
- Some ( it) => it,
1150
- None => return false ,
1151
- }
1152
- }
1153
- }
1154
- token. kind ( ) == T ! [ & ]
1155
- }
1156
-
1157
1180
pub ( crate ) fn is_in_token_of_for_loop ( element : SyntaxElement ) -> bool {
1158
1181
// oh my ...
1159
1182
( || {
0 commit comments