diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index eb26543a4b..7219a5f1b0 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -345,6 +345,7 @@ pub(crate) fn complete_expr_path( if !in_block_expr { add_keyword("unsafe", "unsafe {\n $0\n}"); + add_keyword("const", "const {\n $0\n}"); } add_keyword("match", "match $1 {\n $0\n}"); add_keyword("while", "while $1 {\n $0\n}"); diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs index 26c29e0202..14b0d543ca 100644 --- a/crates/ide-completion/src/completions/keyword.rs +++ b/crates/ide-completion/src/completions/keyword.rs @@ -76,6 +76,7 @@ fn foo(a: A) { a.$0 } kw await expr.await sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -103,6 +104,7 @@ fn foo() { kw await expr.await sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -132,6 +134,7 @@ fn foo(a: A) { a.$0 } kw await expr.await sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index eb84debcaf..3a55e83026 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -155,22 +155,29 @@ pub(crate) fn complete_postfix( postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc, ctx.db); postfix_snippet("deref", "*expr", &format!("*{receiver_text}")).add_to(acc, ctx.db); - let mut unsafe_should_be_wrapped = true; + let mut block_should_be_wrapped = true; if dot_receiver.syntax().kind() == BLOCK_EXPR { - unsafe_should_be_wrapped = false; + block_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; + block_should_be_wrapped = true; } } }; - let unsafe_completion_string = if unsafe_should_be_wrapped { + let unsafe_completion_string = if block_should_be_wrapped { format!("unsafe {{ {receiver_text} }}") } else { format!("unsafe {receiver_text}") }; postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc, ctx.db); + let const_completion_string = if block_should_be_wrapped { + format!("const {{ {receiver_text} }}") + } else { + format!("const {receiver_text}") + }; + postfix_snippet("const", "const {}", &const_completion_string).add_to(acc, ctx.db); + // 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 @@ -430,6 +437,7 @@ fn main() { expect![[r#" sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -463,6 +471,7 @@ fn main() { expect![[r#" sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -490,6 +499,7 @@ fn main() { expect![[r#" sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -516,6 +526,7 @@ fn main() { expect![[r#" sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -653,44 +664,57 @@ 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 } }"#); + postfix_completion_for_block("unsafe"); + } + + #[test] + fn postfix_completion_for_const() { + postfix_completion_for_block("const"); + } + + fn postfix_completion_for_block(kind: &str) { + check_edit(kind, r#"fn main() { foo.$0 }"#, &format!("fn main() {{ {kind} {{ foo }} }}")); check_edit( - "unsafe", + kind, + r#"fn main() { { foo }.$0 }"#, + &format!("fn main() {{ {kind} {{ foo }} }}"), + ); + check_edit( + kind, r#"fn main() { if x { foo }.$0 }"#, - r#"fn main() { unsafe { if x { foo } } }"#, + &format!("fn main() {{ {kind} {{ if x {{ foo }} }} }}"), ); check_edit( - "unsafe", + kind, r#"fn main() { loop { foo }.$0 }"#, - r#"fn main() { unsafe { loop { foo } } }"#, + &format!("fn main() {{ {kind} {{ loop {{ foo }} }} }}"), ); check_edit( - "unsafe", + kind, r#"fn main() { if true {}.$0 }"#, - r#"fn main() { unsafe { if true {} } }"#, + &format!("fn main() {{ {kind} {{ if true {{}} }} }}"), ); check_edit( - "unsafe", + kind, r#"fn main() { while true {}.$0 }"#, - r#"fn main() { unsafe { while true {} } }"#, + &format!("fn main() {{ {kind} {{ while true {{}} }} }}"), ); check_edit( - "unsafe", + kind, r#"fn main() { for i in 0..10 {}.$0 }"#, - r#"fn main() { unsafe { for i in 0..10 {} } }"#, + &format!("fn main() {{ {kind} {{ for i in 0..10 {{}} }} }}"), ); check_edit( - "unsafe", + kind, r#"fn main() { let x = if true {1} else {2}.$0 }"#, - r#"fn main() { let x = unsafe { if true {1} else {2} } }"#, + &format!("fn main() {{ let x = {kind} {{ if true {{1}} else {{2}} }} }}"), ); // completion will not be triggered check_edit( - "unsafe", + kind, r#"fn main() { let x = true else {panic!()}.$0}"#, - r#"fn main() { let x = true else {panic!()}.unsafe $0}"#, + &format!("fn main() {{ let x = true else {{panic!()}}.{kind} $0}}"), ); } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 793a2fc027..82c12662c4 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -3006,6 +3006,7 @@ fn main() { sn refm &mut expr [] sn deref *expr [] sn unsafe unsafe {} [] + sn const const {} [] sn match match expr {} [] sn box Box::new(expr) [] sn dbg dbg!(expr) [] @@ -3036,6 +3037,7 @@ fn main() { sn refm &mut expr [] sn deref *expr [] sn unsafe unsafe {} [] + sn const const {} [] sn match match expr {} [] sn box Box::new(expr) [] sn dbg dbg!(expr) [] diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index 61823811dc..22d42ba750 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -58,6 +58,7 @@ fn baz() { un Union Union ev TupleV(…) TupleV(u32) bt u32 u32 + kw const kw crate:: kw false kw for @@ -101,6 +102,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) { lc param1 i32 lc param2 i32 bt u32 u32 + kw const kw crate:: kw false kw for @@ -335,6 +337,7 @@ fn complete_in_match_arm() { expect![[r#" fn foo() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -400,6 +403,7 @@ fn completes_in_loop_ctx() { sn box Box::new(expr) sn break break expr sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -424,6 +428,7 @@ fn completes_in_let_initializer() { expect![[r#" fn main() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -448,6 +453,7 @@ fn completes_after_ref_expr() { expect![[r#" fn main() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -471,6 +477,7 @@ fn completes_after_ref_expr() { fn main() fn() bt u32 u32 kw const + kw const kw crate:: kw false kw for @@ -492,6 +499,7 @@ fn completes_after_ref_expr() { expect![[r#" fn main() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -512,6 +520,7 @@ fn completes_after_ref_expr() { expect![[r#" fn main() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -532,6 +541,7 @@ fn completes_after_ref_expr() { expect![[r#" fn main() fn() bt u32 u32 + kw const kw crate:: kw false kw for @@ -566,6 +576,7 @@ fn foo() { fn foo() fn() st Foo Foo bt u32 u32 + kw const kw crate:: kw false kw for @@ -601,6 +612,7 @@ fn foo() { fn foo() fn() lc bar i32 bt u32 u32 + kw const kw crate:: kw false kw for @@ -632,6 +644,7 @@ fn quux(x: i32) { lc x i32 ma m!(…) macro_rules! m bt u32 u32 + kw const kw crate:: kw false kw for @@ -659,6 +672,7 @@ fn quux(x: i32) { lc x i32 ma m!(…) macro_rules! m bt u32 u32 + kw const kw crate:: kw false kw for @@ -688,6 +702,7 @@ fn quux(x: i32) { lc y i32 ma m!(…) macro_rules! m bt u32 u32 + kw const kw crate:: kw false kw for @@ -870,6 +885,7 @@ fn brr() { st YoloVariant YoloVariant st YoloVariant {…} YoloVariant { f: usize } bt u32 u32 + kw const kw crate:: kw false kw for @@ -1016,6 +1032,7 @@ fn foo() { bar(if foo {} $0) } expect![[r#" fn foo() fn() bt u32 u32 + kw const kw crate:: kw else kw else if @@ -1040,6 +1057,7 @@ fn foo() { bar(if foo {} el$0) } expect![[r#" fn foo() fn() bt u32 u32 + kw const kw crate:: kw else kw else if @@ -1309,6 +1327,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1335,6 +1354,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1365,6 +1385,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1391,6 +1412,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1417,6 +1439,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1442,6 +1465,7 @@ fn main() { expect![[r#" sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1557,6 +1581,7 @@ fn foo() { me inherent() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1594,6 +1619,7 @@ fn foo(v: &dyn ExcludedTrait) { me foo() (as ExcludedTrait) fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1627,6 +1653,7 @@ fn foo(v: impl ExcludedTrait) { me foo() (as ExcludedTrait) fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1660,6 +1687,7 @@ fn foo(v: T) { me foo() (as ExcludedTrait) fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1708,6 +1736,7 @@ fn foo() { me inherent() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1759,6 +1788,7 @@ fn foo() { me inherent() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr diff --git a/crates/ide-completion/src/tests/proc_macros.rs b/crates/ide-completion/src/tests/proc_macros.rs index 6b1dfe366c..626d1677d5 100644 --- a/crates/ide-completion/src/tests/proc_macros.rs +++ b/crates/ide-completion/src/tests/proc_macros.rs @@ -22,6 +22,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -55,6 +56,7 @@ fn main() { me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -90,6 +92,7 @@ fn main() {} me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -125,6 +128,7 @@ fn main() {} me foo() fn(&self) sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index afb41cf613..70caeac95b 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -1146,6 +1146,7 @@ fn here_we_go() { me baz() (alias qux) fn(&self) -> u8 sn box Box::new(expr) sn call function(expr) + sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr @@ -1264,6 +1265,7 @@ fn here_we_go() { md foo st Bar (alias Qux) (use foo::Bar) Bar bt u32 u32 + kw const kw crate:: kw false kw for