about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-08 09:44:22 +0000
committerbors <bors@rust-lang.org>2023-02-08 09:44:22 +0000
commit6effb2606269c25d95fa77eba863fe594e3cca23 (patch)
tree3a6e512c3b70394affff53ce5364b05446bdb3a5
parenta05ce5a3e75fe642826e9e244aecaf599e95ed92 (diff)
parent2666e6eda8220af036973881a35bdc2d85d6d8a2 (diff)
downloadrust-6effb2606269c25d95fa77eba863fe594e3cca23.tar.gz
rust-6effb2606269c25d95fa77eba863fe594e3cca23.zip
Auto merge of #14095 - dqkqd:master, r=Veykril
Add postfix completion for `unsafe`.

Fix #13779.

Hi, this is my first PR. Please tell me if there is anything I should do.
-rw-r--r--crates/ide-completion/src/completions/keyword.rs3
-rw-r--r--crates/ide-completion/src/completions/postfix.rs151
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-completion/src/tests/proc_macros.rs84
4 files changed, 156 insertions, 84 deletions
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 1d03c8cc5ca..b9ab2afca2b 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -86,6 +86,7 @@ fn foo(a: A) { a.$0 }
                 sn match                  match expr {}
                 sn ref                    &expr
                 sn refm                   &mut expr
+                sn unsafe                 unsafe {}
             "#]],
         );
 
@@ -110,6 +111,7 @@ fn foo() {
                 sn match                  match expr {}
                 sn ref                    &expr
                 sn refm                   &mut expr
+                sn unsafe                 unsafe {}
             "#]],
         );
     }
@@ -136,6 +138,7 @@ fn foo(a: A) { a.$0 }
                 sn match                  match expr {}
                 sn ref                    &expr
                 sn refm                   &mut expr
+                sn unsafe                 unsafe {}
             "#]],
         );
     }
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index f4f37d77d81..90c523735da 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -6,7 +6,7 @@ use hir::{Documentation, HasAttrs};
 use ide_db::{imports::insert_use::ImportScope, ty_filter::TryEnum, SnippetCap};
 use syntax::{
     ast::{self, make, AstNode, AstToken},
-    SyntaxKind::{EXPR_STMT, STMT_LIST},
+    SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR},
     TextRange, TextSize,
 };
 use text_edit::TextEdit;
@@ -123,6 +123,22 @@ pub(crate) fn complete_postfix(
     postfix_snippet("ref", "&expr", &format!("&{receiver_text}")).add_to(acc);
     postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc);
 
+    let mut unsafe_should_be_wrapped = true;
+    if dot_receiver.syntax().kind() == BLOCK_EXPR {
+        unsafe_should_be_wrapped = false;
+        if let Some(parent) = dot_receiver.syntax().parent() {
+            if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) {
+                unsafe_should_be_wrapped = true;
+            }
+        }
+    };
+    let unsafe_completion_string = if unsafe_should_be_wrapped {
+        format!("unsafe {{ {receiver_text} }}")
+    } else {
+        format!("unsafe {receiver_text}")
+    };
+    postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc);
+
     // The rest of the postfix completions create an expression that moves an argument,
     // so it's better to consider references now to avoid breaking the compilation
 
@@ -329,18 +345,19 @@ fn main() {
 }
 "#,
             expect![[r#"
-                sn box   Box::new(expr)
-                sn call  function(expr)
-                sn dbg   dbg!(expr)
-                sn dbgr  dbg!(&expr)
-                sn if    if expr {}
-                sn let   let
-                sn letm  let mut
-                sn match match expr {}
-                sn not   !expr
-                sn ref   &expr
-                sn refm  &mut expr
-                sn while while expr {}
+                sn box    Box::new(expr)
+                sn call   function(expr)
+                sn dbg    dbg!(expr)
+                sn dbgr   dbg!(&expr)
+                sn if     if expr {}
+                sn let    let
+                sn letm   let mut
+                sn match  match expr {}
+                sn not    !expr
+                sn ref    &expr
+                sn refm   &mut expr
+                sn unsafe unsafe {}
+                sn while  while expr {}
             "#]],
         );
     }
@@ -359,16 +376,17 @@ fn main() {
 }
 "#,
             expect![[r#"
-                sn box   Box::new(expr)
-                sn call  function(expr)
-                sn dbg   dbg!(expr)
-                sn dbgr  dbg!(&expr)
-                sn if    if expr {}
-                sn match match expr {}
-                sn not   !expr
-                sn ref   &expr
-                sn refm  &mut expr
-                sn while while expr {}
+                sn box    Box::new(expr)
+                sn call   function(expr)
+                sn dbg    dbg!(expr)
+                sn dbgr   dbg!(&expr)
+                sn if     if expr {}
+                sn match  match expr {}
+                sn not    !expr
+                sn ref    &expr
+                sn refm   &mut expr
+                sn unsafe unsafe {}
+                sn while  while expr {}
             "#]],
         );
     }
@@ -383,15 +401,16 @@ fn main() {
 }
 "#,
             expect![[r#"
-                sn box   Box::new(expr)
-                sn call  function(expr)
-                sn dbg   dbg!(expr)
-                sn dbgr  dbg!(&expr)
-                sn let   let
-                sn letm  let mut
-                sn match match expr {}
-                sn ref   &expr
-                sn refm  &mut expr
+                sn box    Box::new(expr)
+                sn call   function(expr)
+                sn dbg    dbg!(expr)
+                sn dbgr   dbg!(&expr)
+                sn let    let
+                sn letm   let mut
+                sn match  match expr {}
+                sn ref    &expr
+                sn refm   &mut expr
+                sn unsafe unsafe {}
             "#]],
         )
     }
@@ -406,18 +425,19 @@ fn main() {
 }
 "#,
             expect![[r#"
-                sn box   Box::new(expr)
-                sn call  function(expr)
-                sn dbg   dbg!(expr)
-                sn dbgr  dbg!(&expr)
-                sn if    if expr {}
-                sn let   let
-                sn letm  let mut
-                sn match match expr {}
-                sn not   !expr
-                sn ref   &expr
-                sn refm  &mut expr
-                sn while while expr {}
+                sn box    Box::new(expr)
+                sn call   function(expr)
+                sn dbg    dbg!(expr)
+                sn dbgr   dbg!(&expr)
+                sn if     if expr {}
+                sn let    let
+                sn letm   let mut
+                sn match  match expr {}
+                sn not    !expr
+                sn ref    &expr
+                sn refm   &mut expr
+                sn unsafe unsafe {}
+                sn while  while expr {}
             "#]],
         );
     }
@@ -518,6 +538,49 @@ fn main() {
     }
 
     #[test]
+    fn postfix_completion_for_unsafe() {
+        check_edit("unsafe", r#"fn main() { foo.$0 }"#, r#"fn main() { unsafe { foo } }"#);
+        check_edit("unsafe", r#"fn main() { { foo }.$0 }"#, r#"fn main() { unsafe { foo } }"#);
+        check_edit(
+            "unsafe",
+            r#"fn main() { if x { foo }.$0 }"#,
+            r#"fn main() { unsafe { if x { foo } } }"#,
+        );
+        check_edit(
+            "unsafe",
+            r#"fn main() { loop { foo }.$0 }"#,
+            r#"fn main() { unsafe { loop { foo } } }"#,
+        );
+        check_edit(
+            "unsafe",
+            r#"fn main() { if true {}.$0 }"#,
+            r#"fn main() { unsafe { if true {} } }"#,
+        );
+        check_edit(
+            "unsafe",
+            r#"fn main() { while true {}.$0 }"#,
+            r#"fn main() { unsafe { while true {} } }"#,
+        );
+        check_edit(
+            "unsafe",
+            r#"fn main() { for i in 0..10 {}.$0 }"#,
+            r#"fn main() { unsafe { for i in 0..10 {} } }"#,
+        );
+        check_edit(
+            "unsafe",
+            r#"fn main() { let x = if true {1} else {2}.$0 }"#,
+            r#"fn main() { let x = unsafe { if true {1} else {2} } }"#,
+        );
+
+        // completion will not be triggered
+        check_edit(
+            "unsafe",
+            r#"fn main() { let x = true else {panic!()}.$0}"#,
+            r#"fn main() { let x = true else {panic!()}.unsafe}"#,
+        );
+    }
+
+    #[test]
     fn custom_postfix_completion() {
         let config = CompletionConfig {
             snippets: vec![Snippet::new(
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index e48d1aecd04..d6476c10258 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -1691,6 +1691,7 @@ fn main() {
                 sn while []
                 sn ref []
                 sn refm []
+                sn unsafe []
                 sn match []
                 sn box []
                 sn dbg []
@@ -1718,6 +1719,7 @@ fn main() {
                 me f() []
                 sn ref []
                 sn refm []
+                sn unsafe []
                 sn match []
                 sn box []
                 sn dbg []
diff --git a/crates/ide-completion/src/tests/proc_macros.rs b/crates/ide-completion/src/tests/proc_macros.rs
index fec149e56a9..92ea4d15b85 100644
--- a/crates/ide-completion/src/tests/proc_macros.rs
+++ b/crates/ide-completion/src/tests/proc_macros.rs
@@ -24,16 +24,17 @@ fn main() {
 }
 "#,
         expect![[r#"
-            me foo() fn(&self)
-            sn box   Box::new(expr)
-            sn call  function(expr)
-            sn dbg   dbg!(expr)
-            sn dbgr  dbg!(&expr)
-            sn let   let
-            sn letm  let mut
-            sn match match expr {}
-            sn ref   &expr
-            sn refm  &mut expr
+            me foo()  fn(&self)
+            sn box    Box::new(expr)
+            sn call   function(expr)
+            sn dbg    dbg!(expr)
+            sn dbgr   dbg!(&expr)
+            sn let    let
+            sn letm   let mut
+            sn match  match expr {}
+            sn ref    &expr
+            sn refm   &mut expr
+            sn unsafe unsafe {}
         "#]],
     )
 }
@@ -54,16 +55,17 @@ fn main() {
 }
 "#,
         expect![[r#"
-            me foo() fn(&self)
-            sn box   Box::new(expr)
-            sn call  function(expr)
-            sn dbg   dbg!(expr)
-            sn dbgr  dbg!(&expr)
-            sn let   let
-            sn letm  let mut
-            sn match match expr {}
-            sn ref   &expr
-            sn refm  &mut expr
+            me foo()  fn(&self)
+            sn box    Box::new(expr)
+            sn call   function(expr)
+            sn dbg    dbg!(expr)
+            sn dbgr   dbg!(&expr)
+            sn let    let
+            sn letm   let mut
+            sn match  match expr {}
+            sn ref    &expr
+            sn refm   &mut expr
+            sn unsafe unsafe {}
         "#]],
     )
 }
@@ -86,16 +88,17 @@ impl Foo {
 fn main() {}
 "#,
         expect![[r#"
-            me foo() fn(&self)
-            sn box   Box::new(expr)
-            sn call  function(expr)
-            sn dbg   dbg!(expr)
-            sn dbgr  dbg!(&expr)
-            sn let   let
-            sn letm  let mut
-            sn match match expr {}
-            sn ref   &expr
-            sn refm  &mut expr
+            me foo()  fn(&self)
+            sn box    Box::new(expr)
+            sn call   function(expr)
+            sn dbg    dbg!(expr)
+            sn dbgr   dbg!(&expr)
+            sn let    let
+            sn letm   let mut
+            sn match  match expr {}
+            sn ref    &expr
+            sn refm   &mut expr
+            sn unsafe unsafe {}
         "#]],
     )
 }
@@ -118,16 +121,17 @@ impl Foo {
 fn main() {}
 "#,
         expect![[r#"
-            me foo() fn(&self)
-            sn box   Box::new(expr)
-            sn call  function(expr)
-            sn dbg   dbg!(expr)
-            sn dbgr  dbg!(&expr)
-            sn let   let
-            sn letm  let mut
-            sn match match expr {}
-            sn ref   &expr
-            sn refm  &mut expr
+            me foo()  fn(&self)
+            sn box    Box::new(expr)
+            sn call   function(expr)
+            sn dbg    dbg!(expr)
+            sn dbgr   dbg!(&expr)
+            sn let    let
+            sn letm   let mut
+            sn match  match expr {}
+            sn ref    &expr
+            sn refm   &mut expr
+            sn unsafe unsafe {}
         "#]],
     )
 }