Skip to content

Commit 22d6136

Browse files
committed
Add assignment type analysis for ide-completion
1 parent 922e04a commit 22d6136

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

crates/ide-completion/src/context/analysis.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ fn expected_type_and_name<'db>(
562562
token: &SyntaxToken,
563563
name_like: &ast::NameLike,
564564
) -> (Option<Type<'db>>, Option<NameOrNameRef>) {
565+
let token = prev_assign_token_at_whitespace(token.clone());
565566
let mut node = match token.parent() {
566567
Some(it) => it,
567568
None => return (None, None),
@@ -632,6 +633,17 @@ fn expected_type_and_name<'db>(
632633
.map(TypeInfo::original);
633634
(ty, None)
634635
},
636+
ast::BinExpr(it) => {
637+
if let Some(ast::BinaryOp::Assignment { op: None }) = it.op_kind() {
638+
let ty = it.lhs()
639+
.and_then(|lhs| sema.type_of_expr(&lhs))
640+
.or_else(|| it.rhs().and_then(|rhs| sema.type_of_expr(&rhs)))
641+
.map(TypeInfo::original);
642+
(ty, None)
643+
} else {
644+
(None, None)
645+
}
646+
},
635647
ast::ArgList(_) => {
636648
cov_mark::hit!(expected_type_fn_param);
637649
ActiveParameter::at_token(
@@ -1870,3 +1882,23 @@ fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
18701882
}
18711883
None
18721884
}
1885+
1886+
fn prev_assign_token_at_whitespace(mut token: SyntaxToken) -> SyntaxToken {
1887+
while token.kind() == SyntaxKind::WHITESPACE
1888+
&& let Some(prev) = token.prev_token()
1889+
&& let T![=]
1890+
| T![+=]
1891+
| T![/=]
1892+
| T![*=]
1893+
| T![%=]
1894+
| T![>>=]
1895+
| T![<<=]
1896+
| T![-=]
1897+
| T![|=]
1898+
| T![&=]
1899+
| T![^=] = prev.kind()
1900+
{
1901+
token = prev
1902+
}
1903+
token
1904+
}

crates/ide-completion/src/context/tests.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,53 @@ fn f(thing: u32) -> &u32 {
434434
expect!["ty: u32, name: ?"],
435435
);
436436
}
437+
438+
#[test]
439+
fn expected_type_assign() {
440+
check_expected_type_and_name(
441+
r#"
442+
enum State { Stop }
443+
fn foo() {
444+
let x: &mut State = &mut State::Stop;
445+
x = $0;
446+
}
447+
"#,
448+
expect![[r#"ty: &'_ mut State, name: ?"#]],
449+
);
450+
}
451+
452+
#[test]
453+
fn expected_type_deref_assign() {
454+
check_expected_type_and_name(
455+
r#"
456+
enum State { Stop }
457+
fn foo() {
458+
let x: &mut State = &mut State::Stop;
459+
match x {
460+
State::Stop => {
461+
*x = $0;
462+
},
463+
}
464+
}
465+
"#,
466+
expect![[r#"ty: State, name: ?"#]],
467+
);
468+
}
469+
470+
#[test]
471+
fn expected_type_deref_assign_at_block_end() {
472+
check_expected_type_and_name(
473+
r#"
474+
enum State { Stop }
475+
fn foo() {
476+
let x: &mut State = &mut State::Stop;
477+
match x {
478+
State::Stop => {
479+
*x = $0
480+
},
481+
}
482+
}
483+
"#,
484+
expect![[r#"ty: State, name: ?"#]],
485+
);
486+
}

0 commit comments

Comments
 (0)