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
Chayim Refael Friedman 3 weeks ago
parent a775481 · parent 9051723 · commit 5d15d9f
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs66
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(