Skip to content

Commit bd08e2e

Browse files
Merge pull request #20381 from A4-Tacks/fix-assign-sug
Add assignment type analysis for ide-completion
2 parents 2e283c1 + bfbeddf commit bd08e2e

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
@@ -559,6 +559,7 @@ fn expected_type_and_name<'db>(
559559
token: &SyntaxToken,
560560
name_like: &ast::NameLike,
561561
) -> (Option<Type<'db>>, Option<NameOrNameRef>) {
562+
let token = prev_assign_token_at_trivia(token.clone());
562563
let mut node = match token.parent() {
563564
Some(it) => it,
564565
None => return (None, None),
@@ -629,6 +630,17 @@ fn expected_type_and_name<'db>(
629630
.map(TypeInfo::original);
630631
(ty, None)
631632
},
633+
ast::BinExpr(it) => {
634+
if let Some(ast::BinaryOp::Assignment { op: None }) = it.op_kind() {
635+
let ty = it.lhs()
636+
.and_then(|lhs| sema.type_of_expr(&lhs))
637+
.or_else(|| it.rhs().and_then(|rhs| sema.type_of_expr(&rhs)))
638+
.map(TypeInfo::original);
639+
(ty, None)
640+
} else {
641+
(None, None)
642+
}
643+
},
632644
ast::ArgList(_) => {
633645
cov_mark::hit!(expected_type_fn_param);
634646
ActiveParameter::at_token(
@@ -1856,3 +1868,23 @@ fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
18561868
}
18571869
None
18581870
}
1871+
1872+
fn prev_assign_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken {
1873+
while token.kind().is_trivia()
1874+
&& let Some(prev) = token.prev_token()
1875+
&& let T![=]
1876+
| T![+=]
1877+
| T![/=]
1878+
| T![*=]
1879+
| T![%=]
1880+
| T![>>=]
1881+
| T![<<=]
1882+
| T![-=]
1883+
| T![|=]
1884+
| T![&=]
1885+
| T![^=] = prev.kind()
1886+
{
1887+
token = prev
1888+
}
1889+
token
1890+
}

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)