Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22645 from A4-Tacks/diag-add-await
feat: add fixes add '.await' for type_mismatch
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/type_mismatch.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 5a1856c89d..da6fc20c3e 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -74,6 +74,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::TypeMismatch<'_>) -> Option< remove_unnecessary_wrapper(ctx, d, expr_ptr, &mut fixes); remove_semicolon(ctx, d, expr_ptr, &mut fixes); str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); + add_await(ctx, d, expr_ptr, &mut fixes); } if fixes.is_empty() { None } else { Some(fixes) } @@ -377,6 +378,30 @@ fn str_ref_to_owned( Some(()) } +fn add_await( + ctx: &DiagnosticsContext<'_, '_>, + d: &hir::TypeMismatch<'_>, + expr_ptr: &InFile<AstPtr<ast::Expr>>, + acc: &mut Vec<Assist>, +) -> Option<()> { + let output = d.actual.clone().future_output(ctx.db())?; + // XXX: maybe should check if ctx is async + let is_applicable = output.could_coerce_to(ctx.db(), &d.expected); + if !is_applicable { + return None; + } + + let root = ctx.db().parse_or_expand(expr_ptr.file_id); + let expr = expr_ptr.value.to_node(&root); + let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?; + + let edit = TextEdit::insert(range.end(), ".await".to_owned()); + let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.db()), edit); + acc.push(fix("add_await", "Add .await here", source_change, range)); + + Some(()) +} + #[cfg(test)] mod tests { use crate::tests::{ @@ -1395,6 +1420,47 @@ identity! { } #[test] + fn add_await() { + check_fix( + r#" +//- minicore: future +async fn foo() -> u32 { 2 } +async fn test() { + let x: u32 = foo()$0; +} + "#, + r#" +async fn foo() -> u32 { 2 } +async fn test() { + let x: u32 = foo().await; +} + "#, + ); + + check_fix( + r#" +//- minicore: future +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +async fn foo() -> u32 { 2 } +identity! { + async fn test() { + let x: u32 = foo()$0; + } +} + "#, + r#" +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +async fn foo() -> u32 { 2 } +identity! { + async fn test() { + let x: u32 = foo().await; + } +} + "#, + ); + } + + #[test] fn type_mismatch_range_adjustment() { cov_mark::check!(type_mismatch_range_adjustment); check_diagnostics( |