Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #12204 - Veykril:completions, r=Veykril
internal: Move keyword expressions to expr completions module
bors 2022-05-10
parent 4a4e9c0 · parent b2abe1b · commit 254bfdd
-rw-r--r--crates/ide-completion/src/completions/expr.rs78
-rw-r--r--crates/ide-completion/src/completions/fn_param.rs1
-rw-r--r--crates/ide-completion/src/completions/keyword.rs73
-rw-r--r--crates/ide-completion/src/completions/trait_impl.rs1
-rw-r--r--crates/ide-completion/src/completions/vis.rs2
-rw-r--r--crates/ide-completion/src/context.rs15
-rw-r--r--crates/ide-completion/src/lib.rs2
-rw-r--r--crates/ide-completion/src/tests/record.rs11
8 files changed, 84 insertions, 99 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",
+ },
+ );
+ }
+ }
}
}
}
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index 47cead7d57..0cdb8ee119 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -13,6 +13,7 @@ use crate::{
CompletionContext, CompletionItem, CompletionItemKind, Completions,
};
+// FIXME: Make this a submodule of [`pattern`]
/// Complete repeated parameters, both name and type. For example, if all
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
/// `spam: &mut Spam` insert text/label will be suggested.
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index b34545414e..14211f86ba 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -5,9 +5,8 @@
use syntax::T;
use crate::{
- context::{PathCompletionCtx, PathKind},
- patterns::ImmediateLocation,
- CompletionContext, CompletionItem, CompletionItemKind, Completions,
+ context::PathKind, patterns::ImmediateLocation, CompletionContext, CompletionItem,
+ CompletionItemKind, Completions,
};
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -83,75 +82,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
add_keyword("struct", "struct $0");
add_keyword("union", "union $1 {\n $0\n}");
}
-
- if ctx.expects_type() {
- return;
- }
-
- if ctx.expects_expression() {
- if !has_block_expr_parent {
- 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]) || has_block_expr_parent {
- 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 ");
- }
-
- let (can_be_stmt, in_loop_body) = match ctx.path_context() {
- Some(&PathCompletionCtx {
- is_absolute_path: false,
- kind: PathKind::Expr { in_block_expr, in_loop_body, .. },
- ..
- }) => (in_block_expr, in_loop_body),
- _ => return,
- };
-
- if in_loop_body {
- if can_be_stmt {
- add_keyword("continue", "continue;");
- add_keyword("break", "break;");
- } else {
- add_keyword("continue", "continue");
- add_keyword("break", "break");
- }
- }
-
- let fn_def = match &ctx.function_def {
- Some(it) => it,
- None => return,
- };
-
- add_keyword(
- "return",
- match (can_be_stmt, fn_def.ret_type().is_some()) {
- (true, true) => "return $0;",
- (true, false) => "return;",
- (false, true) => "return $0",
- (false, false) => "return",
- },
- )
}
-fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
+pub(super) fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
match ctx.config.snippet_cap {
diff --git a/crates/ide-completion/src/completions/trait_impl.rs b/crates/ide-completion/src/completions/trait_impl.rs
index e3c15038d0..61c5d12649 100644
--- a/crates/ide-completion/src/completions/trait_impl.rs
+++ b/crates/ide-completion/src/completions/trait_impl.rs
@@ -52,6 +52,7 @@ enum ImplCompletionKind {
Const,
}
+// FIXME: Make this a submodule of [`item_list`]
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
if let Some((kind, replacement_range, impl_def)) = completion_match(ctx) {
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
diff --git a/crates/ide-completion/src/completions/vis.rs b/crates/ide-completion/src/completions/vis.rs
index b5e86b62d1..d538f1879e 100644
--- a/crates/ide-completion/src/completions/vis.rs
+++ b/crates/ide-completion/src/completions/vis.rs
@@ -7,7 +7,7 @@ use crate::{
Completions,
};
-pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
+pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext) {
let (&is_absolute_path, qualifier, &has_in_token) = match ctx.path_context() {
Some(PathCompletionCtx {
kind: PathKind::Vis { has_in_token },
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index f6b8962df6..4a058ac261 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -48,6 +48,7 @@ pub(super) enum PathKind {
Expr {
in_block_expr: bool,
in_loop_body: bool,
+ in_functional_update: bool,
},
Type,
Attr {
@@ -392,10 +393,6 @@ impl<'a> CompletionContext<'a> {
matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Expr { .. }, .. }))
}
- pub(crate) fn expects_type(&self) -> bool {
- matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Type, .. }))
- }
-
pub(crate) fn is_non_trivial_path(&self) -> bool {
matches!(
self.path_context(),
@@ -1104,6 +1101,9 @@ impl<'a> CompletionContext<'a> {
})
.unwrap_or(false)
};
+ let is_in_func_update = |it: &SyntaxNode| {
+ it.parent().map_or(false, |it| ast::RecordExprFieldList::can_cast(it.kind()))
+ };
let kind = path.syntax().ancestors().find_map(|it| {
// using Option<Option<PathKind>> as extra controlflow
@@ -1114,8 +1114,8 @@ impl<'a> CompletionContext<'a> {
path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
let in_block_expr = is_in_block(it.syntax());
let in_loop_body = is_in_loop_body(it.syntax());
-
- Some(PathKind::Expr { in_block_expr, in_loop_body })
+ let in_functional_update = is_in_func_update(it.syntax());
+ Some(PathKind::Expr { in_block_expr, in_loop_body, in_functional_update })
},
ast::TupleStructPat(it) => {
path_ctx.has_call_parens = true;
@@ -1149,7 +1149,8 @@ impl<'a> CompletionContext<'a> {
return Some(parent.and_then(ast::MacroExpr::cast).map(|it| {
let in_loop_body = is_in_loop_body(it.syntax());
let in_block_expr = is_in_block(it.syntax());
- PathKind::Expr { in_block_expr, in_loop_body }
+ let in_functional_update = is_in_func_update(it.syntax());
+ PathKind::Expr { in_block_expr, in_loop_body, in_functional_update }
}));
},
}
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 6695fcdc19..7789c96707 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -173,7 +173,7 @@ pub fn completions(
completions::r#type::complete_type_path(acc, ctx);
completions::r#type::complete_inferred_type(acc, ctx);
completions::use_::complete_use_tree(acc, ctx);
- completions::vis::complete_vis(acc, ctx);
+ completions::vis::complete_vis_path(acc, ctx);
}
Some(acc)
diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs
index a0f8b24867..2c49761748 100644
--- a/crates/ide-completion/src/tests/record.rs
+++ b/crates/ide-completion/src/tests/record.rs
@@ -168,19 +168,8 @@ fn main() {
tt Sized
bt u32
kw crate::
- kw false
- kw for
- kw if
- kw if let
- kw loop
- kw match
- kw return
kw self::
kw super::
- kw true
- kw unsafe
- kw while
- kw while let
"#]],
);
check(