Unnamed repository; edit this file 'description' to name the repository.
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.
bors 2023-02-08
parent a05ce5a · parent 2666e6e · commit 6effb26
-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 1d03c8cc5c..b9ab2afca2 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 f4f37d77d8..90c523735d 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 e48d1aecd0..d6476c1025 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 fec149e56a..92ea4d15b8 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 {}
"#]],
)
}