Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/postfix.rs')
-rw-r--r--crates/ide-completion/src/completions/postfix.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index d355fdbe07..73cbe3f0aa 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -11,12 +11,12 @@ use ide_db::{
text_edit::TextEdit,
ty_filter::TryEnum,
};
-use itertools::Either;
use stdx::never;
use syntax::{
SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR},
- TextRange, TextSize,
+ T, TextRange, TextSize,
ast::{self, AstNode, AstToken},
+ match_ast,
};
use crate::{
@@ -113,12 +113,8 @@ pub(crate) fn complete_postfix(
if let Some(parent) = dot_receiver_including_refs.syntax().parent()
&& let Some(second_ancestor) = parent.parent()
{
- let sec_ancestor_kind = second_ancestor.kind();
- if let Some(expr) = <Either<ast::IfExpr, ast::WhileExpr>>::cast(second_ancestor) {
- is_in_cond = match expr {
- Either::Left(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent),
- Either::Right(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent),
- }
+ if let Some(parent_expr) = ast::Expr::cast(parent) {
+ is_in_cond = is_in_condition(&parent_expr);
}
match &try_enum {
Some(try_enum) if is_in_cond => match try_enum {
@@ -147,7 +143,7 @@ pub(crate) fn complete_postfix(
.add_to(acc, ctx.db);
}
},
- _ if matches!(sec_ancestor_kind, STMT_LIST | EXPR_STMT) => {
+ _ if matches!(second_ancestor.kind(), STMT_LIST | EXPR_STMT) => {
postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
.add_to(acc, ctx.db);
postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};"))
@@ -295,7 +291,7 @@ pub(crate) fn complete_postfix(
)
.add_to(acc, ctx.db);
- if let BreakableKind::Block | BreakableKind::Loop = expr_ctx.in_breakable {
+ if let Some(BreakableKind::Block | BreakableKind::Loop) = expr_ctx.in_breakable {
postfix_snippet(
"break",
"break expr",
@@ -454,6 +450,22 @@ fn add_custom_postfix_completions(
None
}
+pub(crate) fn is_in_condition(it: &ast::Expr) -> bool {
+ it.syntax()
+ .parent()
+ .and_then(|parent| {
+ Some(match_ast! { match parent {
+ ast::IfExpr(expr) => expr.condition()? == *it,
+ ast::WhileExpr(expr) => expr.condition()? == *it,
+ ast::MatchGuard(guard) => guard.condition()? == *it,
+ ast::BinExpr(bin_expr) => (bin_expr.op_token()?.kind() == T![&&])
+ .then(|| is_in_condition(&bin_expr.into()))?,
+ _ => return None,
+ } })
+ })
+ .unwrap_or(false)
+}
+
#[cfg(test)]
mod tests {
use expect_test::expect;
@@ -650,6 +662,38 @@ fn main() {
}
"#,
);
+ check_edit(
+ "let",
+ r#"
+//- minicore: option
+fn main() {
+ let bar = Some(true);
+ if true && bar.$0
+}
+"#,
+ r#"
+fn main() {
+ let bar = Some(true);
+ if true && let Some($0) = bar
+}
+"#,
+ );
+ check_edit(
+ "let",
+ r#"
+//- minicore: option
+fn main() {
+ let bar = Some(true);
+ if true && true && bar.$0
+}
+"#,
+ r#"
+fn main() {
+ let bar = Some(true);
+ if true && true && let Some($0) = bar
+}
+"#,
+ );
}
#[test]