about summary refs log tree commit diff
diff options
context:
space:
mode:
authormaxwase <max.vvase@gmail.com>2024-05-24 01:10:18 +0300
committermaxwase <max.vvase@gmail.com>2024-05-24 01:10:18 +0300
commit9cf35f1262c36dcd5c0f25a2875295df9e2ec856 (patch)
tree35440c74ef1daf51459b0b5c09d272f3e3539151
parent9244dbff769f7afc3a0b54d63e2ed0ade06c42cd (diff)
downloadrust-9cf35f1262c36dcd5c0f25a2875295df9e2ec856.tar.gz
rust-9cf35f1262c36dcd5c0f25a2875295df9e2ec856.zip
Review fixes: Split into 2, check tuple fields
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs161
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs30
3 files changed, 137 insertions, 57 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs
index ea127d65e54..356e1d50ae8 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs
@@ -9,42 +9,38 @@ use syntax::{
 
 use crate::{AssistContext, Assists};
 
-// Assist: toggle_async_sugar
+// Assist: sugar_impl_future_into_async
 //
-// Rewrites asynchronous function into `impl Future` and back.
+// Rewrites asynchronous function from `impl Future` to `async fn`.
 // This action does not touch the function body and therefore `async { 0 }`
 // block does not transform to just `0`.
 //
 // ```
-// pub async f$0n foo() -> usize {
-//     0
+// # //- minicore: future
+// pub f$0n foo() -> impl core::future::Future<Output = usize> {
+//     async { 0 }
 // }
 // ```
 // ->
 // ```
-// pub fn foo() -> impl Future<Output = usize> {
-//     0
+// pub async fn foo() -> usize {
+//     async { 0 }
 // }
 // ```
-pub(crate) fn toggle_async_sugar(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let function: ast::Fn = ctx.find_node_at_offset()?;
-    match (function.async_token(), function.ret_type()) {
-        // async function returning futures cannot be flattened
-        // const async is not yet supported
-        (None, Some(ret_type)) if function.const_token().is_none() => {
-            add_async(acc, ctx, function, ret_type)
-        }
-        (Some(async_token), ret_type) => remove_async(function, ret_type, acc, async_token),
-        _ => None,
-    }
-}
-
-fn add_async(
+pub(crate) fn sugar_impl_future_into_async(
     acc: &mut Assists,
     ctx: &AssistContext<'_>,
-    function: ast::Fn,
-    ret_type: ast::RetType,
 ) -> Option<()> {
+    let function: ast::Fn = ctx.find_node_at_offset()?;
+    if function.async_token().is_some() {
+        return None;
+    }
+
+    let ret_type = function.ret_type()?;
+    if function.const_token().is_some() {
+        return None;
+    }
+
     let ast::Type::ImplTraitType(return_impl_trait) = ret_type.ty()? else {
         return None;
     };
@@ -66,12 +62,12 @@ fn add_async(
     let future_output = unwrap_future_output(main_trait_path)?;
 
     acc.add(
-        AssistId("toggle_async_sugar", AssistKind::RefactorRewrite),
+        AssistId("sugar_impl_future_into_async", AssistKind::RefactorRewrite),
         "Convert `impl Future` into async",
         function.syntax().text_range(),
         |builder| {
             match future_output {
-                ast::Type::TupleType(_) => {
+                ast::Type::TupleType(t) if t.fields().next().is_none() => {
                     let mut ret_type_range = ret_type.syntax().text_range();
 
                     // find leftover whitespace
@@ -105,14 +101,32 @@ fn add_async(
     )
 }
 
-fn remove_async(
-    function: ast::Fn,
-    ret_type: Option<ast::RetType>,
+// Assist: desugar_async_into_impl_future
+//
+// Rewrites asynchronous function from `async fn` to `impl Future`.
+// This action does not touch the function body and therefore `0`
+// block does not transform to `async { 0 }`.
+//
+// ```
+// pub async f$0n foo() -> usize {
+//     0
+// }
+// ```
+// ->
+// ```
+// pub fn foo() -> impl Future<Output = usize> {
+//     0
+// }
+// ```
+pub(crate) fn desugar_async_into_impl_future(
     acc: &mut Assists,
-    async_token: SyntaxToken,
+    ctx: &AssistContext<'_>,
 ) -> Option<()> {
+    let function: ast::Fn = ctx.find_node_at_offset()?;
+    let async_token = function.async_token()?;
+
     let rparen = function.param_list()?.r_paren_token()?;
-    let return_type = match ret_type {
+    let return_type = match function.ret_type() {
         // unable to get a `ty` makes the action unapplicable
         Some(ret_type) => Some(ret_type.ty()?),
         // No type means `-> ()`
@@ -120,7 +134,7 @@ fn remove_async(
     };
 
     acc.add(
-        AssistId("toggle_async_sugar", AssistKind::RefactorRewrite),
+        AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite),
         "Convert async into `impl Future`",
         function.syntax().text_range(),
         |builder| {
@@ -168,7 +182,7 @@ mod tests {
     #[test]
     fn sugar_with_use() {
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -185,7 +199,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -205,7 +219,7 @@ mod tests {
     #[test]
     fn desugar_with_use() {
         check_assist(
-            toggle_async_sugar,
+            desugar_async_into_impl_future,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -222,7 +236,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            desugar_async_into_impl_future,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -242,7 +256,7 @@ mod tests {
     #[test]
     fn sugar_without_use() {
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo() -> impl core::future::Future<Output = ()> {
@@ -257,7 +271,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo() -> impl core::future::Future<Output = usize> {
@@ -275,7 +289,7 @@ mod tests {
     #[test]
     fn desugar_without_use() {
         check_assist(
-            toggle_async_sugar,
+            desugar_async_into_impl_future,
             r#"
     //- minicore: future
     async f$0n foo() {
@@ -290,7 +304,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            desugar_async_into_impl_future,
             r#"
     //- minicore: future
     async f$0n foo() -> usize {
@@ -308,7 +322,7 @@ mod tests {
     #[test]
     fn sugar_not_applicable() {
         check_assist_not_applicable(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     trait Future {
@@ -321,7 +335,7 @@ mod tests {
         );
 
         check_assist_not_applicable(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     trait Future {
@@ -337,7 +351,7 @@ mod tests {
     #[test]
     fn sugar_definition_with_use() {
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -350,7 +364,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     use core::future::Future;
@@ -366,7 +380,7 @@ mod tests {
     #[test]
     fn sugar_definition_without_use() {
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo() -> impl core::future::Future<Output = ()>;
@@ -377,7 +391,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo() -> impl core::future::Future<Output = usize>;
@@ -389,9 +403,56 @@ mod tests {
     }
 
     #[test]
+    fn sugar_more_types() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    f$0n foo() -> impl core::future::Future<Output = ()> + Send + Sync;
+    "#,
+            r#"
+    async fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    f$0n foo() -> impl core::future::Future<Output = usize> + Debug;
+    "#,
+            r#"
+    async fn foo() -> usize;
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    f$0n foo() -> impl core::future::Future<Output = (usize)> + Debug;
+    "#,
+            r#"
+    async fn foo() -> (usize);
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    f$0n foo() -> impl core::future::Future<Output = (usize, usize)> + Debug;
+    "#,
+            r#"
+    async fn foo() -> (usize, usize);
+    "#,
+        );
+    }
+
+    #[test]
     fn sugar_with_modifiers() {
         check_assist_not_applicable(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     const f$0n foo() -> impl core::future::Future<Output = ()>;
@@ -399,7 +460,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
             //- minicore: future
             pub(crate) unsafe f$0n foo() -> impl core::future::Future<Output = usize>;
@@ -410,7 +471,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     unsafe f$0n foo() -> impl core::future::Future<Output = ()>;
@@ -421,7 +482,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     unsafe extern "C" f$0n foo() -> impl core::future::Future<Output = ()>;
@@ -432,7 +493,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo<T>() -> impl core::future::Future<Output = T>;
@@ -443,7 +504,7 @@ mod tests {
         );
 
         check_assist(
-            toggle_async_sugar,
+            sugar_impl_future_into_async,
             r#"
     //- minicore: future
     f$0n foo<T>() -> impl core::future::Future<Output = T>
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index d26ac23099a..34ef341c446 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -239,7 +239,8 @@ mod handlers {
             change_visibility::change_visibility,
             convert_bool_then::convert_bool_then_to_if,
             convert_bool_then::convert_if_to_bool_then,
-            toggle_async_sugar::toggle_async_sugar,
+            toggle_async_sugar::desugar_async_into_impl_future,
+            toggle_async_sugar::sugar_impl_future_into_async,
             convert_comment_block::convert_comment_block,
             convert_from_to_tryfrom::convert_from_to_tryfrom,
             convert_integer_literal::convert_integer_literal,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 8e0d1bd667a..5f187880b01 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -801,6 +801,23 @@ fn main() {
 }
 
 #[test]
+fn doctest_desugar_async_into_impl_future() {
+    check_doc_test(
+        "desugar_async_into_impl_future",
+        r#####"
+pub async f$0n foo() -> usize {
+    0
+}
+"#####,
+        r#####"
+pub fn foo() -> impl Future<Output = usize> {
+    0
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_desugar_doc_comment() {
     check_doc_test(
         "desugar_doc_comment",
@@ -3021,17 +3038,18 @@ use std::{collections::HashMap};
 }
 
 #[test]
-fn doctest_toggle_async_sugar() {
+fn doctest_sugar_impl_future_into_async() {
     check_doc_test(
-        "toggle_async_sugar",
+        "sugar_impl_future_into_async",
         r#####"
-pub async f$0n foo() -> usize {
-    0
+//- minicore: future
+pub f$0n foo() -> impl core::future::Future<Output = usize> {
+    async { 0 }
 }
 "#####,
         r#####"
-pub fn foo() -> impl Future<Output = usize> {
-    0
+pub async fn foo() -> usize {
+    async { 0 }
 }
 "#####,
     )