Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/expr.rs')
-rw-r--r--crates/ide-completion/src/completions/expr.rs78
1 files changed, 69 insertions, 9 deletions
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index a2a17d9218..87fae18f4c 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -2,6 +2,7 @@
use hir::ScopeDef;
use ide_db::FxHashSet;
+use syntax::T;
use crate::{
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
@@ -14,15 +15,16 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
return;
}
- let (&is_absolute_path, qualifier) = match ctx.path_context() {
- Some(PathCompletionCtx {
- kind: PathKind::Expr { .. },
- is_absolute_path,
- qualifier,
- ..
- }) => (is_absolute_path, qualifier),
- _ => return,
- };
+ let (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update) =
+ match ctx.path_context() {
+ Some(&PathCompletionCtx {
+ kind: PathKind::Expr { in_block_expr, in_loop_body, in_functional_update },
+ is_absolute_path,
+ ref qualifier,
+ ..
+ }) => (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update),
+ _ => return,
+ };
let scope_def_applicable = |def| {
use hir::{GenericParam::*, ModuleDef::*};
@@ -162,6 +164,64 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
acc.add_resolution(ctx, name, def);
}
});
+
+ if !in_functional_update {
+ let mut add_keyword =
+ |kw, snippet| super::keyword::add_keyword(acc, ctx, kw, snippet);
+
+ if ctx.expects_expression() {
+ if !in_block_expr {
+ add_keyword("unsafe", "unsafe {\n $0\n}");
+ }
+ add_keyword("match", "match $1 {\n $0\n}");
+ add_keyword("while", "while $1 {\n $0\n}");
+ add_keyword("while let", "while let $1 = $2 {\n $0\n}");
+ add_keyword("loop", "loop {\n $0\n}");
+ add_keyword("if", "if $1 {\n $0\n}");
+ add_keyword("if let", "if let $1 = $2 {\n $0\n}");
+ add_keyword("for", "for $1 in $2 {\n $0\n}");
+ add_keyword("true", "true");
+ add_keyword("false", "false");
+ }
+
+ if ctx.previous_token_is(T![if])
+ || ctx.previous_token_is(T![while])
+ || in_block_expr
+ {
+ add_keyword("let", "let");
+ }
+
+ if ctx.after_if() {
+ add_keyword("else", "else {\n $0\n}");
+ add_keyword("else if", "else if $1 {\n $0\n}");
+ }
+
+ if ctx.expects_ident_ref_expr() {
+ add_keyword("mut", "mut ");
+ }
+
+ if in_loop_body {
+ if in_block_expr {
+ add_keyword("continue", "continue;");
+ add_keyword("break", "break;");
+ } else {
+ add_keyword("continue", "continue");
+ add_keyword("break", "break");
+ }
+ }
+
+ if let Some(fn_def) = &ctx.function_def {
+ add_keyword(
+ "return",
+ match (in_block_expr, fn_def.ret_type().is_some()) {
+ (true, true) => "return ;",
+ (true, false) => "return;",
+ (false, true) => "return $0",
+ (false, false) => "return",
+ },
+ );
+ }
+ }
}
}
}