mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-31 15:47:31 +00:00
Add .let postfix completion in let-chain support
This commit is contained in:
parent
db7b3b1b91
commit
afbecea5e9
2 changed files with 63 additions and 33 deletions
|
@ -11,11 +11,10 @@ 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},
|
||||
};
|
||||
|
||||
|
@ -113,12 +112,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 +142,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};"))
|
||||
|
@ -454,6 +449,24 @@ fn add_custom_postfix_completions(
|
|||
None
|
||||
}
|
||||
|
||||
pub(crate) fn is_in_condition(it: &ast::Expr) -> bool {
|
||||
(|| {
|
||||
let parent = it.syntax().parent()?;
|
||||
if let Some(expr) = ast::WhileExpr::cast(parent.clone()) {
|
||||
Some(expr.condition()? == *it)
|
||||
} else if let Some(expr) = ast::IfExpr::cast(parent.clone()) {
|
||||
Some(expr.condition()? == *it)
|
||||
} else if let Some(expr) = ast::BinExpr::cast(parent)
|
||||
&& expr.op_token()?.kind() == T![&&]
|
||||
{
|
||||
Some(is_in_condition(&expr.into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})()
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use expect_test::expect;
|
||||
|
@ -648,6 +661,38 @@ fn main() {
|
|||
let bar = Some(true);
|
||||
if let Some($0) = bar
|
||||
}
|
||||
"#,
|
||||
);
|
||||
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
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,12 +19,15 @@ use syntax::{
|
|||
match_ast,
|
||||
};
|
||||
|
||||
use crate::context::{
|
||||
AttrCtx, BreakableKind, COMPLETION_MARKER, CompletionAnalysis, DotAccess, DotAccessExprCtx,
|
||||
DotAccessKind, ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind,
|
||||
NameRefContext, NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx, PathKind,
|
||||
PatternContext, PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget,
|
||||
TypeLocation,
|
||||
use crate::{
|
||||
completions::postfix::is_in_condition,
|
||||
context::{
|
||||
AttrCtx, BreakableKind, COMPLETION_MARKER, CompletionAnalysis, DotAccess, DotAccessExprCtx,
|
||||
DotAccessKind, ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind,
|
||||
NameRefContext, NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx,
|
||||
PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx,
|
||||
TypeAscriptionTarget, TypeLocation,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1188,24 +1191,6 @@ fn classify_name_ref<'db>(
|
|||
Some(res)
|
||||
};
|
||||
|
||||
fn is_in_condition(it: &ast::Expr) -> bool {
|
||||
(|| {
|
||||
let parent = it.syntax().parent()?;
|
||||
if let Some(expr) = ast::WhileExpr::cast(parent.clone()) {
|
||||
Some(expr.condition()? == *it)
|
||||
} else if let Some(expr) = ast::IfExpr::cast(parent.clone()) {
|
||||
Some(expr.condition()? == *it)
|
||||
} else if let Some(expr) = ast::BinExpr::cast(parent)
|
||||
&& expr.op_token()?.kind() == T![&&]
|
||||
{
|
||||
Some(is_in_condition(&expr.into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})()
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
let make_path_kind_expr = |expr: ast::Expr| {
|
||||
let it = expr.syntax();
|
||||
let in_block_expr = is_in_block(it);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue