@@ -227,6 +227,11 @@ fn edit_tuple_usage(
227
227
228
228
// no index access -> make invalid -> requires handling by user
229
229
// -> put usage in block comment
230
+ //
231
+ // Note: For macro invocations this might result in still valid code:
232
+ // When a macro accepts the tuple as argument, as well as no arguments at all,
233
+ // uncommenting the tuple still leaves the macro call working (see `tests::in_macro_call::empty_macro`).
234
+ // But this is an unlikely case. Usually the resulting macro call will become erroneous.
230
235
builder. insert ( usage. range . start ( ) , "/*" ) ;
231
236
builder. insert ( usage. range . end ( ) , "*/" ) ;
232
237
}
@@ -322,89 +327,91 @@ fn handle_ref_field_usage(ctx: &AssistContext, field_expr: &FieldExpr) -> RefDat
322
327
let mut ref_data =
323
328
RefData { range : s. text_range ( ) , needs_deref : true , needs_parentheses : true } ;
324
329
325
- let parent = match s. parent ( ) {
326
- Some ( parent) => parent,
330
+ let parent = match s. parent ( ) . map ( ast:: Expr :: cast) {
331
+ Some ( Some ( parent) ) => parent,
332
+ Some ( None ) => {
333
+ ref_data. needs_parentheses = false ;
334
+ return ref_data;
335
+ }
327
336
None => return ref_data,
328
337
} ;
329
338
330
- match_ast ! {
331
- match parent {
332
- ast:: ParenExpr ( it) => {
333
- // already parens in place -> don't replace
334
- ref_data. needs_parentheses = false ;
335
- // there might be a ref outside: `&(t.0)` -> can be removed
336
- if let Some ( it) = it. syntax( ) . parent( ) . and_then( ast:: RefExpr :: cast) {
337
- ref_data. needs_deref = false ;
338
- ref_data. range = it. syntax( ) . text_range( ) ;
339
- }
340
- } ,
341
- ast:: RefExpr ( it) => {
342
- // `&*` -> cancel each other out
339
+ match parent {
340
+ ast:: Expr :: ParenExpr ( it) => {
341
+ // already parens in place -> don't replace
342
+ ref_data. needs_parentheses = false ;
343
+ // there might be a ref outside: `&(t.0)` -> can be removed
344
+ if let Some ( it) = it. syntax ( ) . parent ( ) . and_then ( ast:: RefExpr :: cast) {
343
345
ref_data. needs_deref = false ;
344
- ref_data. needs_parentheses = false ;
345
- // might be surrounded by parens -> can be removed too
346
- match it. syntax( ) . parent( ) . and_then( ast:: ParenExpr :: cast) {
347
- Some ( parent) => ref_data. range = parent. syntax( ) . text_range( ) ,
348
- None => ref_data. range = it. syntax( ) . text_range( ) ,
349
- } ;
350
- } ,
351
- // higher precedence than deref `*`
352
- // https://doc.rust-lang.org/reference/expressions.html#expression-precedence
353
- // -> requires parentheses
354
- ast:: PathExpr ( _it) => { } ,
355
- ast:: MethodCallExpr ( it) => {
356
- // `field_expr` is `self_param` (otherwise it would be in `ArgList`)
346
+ ref_data. range = it. syntax ( ) . text_range ( ) ;
347
+ }
348
+ }
349
+ ast:: Expr :: RefExpr ( it) => {
350
+ // `&*` -> cancel each other out
351
+ ref_data. needs_deref = false ;
352
+ ref_data. needs_parentheses = false ;
353
+ // might be surrounded by parens -> can be removed too
354
+ match it. syntax ( ) . parent ( ) . and_then ( ast:: ParenExpr :: cast) {
355
+ Some ( parent) => ref_data. range = parent. syntax ( ) . text_range ( ) ,
356
+ None => ref_data. range = it. syntax ( ) . text_range ( ) ,
357
+ } ;
358
+ }
359
+ // higher precedence than deref `*`
360
+ // https://doc.rust-lang.org/reference/expressions.html#expression-precedence
361
+ // -> requires parentheses
362
+ ast:: Expr :: PathExpr ( _it) => { }
363
+ ast:: Expr :: MethodCallExpr ( it) => {
364
+ // `field_expr` is `self_param` (otherwise it would be in `ArgList`)
365
+
366
+ // test if there's already auto-ref in place (`value` -> `&value`)
367
+ // -> no method accepting `self`, but `&self` -> no need for deref
368
+ //
369
+ // other combinations (`&value` -> `value`, `&&value` -> `&value`, `&value` -> `&&value`) might or might not be able to auto-ref/deref,
370
+ // but there might be trait implementations an added `&` might resolve to
371
+ // -> ONLY handle auto-ref from `value` to `&value`
372
+ fn is_auto_ref ( ctx : & AssistContext , call_expr : & MethodCallExpr ) -> bool {
373
+ fn impl_ ( ctx : & AssistContext , call_expr : & MethodCallExpr ) -> Option < bool > {
374
+ let rec = call_expr. receiver ( ) ?;
375
+ let rec_ty = ctx. sema . type_of_expr ( & rec) ?. adjusted ( ) ;
376
+ // input must be actual value
377
+ if rec_ty. is_reference ( ) {
378
+ return Some ( false ) ;
379
+ }
357
380
358
- // test if there's already auto-ref in place (`value` -> `&value`)
359
- // -> no method accepting `self`, but `&self` -> no need for deref
360
- //
361
- // other combinations (`&value` -> `value`, `&&value` -> `&value`, `&value` -> `&&value`) might or might not be able to auto-ref/deref,
362
- // but there might be trait implementations an added `&` might resolve to
363
- // -> ONLY handle auto-ref from `value` to `&value`
364
- fn is_auto_ref( ctx: & AssistContext , call_expr: & MethodCallExpr ) -> bool {
365
- fn impl_( ctx: & AssistContext , call_expr: & MethodCallExpr ) -> Option <bool > {
366
- let rec = call_expr. receiver( ) ?;
367
- let rec_ty = ctx. sema. type_of_expr( & rec) ?. adjusted( ) ;
368
- // input must be actual value
369
- if rec_ty. is_reference( ) {
370
- return Some ( false ) ;
371
- }
372
-
373
- // doesn't resolve trait impl
374
- let f = ctx. sema. resolve_method_call( call_expr) ?;
375
- let self_param = f. self_param( ctx. db( ) ) ?;
376
- // self must be ref
377
- match self_param. access( ctx. db( ) ) {
378
- hir:: Access :: Shared | hir:: Access :: Exclusive => Some ( true ) ,
379
- hir:: Access :: Owned => Some ( false ) ,
380
- }
381
+ // doesn't resolve trait impl
382
+ let f = ctx. sema . resolve_method_call ( call_expr) ?;
383
+ let self_param = f. self_param ( ctx. db ( ) ) ?;
384
+ // self must be ref
385
+ match self_param. access ( ctx. db ( ) ) {
386
+ hir:: Access :: Shared | hir:: Access :: Exclusive => Some ( true ) ,
387
+ hir:: Access :: Owned => Some ( false ) ,
381
388
}
382
- impl_( ctx, call_expr) . unwrap_or( false )
383
389
}
390
+ impl_ ( ctx, call_expr) . unwrap_or ( false )
391
+ }
384
392
385
- if is_auto_ref( ctx, & it) {
386
- ref_data. needs_deref = false ;
387
- ref_data. needs_parentheses = false ;
388
- }
389
- } ,
390
- ast:: FieldExpr ( _it) => {
391
- // `t.0.my_field`
392
- ref_data. needs_deref = false ;
393
- ref_data. needs_parentheses = false ;
394
- } ,
395
- ast:: IndexExpr ( _it) => {
396
- // `t.0[1]`
393
+ if is_auto_ref ( ctx, & it) {
397
394
ref_data. needs_deref = false ;
398
395
ref_data. needs_parentheses = false ;
399
- } ,
400
- ast:: TryExpr ( _it) => {
401
- // `t.0?`
402
- // requires deref and parens: `(*_0)`
403
- } ,
404
- // lower precedence than deref `*` -> no parens
405
- _ => {
406
- ref_data. needs_parentheses = false ;
407
- } ,
396
+ }
397
+ }
398
+ ast:: Expr :: FieldExpr ( _it) => {
399
+ // `t.0.my_field`
400
+ ref_data. needs_deref = false ;
401
+ ref_data. needs_parentheses = false ;
402
+ }
403
+ ast:: Expr :: IndexExpr ( _it) => {
404
+ // `t.0[1]`
405
+ ref_data. needs_deref = false ;
406
+ ref_data. needs_parentheses = false ;
407
+ }
408
+ ast:: Expr :: TryExpr ( _it) => {
409
+ // `t.0?`
410
+ // requires deref and parens: `(*_0)`
411
+ }
412
+ // lower precedence than deref `*` -> no parens
413
+ _ => {
414
+ ref_data. needs_parentheses = false ;
408
415
}
409
416
} ;
410
417
0 commit comments