|  | //! Completes `where` and `for` keywords. | 
|  |  | 
|  | use syntax::ast::{self, Item}; | 
|  |  | 
|  | use crate::{CompletionContext, Completions}; | 
|  |  | 
|  | pub(crate) fn complete_for_and_where( | 
|  | acc: &mut Completions, | 
|  | ctx: &CompletionContext<'_>, | 
|  | keyword_item: &ast::Item, | 
|  | ) { | 
|  | let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet); | 
|  |  | 
|  | match keyword_item { | 
|  | Item::Impl(it) => { | 
|  | if it.for_token().is_none() && it.trait_().is_none() && it.self_ty().is_some() { | 
|  | add_keyword("for", "for $0"); | 
|  | } | 
|  | add_keyword("where", "where $0"); | 
|  | } | 
|  | Item::Enum(_) | 
|  | | Item::Fn(_) | 
|  | | Item::Struct(_) | 
|  | | Item::Trait(_) | 
|  | | Item::TypeAlias(_) | 
|  | | Item::Union(_) => { | 
|  | add_keyword("where", "where $0"); | 
|  | } | 
|  | _ => (), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(test)] | 
|  | mod tests { | 
|  | use expect_test::expect; | 
|  |  | 
|  | use crate::tests::{check, check_edit}; | 
|  |  | 
|  | #[test] | 
|  | fn test_else_edit_after_if() { | 
|  | check_edit( | 
|  | "else", | 
|  | r#"fn quux() { if true { () } $0 }"#, | 
|  | r#"fn quux() { if true { () } else { | 
|  | $0 | 
|  | } }"#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_keywords_after_unsafe_in_block_expr() { | 
|  | check( | 
|  | r"fn my_fn() { unsafe $0 }", | 
|  | expect![[r#" | 
|  | kw async | 
|  | kw extern | 
|  | kw fn | 
|  | kw impl | 
|  | kw impl for | 
|  | kw trait | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_completion_await_impls_future() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: future | 
|  | use core::future::*; | 
|  | struct A {} | 
|  | impl Future for A {} | 
|  | fn foo(a: A) { a.$0 } | 
|  | "#, | 
|  | expect![[r#" | 
|  | me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture | 
|  | 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 | 
|  | sn let                                                                    let | 
|  | sn letm                                                               let mut | 
|  | sn match                                                        match expr {} | 
|  | sn ref                                                                  &expr | 
|  | sn refm                                                             &mut expr | 
|  | sn return                                                         return expr | 
|  | sn unsafe                                                           unsafe {} | 
|  | "#]], | 
|  | ); | 
|  |  | 
|  | check( | 
|  | r#" | 
|  | //- minicore: future | 
|  | use std::future::*; | 
|  | fn foo() { | 
|  | let a = async {}; | 
|  | a.$0 | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture | 
|  | 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 | 
|  | sn let                                                                                   let | 
|  | sn letm                                                                              let mut | 
|  | sn match                                                                       match expr {} | 
|  | sn ref                                                                                 &expr | 
|  | sn refm                                                                            &mut expr | 
|  | sn return                                                                        return expr | 
|  | sn unsafe                                                                          unsafe {} | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_completion_await_impls_into_future() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: future | 
|  | use core::future::*; | 
|  | struct A {} | 
|  | impl IntoFuture for A {} | 
|  | fn foo(a: A) { a.$0 } | 
|  | "#, | 
|  | expect![[r#" | 
|  | me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture | 
|  | 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 | 
|  | sn let                                                                    let | 
|  | sn letm                                                               let mut | 
|  | sn match                                                        match expr {} | 
|  | sn ref                                                                  &expr | 
|  | sn refm                                                             &mut expr | 
|  | sn return                                                         return expr | 
|  | sn unsafe                                                           unsafe {} | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn for_in_impl() { | 
|  | check_edit( | 
|  | "for", | 
|  | r#" | 
|  | struct X; | 
|  | impl X $0 {} | 
|  | "#, | 
|  | r#" | 
|  | struct X; | 
|  | impl X for $0 {} | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "for", | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X $0 {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X for $0 {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "for", | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X $0 | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X for $0 | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "for", | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X { fn bar() { $0 } } | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn foo() { | 
|  | struct X; | 
|  | impl X { fn bar() { for $1 in $2 { | 
|  | $0 | 
|  | } } } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn let_semi() { | 
|  | cov_mark::check!(let_semi); | 
|  | check_edit( | 
|  | "match", | 
|  | r#" | 
|  | fn main() { let x = $0 } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { let x = match $1 { | 
|  | $0 | 
|  | }; } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "if", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = $0 | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if $1 { | 
|  | $2 | 
|  | } else { | 
|  | $0 | 
|  | }; | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "else", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } $0 | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } else { | 
|  | $0 | 
|  | }; | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "else if", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } $0 else {}; | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } else if $1 { | 
|  | $0 | 
|  | } else {}; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "else if", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } $0 else if true {}; | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = if true { | 
|  | () | 
|  | } else if $1 { | 
|  | $0 | 
|  | } else if true {}; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "else", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = 2 $0 | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = 2 else { | 
|  | $0 | 
|  | }; | 
|  | let y = 92; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "loop", | 
|  | r#" | 
|  | fn main() { | 
|  | let x = $0 | 
|  | bar(); | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let x = loop { | 
|  | $0 | 
|  | }; | 
|  | bar(); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_completion_in_match_guard() { | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () $0 | 
|  | } | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () if $0 | 
|  | } | 
|  | } | 
|  | ", | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_completion_in_match_arm_expr() { | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () => $0 | 
|  | } | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () => if $1 { | 
|  | $0 | 
|  | } | 
|  | } | 
|  | } | 
|  | ", | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_completion_in_match_arm_expr_block() { | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () => { | 
|  | $0 | 
|  | } | 
|  | } | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | match () { | 
|  | () => { | 
|  | if $1 { | 
|  | $0 | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | ", | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_completion_in_parameter() { | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | foo($0) | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | foo(if $1 { | 
|  | $2 | 
|  | } else { | 
|  | $0 | 
|  | }) | 
|  | } | 
|  | ", | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | foo($0, 2) | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | foo(if $1 { | 
|  | $2 | 
|  | } else { | 
|  | $0 | 
|  | }, 2) | 
|  | } | 
|  | ", | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | foo(2, $0) | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | foo(2, if $1 { | 
|  | $2 | 
|  | } else { | 
|  | $0 | 
|  | }) | 
|  | } | 
|  | ", | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "if let", | 
|  | r" | 
|  | fn main() { | 
|  | foo(2, $0) | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | foo(2, if let $1 = $2 { | 
|  | $3 | 
|  | } else { | 
|  | $0 | 
|  | }) | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_completion_in_let_statement() { | 
|  | check_edit( | 
|  | "if", | 
|  | r" | 
|  | fn main() { | 
|  | let x = $0; | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | let x = if $1 { | 
|  | $2 | 
|  | } else { | 
|  | $0 | 
|  | }; | 
|  | } | 
|  | ", | 
|  | ); | 
|  |  | 
|  | check_edit( | 
|  | "if let", | 
|  | r" | 
|  | fn main() { | 
|  | let x = $0; | 
|  | } | 
|  | ", | 
|  | r" | 
|  | fn main() { | 
|  | let x = if let $1 = $2 { | 
|  | $3 | 
|  | } else { | 
|  | $0 | 
|  | }; | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn completes_let_in_block() { | 
|  | check_edit( | 
|  | "let", | 
|  | r#" | 
|  | fn main() { | 
|  | $0 | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let $1 = $0; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "letm", | 
|  | r#" | 
|  | fn main() { | 
|  | $0 | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | let mut $1 = $0; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn completes_let_in_condition() { | 
|  | check_edit( | 
|  | "let", | 
|  | r#" | 
|  | fn main() { | 
|  | if $0 {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if let $1 = $0 {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "letm", | 
|  | r#" | 
|  | fn main() { | 
|  | if $0 {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if let mut $1 = $0 {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn completes_let_in_no_empty_condition() { | 
|  | check_edit( | 
|  | "let", | 
|  | r#" | 
|  | fn main() { | 
|  | if $0x {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if let $1 = $0x {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "letm", | 
|  | r#" | 
|  | fn main() { | 
|  | if $0x {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if let mut $1 = $0x {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn completes_let_in_condition_block() { | 
|  | check_edit( | 
|  | "let", | 
|  | r#" | 
|  | fn main() { | 
|  | if { $0 } {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if { let $1 = $0; } {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_edit( | 
|  | "letm", | 
|  | r#" | 
|  | fn main() { | 
|  | if { $0 } {} | 
|  | } | 
|  | "#, | 
|  | r#" | 
|  | fn main() { | 
|  | if { let mut $1 = $0; } {} | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  | } |