Support else completion for more expressions
- Support else completion in ArrayExpr, ReturnExpr and PrefixExpr etc
- Support else completion after MatchArm expression
Before this PR, the else branch could not be completed in most expressions
Example
---
```rust
fn foo() -> [i32; 1] {
[if true {
2
} $0]
}
```
->
```rust
fn foo() -> [i32; 1] {
[if true {
2
} else {
$0
}]
}
```
---
```rust
fn foo() -> i32 {
match () {
() => if true {
2
} $0
}
}
```
->
```rust
fn foo() -> i32 {
match () {
() => if true {
2
} else {
$0
}
}
}
```
This commit is contained in:
parent
6e397d3cd5
commit
76b7c79e32
4 changed files with 312 additions and 5 deletions
|
|
@ -42,6 +42,11 @@ pub(crate) fn complete_pattern(
|
|||
}
|
||||
}
|
||||
|
||||
if pattern_ctx.after_if_expr {
|
||||
add_keyword("else", "else {\n $0\n}");
|
||||
add_keyword("else if", "else if $1 {\n $0\n}");
|
||||
}
|
||||
|
||||
if pattern_ctx.record_pat.is_some() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ pub(crate) struct PatternContext {
|
|||
pub(crate) param_ctx: Option<ParamContext>,
|
||||
pub(crate) has_type_ascription: bool,
|
||||
pub(crate) should_suggest_name: bool,
|
||||
pub(crate) after_if_expr: bool,
|
||||
pub(crate) parent_pat: Option<ast::Pat>,
|
||||
pub(crate) ref_token: Option<SyntaxToken>,
|
||||
pub(crate) mut_token: Option<SyntaxToken>,
|
||||
|
|
|
|||
|
|
@ -999,10 +999,6 @@ fn classify_name_ref<'db>(
|
|||
}
|
||||
}
|
||||
};
|
||||
let after_if_expr = |node: SyntaxNode| {
|
||||
let prev_expr = prev_expr(node);
|
||||
matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
|
||||
};
|
||||
let after_incomplete_let = |node: SyntaxNode| {
|
||||
prev_expr(node).and_then(|it| it.syntax().parent()).and_then(ast::LetStmt::cast)
|
||||
};
|
||||
|
|
@ -1242,7 +1238,7 @@ fn classify_name_ref<'db>(
|
|||
let it = expr.syntax();
|
||||
let in_block_expr = is_in_block(it);
|
||||
let (in_loop_body, innermost_breakable) = is_in_breakable(it).unzip();
|
||||
let after_if_expr = after_if_expr(it.clone());
|
||||
let after_if_expr = is_after_if_expr(it.clone());
|
||||
let ref_expr_parent =
|
||||
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
|
||||
let after_amp = non_trivia_sibling(it.clone().into(), Direction::Prev)
|
||||
|
|
@ -1763,6 +1759,7 @@ fn pattern_context_for(
|
|||
param_ctx,
|
||||
has_type_ascription,
|
||||
should_suggest_name,
|
||||
after_if_expr: is_after_if_expr(pat.syntax().clone()),
|
||||
parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
|
||||
mut_token,
|
||||
ref_token,
|
||||
|
|
@ -1933,6 +1930,18 @@ fn has_in_newline_expr_first(node: &SyntaxNode) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_after_if_expr(node: SyntaxNode) -> bool {
|
||||
let node = match node.parent().and_then(Either::<ast::ExprStmt, ast::MatchArm>::cast) {
|
||||
Some(stmt) => stmt.syntax().clone(),
|
||||
None => node,
|
||||
};
|
||||
let prev_sibling =
|
||||
non_trivia_sibling(node.into(), Direction::Prev).and_then(NodeOrToken::into_node);
|
||||
iter::successors(prev_sibling, |it| it.last_child_or_token()?.into_node())
|
||||
.find_map(ast::IfExpr::cast)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn next_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
|
||||
let mut token = match e.into() {
|
||||
SyntaxElement::Node(n) => n.last_token()?,
|
||||
|
|
|
|||
|
|
@ -1869,6 +1869,298 @@ fn foo() { let x = if foo {} $0 else if true {} else {}; }
|
|||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { [if foo {} $0]}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { [if foo {} el$0]}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { 2 + if foo {} $0 }
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { -if foo {} $0 }
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { &mut if foo {} $0 }
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { return if foo {} $0 }
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { match () { () => if foo {} $0 } }
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw else
|
||||
kw else if
|
||||
kw mut
|
||||
kw ref
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { match () { () => if foo {} $0, } }
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw else
|
||||
kw else if
|
||||
kw mut
|
||||
kw ref
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo() { match () { () => if foo {} $0, _ => (), } }
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw else
|
||||
kw else if
|
||||
kw mut
|
||||
kw ref
|
||||
"#]],
|
||||
);
|
||||
// FIXME: support else completion after ast::RecordExprField
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue