@@ -6,7 +6,7 @@ use hir::{Documentation, HasAttrs};
6
6
use ide_db:: { imports:: insert_use:: ImportScope , ty_filter:: TryEnum , SnippetCap } ;
7
7
use syntax:: {
8
8
ast:: { self , make, AstNode , AstToken } ,
9
- SyntaxKind :: { EXPR_STMT , STMT_LIST } ,
9
+ SyntaxKind :: { BLOCK_EXPR , EXPR_STMT , FOR_EXPR , IF_EXPR , LOOP_EXPR , STMT_LIST , WHILE_EXPR } ,
10
10
TextRange , TextSize ,
11
11
} ;
12
12
use text_edit:: TextEdit ;
@@ -123,6 +123,22 @@ pub(crate) fn complete_postfix(
123
123
postfix_snippet ( "ref" , "&expr" , & format ! ( "&{receiver_text}" ) ) . add_to ( acc) ;
124
124
postfix_snippet ( "refm" , "&mut expr" , & format ! ( "&mut {receiver_text}" ) ) . add_to ( acc) ;
125
125
126
+ let mut unsafe_should_be_wrapped = true ;
127
+ if dot_receiver. syntax ( ) . kind ( ) == BLOCK_EXPR {
128
+ unsafe_should_be_wrapped = false ;
129
+ if let Some ( parent) = dot_receiver. syntax ( ) . parent ( ) {
130
+ if matches ! ( parent. kind( ) , IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR ) {
131
+ unsafe_should_be_wrapped = true ;
132
+ }
133
+ }
134
+ } ;
135
+ let unsafe_completion_string = if unsafe_should_be_wrapped {
136
+ format ! ( "unsafe {{ {receiver_text} }}" )
137
+ } else {
138
+ format ! ( "unsafe {receiver_text}" )
139
+ } ;
140
+ postfix_snippet ( "unsafe" , "unsafe {}" , & unsafe_completion_string) . add_to ( acc) ;
141
+
126
142
// The rest of the postfix completions create an expression that moves an argument,
127
143
// so it's better to consider references now to avoid breaking the compilation
128
144
@@ -329,18 +345,19 @@ fn main() {
329
345
}
330
346
"# ,
331
347
expect ! [ [ r#"
332
- sn box Box::new(expr)
333
- sn call function(expr)
334
- sn dbg dbg!(expr)
335
- sn dbgr dbg!(&expr)
336
- sn if if expr {}
337
- sn let let
338
- sn letm let mut
339
- sn match match expr {}
340
- sn not !expr
341
- sn ref &expr
342
- sn refm &mut expr
343
- sn while while expr {}
348
+ sn box Box::new(expr)
349
+ sn call function(expr)
350
+ sn dbg dbg!(expr)
351
+ sn dbgr dbg!(&expr)
352
+ sn if if expr {}
353
+ sn let let
354
+ sn letm let mut
355
+ sn match match expr {}
356
+ sn not !expr
357
+ sn ref &expr
358
+ sn refm &mut expr
359
+ sn unsafe unsafe {}
360
+ sn while while expr {}
344
361
"# ] ] ,
345
362
) ;
346
363
}
@@ -359,16 +376,17 @@ fn main() {
359
376
}
360
377
"# ,
361
378
expect ! [ [ r#"
362
- sn box Box::new(expr)
363
- sn call function(expr)
364
- sn dbg dbg!(expr)
365
- sn dbgr dbg!(&expr)
366
- sn if if expr {}
367
- sn match match expr {}
368
- sn not !expr
369
- sn ref &expr
370
- sn refm &mut expr
371
- sn while while expr {}
379
+ sn box Box::new(expr)
380
+ sn call function(expr)
381
+ sn dbg dbg!(expr)
382
+ sn dbgr dbg!(&expr)
383
+ sn if if expr {}
384
+ sn match match expr {}
385
+ sn not !expr
386
+ sn ref &expr
387
+ sn refm &mut expr
388
+ sn unsafe unsafe {}
389
+ sn while while expr {}
372
390
"# ] ] ,
373
391
) ;
374
392
}
@@ -383,15 +401,16 @@ fn main() {
383
401
}
384
402
"# ,
385
403
expect ! [ [ r#"
386
- sn box Box::new(expr)
387
- sn call function(expr)
388
- sn dbg dbg!(expr)
389
- sn dbgr dbg!(&expr)
390
- sn let let
391
- sn letm let mut
392
- sn match match expr {}
393
- sn ref &expr
394
- sn refm &mut expr
404
+ sn box Box::new(expr)
405
+ sn call function(expr)
406
+ sn dbg dbg!(expr)
407
+ sn dbgr dbg!(&expr)
408
+ sn let let
409
+ sn letm let mut
410
+ sn match match expr {}
411
+ sn ref &expr
412
+ sn refm &mut expr
413
+ sn unsafe unsafe {}
395
414
"# ] ] ,
396
415
)
397
416
}
@@ -406,18 +425,19 @@ fn main() {
406
425
}
407
426
"# ,
408
427
expect ! [ [ r#"
409
- sn box Box::new(expr)
410
- sn call function(expr)
411
- sn dbg dbg!(expr)
412
- sn dbgr dbg!(&expr)
413
- sn if if expr {}
414
- sn let let
415
- sn letm let mut
416
- sn match match expr {}
417
- sn not !expr
418
- sn ref &expr
419
- sn refm &mut expr
420
- sn while while expr {}
428
+ sn box Box::new(expr)
429
+ sn call function(expr)
430
+ sn dbg dbg!(expr)
431
+ sn dbgr dbg!(&expr)
432
+ sn if if expr {}
433
+ sn let let
434
+ sn letm let mut
435
+ sn match match expr {}
436
+ sn not !expr
437
+ sn ref &expr
438
+ sn refm &mut expr
439
+ sn unsafe unsafe {}
440
+ sn while while expr {}
421
441
"# ] ] ,
422
442
) ;
423
443
}
@@ -517,6 +537,49 @@ fn main() {
517
537
)
518
538
}
519
539
540
+ #[ test]
541
+ fn postfix_completion_for_unsafe ( ) {
542
+ check_edit ( "unsafe" , r#"fn main() { foo.$0 }"# , r#"fn main() { unsafe { foo } }"# ) ;
543
+ check_edit ( "unsafe" , r#"fn main() { { foo }.$0 }"# , r#"fn main() { unsafe { foo } }"# ) ;
544
+ check_edit (
545
+ "unsafe" ,
546
+ r#"fn main() { if x { foo }.$0 }"# ,
547
+ r#"fn main() { unsafe { if x { foo } } }"# ,
548
+ ) ;
549
+ check_edit (
550
+ "unsafe" ,
551
+ r#"fn main() { loop { foo }.$0 }"# ,
552
+ r#"fn main() { unsafe { loop { foo } } }"# ,
553
+ ) ;
554
+ check_edit (
555
+ "unsafe" ,
556
+ r#"fn main() { if true {}.$0 }"# ,
557
+ r#"fn main() { unsafe { if true {} } }"# ,
558
+ ) ;
559
+ check_edit (
560
+ "unsafe" ,
561
+ r#"fn main() { while true {}.$0 }"# ,
562
+ r#"fn main() { unsafe { while true {} } }"# ,
563
+ ) ;
564
+ check_edit (
565
+ "unsafe" ,
566
+ r#"fn main() { for i in 0..10 {}.$0 }"# ,
567
+ r#"fn main() { unsafe { for i in 0..10 {} } }"# ,
568
+ ) ;
569
+ check_edit (
570
+ "unsafe" ,
571
+ r#"fn main() { let x = if true {1} else {2}.$0 }"# ,
572
+ r#"fn main() { let x = unsafe { if true {1} else {2} } }"# ,
573
+ ) ;
574
+
575
+ // completion will not be triggered
576
+ check_edit (
577
+ "unsafe" ,
578
+ r#"fn main() { let x = true else {panic!()}.$0}"# ,
579
+ r#"fn main() { let x = true else {panic!()}.unsafe}"# ,
580
+ ) ;
581
+ }
582
+
520
583
#[ test]
521
584
fn custom_postfix_completion ( ) {
522
585
let config = CompletionConfig {
0 commit comments