Unnamed repository; edit this file 'description' to name the repository.
Make else autocompletion work in more places
Lukas Wirth 2023-02-12
parent 33cacde · commit d2cf8c2
-rw-r--r--crates/ide-completion/src/context/analysis.rs11
-rw-r--r--crates/ide-completion/src/tests/expression.rs252
-rw-r--r--crates/ide-completion/src/tests/special.rs81
3 files changed, 305 insertions, 39 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 036fc98629..f696b273a4 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -380,7 +380,7 @@ fn expected_type_and_name(
sema,
token.clone(),
).map(|ap| {
- let name = dbg!(ap.ident().map(NameOrNameRef::Name));
+ let name = ap.ident().map(NameOrNameRef::Name);
let ty = strip_refs(ap.ty);
(Some(ty), name)
@@ -656,8 +656,15 @@ fn classify_name_ref(
};
let after_if_expr = |node: SyntaxNode| {
let prev_expr = (|| {
+ let node = match node.parent().and_then(ast::ExprStmt::cast) {
+ Some(stmt) => stmt.syntax().clone(),
+ None => node,
+ };
let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?;
- ast::ExprStmt::cast(prev_sibling)?.expr()
+
+ ast::ExprStmt::cast(prev_sibling.clone())
+ .and_then(|it| it.expr())
+ .or_else(|| ast::Expr::cast(prev_sibling))
})();
matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
};
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index 043f552bd8..c1c6a689eb 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -745,3 +745,255 @@ fn return_value_no_block() {
r#"fn f() -> i32 { match () { () => return $0 } }"#,
);
}
+
+#[test]
+fn else_completion_after_if() {
+ check_empty(
+ r#"
+fn foo() { if foo {} $0 }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { bar(if foo {} $0) }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw crate::
+ kw else
+ kw else if
+ kw false
+ kw for
+ kw if
+ kw if let
+ kw loop
+ kw match
+ kw return
+ kw self::
+ kw true
+ kw unsafe
+ kw while
+ kw while let
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { bar(if foo {} el$0) }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw crate::
+ kw else
+ kw else if
+ kw false
+ kw for
+ kw if
+ kw if let
+ kw loop
+ kw match
+ kw return
+ kw self::
+ kw true
+ kw unsafe
+ kw while
+ kw while let
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} $0 let x = 92; }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 let x = 92; }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 { let x = 92; } }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+}
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index 6052b06232..cb71c7b2bd 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -2,13 +2,20 @@
use expect_test::{expect, Expect};
-use crate::tests::{check_edit, completion_list_no_kw, completion_list_with_trigger_character};
+use crate::tests::{
+ check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character,
+};
-fn check(ra_fixture: &str, expect: Expect) {
+fn check_no_kw(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
}
+fn check(ra_fixture: &str, expect: Expect) {
+ let actual = completion_list(ra_fixture);
+ expect.assert_eq(&actual)
+}
+
pub(crate) fn check_with_trigger_character(
ra_fixture: &str,
trigger_character: Option<char>,
@@ -59,7 +66,7 @@ fn _alpha() {}
#[test]
fn completes_prelude() {
- check(
+ check_no_kw(
r#"
//- /main.rs edition:2018 crate:main deps:std
fn foo() { let x: $0 }
@@ -81,7 +88,7 @@ pub mod prelude {
#[test]
fn completes_prelude_macros() {
- check(
+ check_no_kw(
r#"
//- /main.rs edition:2018 crate:main deps:std
fn f() {$0}
@@ -110,7 +117,7 @@ mod macros {
#[test]
fn completes_std_prelude_if_core_is_defined() {
- check(
+ check_no_kw(
r#"
//- /main.rs crate:main deps:core,std
fn foo() { let x: $0 }
@@ -140,7 +147,7 @@ pub mod prelude {
#[test]
fn respects_doc_hidden() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:std
fn f() {
@@ -168,7 +175,7 @@ pub mod prelude {
#[test]
fn respects_doc_hidden_in_assoc_item_list() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:std
struct S;
@@ -195,7 +202,7 @@ pub mod prelude {
#[test]
fn associated_item_visibility() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib new_source_root:library
pub struct S;
@@ -222,7 +229,7 @@ fn foo() { let _ = lib::S::$0 }
#[test]
fn completes_union_associated_method() {
- check(
+ check_no_kw(
r#"
union U {};
impl U { fn m() { } }
@@ -237,7 +244,7 @@ fn foo() { let _ = U::$0 }
#[test]
fn completes_trait_associated_method_1() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -251,7 +258,7 @@ fn foo() { let _ = Trait::$0 }
#[test]
fn completes_trait_associated_method_2() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -268,7 +275,7 @@ fn foo() { let _ = S::$0 }
#[test]
fn completes_trait_associated_method_3() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -285,7 +292,7 @@ fn foo() { let _ = <S as Trait>::$0 }
#[test]
fn completes_ty_param_assoc_ty() {
- check(
+ check_no_kw(
r#"
trait Super {
type Ty;
@@ -318,7 +325,7 @@ fn foo<T: Sub>() { T::$0 }
#[test]
fn completes_self_param_assoc_ty() {
- check(
+ check_no_kw(
r#"
trait Super {
type Ty;
@@ -358,7 +365,7 @@ impl<T> Sub for Wrap<T> {
#[test]
fn completes_type_alias() {
- check(
+ check_no_kw(
r#"
struct S;
impl S { fn foo() {} }
@@ -376,7 +383,7 @@ fn main() { T::$0; }
#[test]
fn completes_qualified_macros() {
- check(
+ check_no_kw(
r#"
#[macro_export]
macro_rules! foo { () => {} }
@@ -392,7 +399,7 @@ fn main() { let _ = crate::$0 }
#[test]
fn does_not_complete_non_fn_macros() {
- check(
+ check_no_kw(
r#"
mod m {
#[rustc_builtin_macro]
@@ -403,7 +410,7 @@ fn f() {m::$0}
"#,
expect![[r#""#]],
);
- check(
+ check_no_kw(
r#"
mod m {
#[rustc_builtin_macro]
@@ -418,7 +425,7 @@ fn f() {m::$0}
#[test]
fn completes_reexported_items_under_correct_name() {
- check(
+ check_no_kw(
r#"
fn foo() { self::m::$0 }
@@ -475,7 +482,7 @@ mod p {
#[test]
fn completes_in_simple_macro_call() {
- check(
+ check_no_kw(
r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() { m!(self::f$0); }
@@ -490,7 +497,7 @@ fn foo() {}
#[test]
fn function_mod_share_name() {
- check(
+ check_no_kw(
r#"
fn foo() { self::m::$0 }
@@ -508,7 +515,7 @@ mod m {
#[test]
fn completes_hashmap_new() {
- check(
+ check_no_kw(
r#"
struct RandomState;
struct HashMap<K, V, S = RandomState> {}
@@ -529,7 +536,7 @@ fn foo() {
#[test]
fn completes_variant_through_self() {
cov_mark::check!(completes_variant_through_self);
- check(
+ check_no_kw(
r#"
enum Foo {
Bar,
@@ -552,7 +559,7 @@ impl Foo {
#[test]
fn completes_non_exhaustive_variant_within_the_defining_crate() {
- check(
+ check_no_kw(
r#"
enum Foo {
#[non_exhaustive]
@@ -570,7 +577,7 @@ fn foo(self) {
"#]],
);
- check(
+ check_no_kw(
r#"
//- /main.rs crate:main deps:e
fn foo(self) {
@@ -593,7 +600,7 @@ enum Foo {
#[test]
fn completes_primitive_assoc_const() {
cov_mark::check!(completes_primitive_assoc_const);
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:core
fn f() {
@@ -618,7 +625,7 @@ impl u8 {
#[test]
fn completes_variant_through_alias() {
cov_mark::check!(completes_variant_through_alias);
- check(
+ check_no_kw(
r#"
enum Foo {
Bar
@@ -636,7 +643,7 @@ fn main() {
#[test]
fn respects_doc_hidden2() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:dep
fn f() {
@@ -665,7 +672,7 @@ pub mod m {}
#[test]
fn type_anchor_empty() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -688,7 +695,7 @@ fn bar() -> Bar {
#[test]
fn type_anchor_type() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -715,7 +722,7 @@ fn bar() -> Bar {
#[test]
fn type_anchor_type_trait() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -741,7 +748,7 @@ fn bar() -> Bar {
#[test]
fn completes_fn_in_pub_trait_generated_by_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_method {
@@ -775,7 +782,7 @@ fn main() {
#[test]
fn completes_fn_in_pub_trait_generated_by_recursive_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_method {
@@ -815,7 +822,7 @@ fn main() {
#[test]
fn completes_const_in_pub_trait_generated_by_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_const {
@@ -847,7 +854,7 @@ fn main() {
#[test]
fn completes_locals_from_macros() {
- check(
+ check_no_kw(
r#"
macro_rules! x {
@@ -875,7 +882,7 @@ fn main() {
#[test]
fn regression_12644() {
- check(
+ check_no_kw(
r#"
macro_rules! __rust_force_expr {
($e:expr) => {
@@ -974,7 +981,7 @@ fn foo { crate:::$0 }
"#,
expect![""],
);
- check(
+ check_no_kw(
r#"
fn foo { crate::::$0 }
"#,