Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-completion/src/completions.rs20
-rw-r--r--crates/ide-completion/src/completions/expr.rs6
-rw-r--r--crates/ide-completion/src/context.rs5
-rw-r--r--crates/ide-completion/src/context/analysis.rs10
4 files changed, 29 insertions, 12 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index b076358443..f8747b0724 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -110,12 +110,18 @@ impl Completions {
["self", "super", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
}
- pub(crate) fn add_keyword_snippet(&mut self, ctx: &CompletionContext, kw: &str, snippet: &str) {
+ pub(crate) fn add_keyword_snippet_expr(
+ &mut self,
+ ctx: &CompletionContext,
+ kw: &str,
+ snippet: &str,
+ incomplete_let: bool,
+ ) {
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
match ctx.config.snippet_cap {
Some(cap) => {
- if snippet.ends_with('}') && ctx.incomplete_let {
+ if snippet.ends_with('}') && incomplete_let {
// complete block expression snippets with a trailing semicolon, if inside an incomplete let
cov_mark::hit!(let_semi);
item.insert_snippet(cap, format!("{};", snippet));
@@ -130,6 +136,16 @@ impl Completions {
item.add_to(self);
}
+ pub(crate) fn add_keyword_snippet(&mut self, ctx: &CompletionContext, kw: &str, snippet: &str) {
+ let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
+
+ match ctx.config.snippet_cap {
+ Some(cap) => item.insert_snippet(cap, snippet),
+ None => item.insert_text(if snippet.contains('$') { kw } else { snippet }),
+ };
+ item.add_to(self);
+ }
+
pub(crate) fn add_crate_roots(&mut self, ctx: &CompletionContext) {
ctx.process_all_names(&mut |name, res| match res {
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index ecc1442bfc..e4d1c290c0 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -26,6 +26,7 @@ pub(crate) fn complete_expr_path(
wants_mut_token,
in_condition,
ty,
+ incomplete_let,
) = match path_ctx {
&PathCompletionCtx {
kind:
@@ -34,6 +35,7 @@ pub(crate) fn complete_expr_path(
in_loop_body,
after_if_expr,
in_condition,
+ incomplete_let,
ref ref_expr_parent,
ref is_func_update,
ref innermost_ret_ty,
@@ -50,6 +52,7 @@ pub(crate) fn complete_expr_path(
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false),
in_condition,
innermost_ret_ty,
+ incomplete_let,
),
_ => return,
};
@@ -220,7 +223,8 @@ pub(crate) fn complete_expr_path(
});
if !is_func_update {
- let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
+ let mut add_keyword =
+ |kw, snippet| acc.add_keyword_snippet_expr(ctx, kw, snippet, incomplete_let);
if !in_block_expr {
add_keyword("unsafe", "unsafe {\n $0\n}");
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 7df9b4921a..bc2c2fc713 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -93,6 +93,7 @@ pub(super) enum PathKind {
after_if_expr: bool,
/// Whether this expression is the direct condition of an if or while expression
in_condition: bool,
+ incomplete_let: bool,
ref_expr_parent: Option<ast::RefExpr>,
is_func_update: Option<ast::RecordExpr>,
self_param: Option<hir::SelfParam>,
@@ -322,9 +323,6 @@ pub(crate) struct CompletionContext<'a> {
/// The parent impl of the cursor position if it exists.
// FIXME: This probably doesn't belong here
pub(super) impl_def: Option<ast::Impl>,
- /// Are we completing inside a let statement with a missing semicolon?
- // FIXME: This should be part of PathKind::Expr
- pub(super) incomplete_let: bool,
// FIXME: This shouldn't exist
pub(super) previous_token: Option<SyntaxToken>,
@@ -500,7 +498,6 @@ impl<'a> CompletionContext<'a> {
expected_name: None,
expected_type: None,
impl_def: None,
- incomplete_let: false,
previous_token: None,
// dummy value, will be overwritten
ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None },
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 4f65ae402e..d416d8251d 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -330,11 +330,6 @@ impl<'a> CompletionContext<'a> {
self.previous_token =
syntax_element.clone().into_token().and_then(previous_non_trivia_token);
- self.incomplete_let =
- syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
- it.syntax().text_range().end() == syntax_element.text_range().end()
- });
-
(self.expected_type, self.expected_name) = self.expected_type_and_name();
// Overwrite the path kind for derives
@@ -767,6 +762,10 @@ impl<'a> CompletionContext<'a> {
};
let is_func_update = func_update_record(it);
let in_condition = is_in_condition(&expr);
+ let incomplete_let = it
+ .parent()
+ .and_then(ast::LetStmt::cast)
+ .map_or(false, |it| it.semicolon_token().is_none());
PathKind::Expr {
in_block_expr,
@@ -777,6 +776,7 @@ impl<'a> CompletionContext<'a> {
is_func_update,
innermost_ret_ty,
self_param,
+ incomplete_let,
}
};
let make_path_kind_type = |ty: ast::Type| {