Unnamed repository; edit this file 'description' to name the repository.
Review fixes: Assist scope, trait qualify
maxwase 2024-05-24
parent 624f99b · commit 61f8ef5
-rw-r--r--crates/ide-assists/src/handlers/toggle_async_sugar.rs164
-rw-r--r--crates/ide-assists/src/tests/generated.rs7
2 files changed, 126 insertions, 45 deletions
diff --git a/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/crates/ide-assists/src/handlers/toggle_async_sugar.rs
index 356e1d50ae..30e09648ea 100644
--- a/crates/ide-assists/src/handlers/toggle_async_sugar.rs
+++ b/crates/ide-assists/src/handlers/toggle_async_sugar.rs
@@ -1,3 +1,4 @@
+use hir::{ImportPathConfig, ModuleDef};
use ide_db::{
assists::{AssistId, AssistKind},
famous_defs::FamousDefs,
@@ -11,13 +12,13 @@ use crate::{AssistContext, Assists};
// Assist: sugar_impl_future_into_async
//
-// Rewrites asynchronous function from `impl Future` to `async fn`.
+// Rewrites asynchronous function from `-> impl Future` into `async fn`.
// This action does not touch the function body and therefore `async { 0 }`
// block does not transform to just `0`.
//
// ```
// # //- minicore: future
-// pub f$0n foo() -> impl core::future::Future<Output = usize> {
+// pub fn foo() -> impl core::future::F$0uture<Output = usize> {
// async { 0 }
// }
// ```
@@ -31,13 +32,10 @@ pub(crate) fn sugar_impl_future_into_async(
acc: &mut Assists,
ctx: &AssistContext<'_>,
) -> Option<()> {
- let function: ast::Fn = ctx.find_node_at_offset()?;
- if function.async_token().is_some() {
- return None;
- }
+ let ret_type: ast::RetType = ctx.find_node_at_offset()?;
+ let function = ret_type.syntax().parent().and_then(ast::Fn::cast)?;
- let ret_type = function.ret_type()?;
- if function.const_token().is_some() {
+ if function.async_token().is_some() || function.const_token().is_some() {
return None;
}
@@ -67,6 +65,7 @@ pub(crate) fn sugar_impl_future_into_async(
function.syntax().text_range(),
|builder| {
match future_output {
+ // Empty tuple
ast::Type::TupleType(t) if t.fields().next().is_none() => {
let mut ret_type_range = ret_type.syntax().text_range();
@@ -103,18 +102,19 @@ pub(crate) fn sugar_impl_future_into_async(
// Assist: desugar_async_into_impl_future
//
-// Rewrites asynchronous function from `async fn` to `impl Future`.
+// Rewrites asynchronous function from `async fn` into `-> 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 {
+// # //- minicore: future
+// pub as$0ync fn foo() -> usize {
// 0
// }
// ```
// ->
// ```
-// pub fn foo() -> impl Future<Output = usize> {
+// pub fn foo() -> impl core::future::Future<Output = usize> {
// 0
// }
// ```
@@ -122,8 +122,8 @@ pub(crate) fn desugar_async_into_impl_future(
acc: &mut Assists,
ctx: &AssistContext<'_>,
) -> Option<()> {
- let function: ast::Fn = ctx.find_node_at_offset()?;
- let async_token = function.async_token()?;
+ let async_token = ctx.find_token_syntax_at_offset(SyntaxKind::ASYNC_KW)?;
+ let function = async_token.parent().and_then(ast::Fn::cast)?;
let rparen = function.param_list()?.r_paren_token()?;
let return_type = match function.ret_type() {
@@ -133,6 +133,19 @@ pub(crate) fn desugar_async_into_impl_future(
None => None,
};
+ let scope = ctx.sema.scope(function.syntax())?;
+ let module = scope.module();
+ let future_trait = FamousDefs(&ctx.sema, scope.krate()).core_future_Future()?;
+ let trait_path = module.find_path(
+ ctx.db(),
+ ModuleDef::Trait(future_trait),
+ ImportPathConfig {
+ prefer_no_std: ctx.config.prefer_no_std,
+ prefer_prelude: ctx.config.prefer_prelude,
+ },
+ )?;
+ let trait_path = trait_path.display(ctx.db());
+
acc.add(
AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite),
"Convert async into `impl Future`",
@@ -148,9 +161,12 @@ pub(crate) fn desugar_async_into_impl_future(
match return_type {
Some(ret_type) => builder.replace(
ret_type.syntax().text_range(),
- format!("impl Future<Output = {ret_type}>"),
+ format!("impl {trait_path}<Output = {ret_type}>"),
+ ),
+ None => builder.insert(
+ rparen.text_range().end(),
+ format!(" -> impl {trait_path}<Output = ()>"),
),
- None => builder.insert(rparen.text_range().end(), " -> impl Future<Output = ()>"),
}
},
)
@@ -186,7 +202,7 @@ mod tests {
r#"
//- minicore: future
use core::future::Future;
- f$0n foo() -> impl Future<Output = ()> {
+ fn foo() -> impl F$0uture<Output = ()> {
todo!()
}
"#,
@@ -203,7 +219,7 @@ mod tests {
r#"
//- minicore: future
use core::future::Future;
- f$0n foo() -> impl Future<Output = usize> {
+ fn foo() -> impl F$0uture<Output = usize> {
todo!()
}
"#,
@@ -223,7 +239,7 @@ mod tests {
r#"
//- minicore: future
use core::future::Future;
- async f$0n foo() {
+ as$0ync fn foo() {
todo!()
}
"#,
@@ -239,8 +255,25 @@ mod tests {
desugar_async_into_impl_future,
r#"
//- minicore: future
+ use core::future;
+ as$0ync fn foo() {
+ todo!()
+ }
+ "#,
+ r#"
+ use core::future;
+ fn foo() -> impl future::Future<Output = ()> {
+ todo!()
+ }
+ "#,
+ );
+
+ check_assist(
+ desugar_async_into_impl_future,
+ r#"
+ //- minicore: future
use core::future::Future;
- async f$0n foo() -> usize {
+ as$0ync fn foo() -> usize {
todo!()
}
"#,
@@ -251,6 +284,23 @@ mod tests {
}
"#,
);
+
+ check_assist(
+ desugar_async_into_impl_future,
+ r#"
+ //- minicore: future
+ use core::future::Future;
+ as$0ync fn foo() -> impl Future<Output = usize> {
+ todo!()
+ }
+ "#,
+ r#"
+ use core::future::Future;
+ fn foo() -> impl Future<Output = impl Future<Output = usize>> {
+ todo!()
+ }
+ "#,
+ );
}
#[test]
@@ -259,7 +309,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = ()> {
+ fn foo() -> impl core::future::F$0uture<Output = ()> {
todo!()
}
"#,
@@ -274,7 +324,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = usize> {
+ fn foo() -> impl core::future::F$0uture<Output = usize> {
todo!()
}
"#,
@@ -292,12 +342,12 @@ mod tests {
desugar_async_into_impl_future,
r#"
//- minicore: future
- async f$0n foo() {
+ as$0ync fn foo() {
todo!()
}
"#,
r#"
- fn foo() -> impl Future<Output = ()> {
+ fn foo() -> impl core::future::Future<Output = ()> {
todo!()
}
"#,
@@ -307,12 +357,12 @@ mod tests {
desugar_async_into_impl_future,
r#"
//- minicore: future
- async f$0n foo() -> usize {
+ as$0ync fn foo() -> usize {
todo!()
}
"#,
r#"
- fn foo() -> impl Future<Output = usize> {
+ fn foo() -> impl core::future::Future<Output = usize> {
todo!()
}
"#,
@@ -320,7 +370,7 @@ mod tests {
}
#[test]
- fn sugar_not_applicable() {
+ fn not_applicable() {
check_assist_not_applicable(
sugar_impl_future_into_async,
r#"
@@ -328,7 +378,7 @@ mod tests {
trait Future {
type Output;
}
- f$0n foo() -> impl Future<Output = ()> {
+ fn foo() -> impl F$0uture<Output = ()> {
todo!()
}
"#,
@@ -341,7 +391,26 @@ mod tests {
trait Future {
type Output;
}
- f$0n foo() -> impl Future<Output = usize> {
+ fn foo() -> impl F$0uture<Output = usize> {
+ todo!()
+ }
+ "#,
+ );
+
+ check_assist_not_applicable(
+ sugar_impl_future_into_async,
+ r#"
+ //- minicore: future
+ f$0n foo() -> impl core::future::Future<Output = usize> {
+ todo!()
+ }
+ "#,
+ );
+
+ check_assist_not_applicable(
+ desugar_async_into_impl_future,
+ r#"
+ async f$0n foo() {
todo!()
}
"#,
@@ -355,7 +424,7 @@ mod tests {
r#"
//- minicore: future
use core::future::Future;
- f$0n foo() -> impl Future<Output = ()>;
+ fn foo() -> impl F$0uture<Output = ()>;
"#,
r#"
use core::future::Future;
@@ -368,7 +437,7 @@ mod tests {
r#"
//- minicore: future
use core::future::Future;
- f$0n foo() -> impl Future<Output = usize>;
+ fn foo() -> impl F$0uture<Output = usize>;
"#,
r#"
use core::future::Future;
@@ -383,7 +452,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = ()>;
+ fn foo() -> impl core::future::F$0uture<Output = ()>;
"#,
r#"
async fn foo();
@@ -394,7 +463,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = usize>;
+ fn foo() -> impl core::future::F$0uture<Output = usize>;
"#,
r#"
async fn foo() -> usize;
@@ -408,7 +477,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = ()> + Send + Sync;
+ fn foo() -> impl core::future::F$0uture<Output = ()> + Send + Sync;
"#,
r#"
async fn foo();
@@ -419,7 +488,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = usize> + Debug;
+ fn foo() -> impl core::future::F$0uture<Output = usize> + Debug;
"#,
r#"
async fn foo() -> usize;
@@ -430,7 +499,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = (usize)> + Debug;
+ fn foo() -> impl core::future::F$0uture<Output = (usize)> + Debug;
"#,
r#"
async fn foo() -> (usize);
@@ -441,12 +510,23 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo() -> impl core::future::Future<Output = (usize, usize)> + Debug;
+ fn foo() -> impl core::future::F$0uture<Output = (usize, usize)> + Debug;
"#,
r#"
async fn foo() -> (usize, usize);
"#,
);
+
+ check_assist(
+ sugar_impl_future_into_async,
+ r#"
+ //- minicore: future
+ fn foo() -> impl core::future::Future<Output = impl core::future::F$0uture<Output = ()> + Send>;
+ "#,
+ r#"
+ async fn foo() -> impl core::future::Future<Output = ()> + Send;
+ "#,
+ );
}
#[test]
@@ -455,7 +535,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- const f$0n foo() -> impl core::future::Future<Output = ()>;
+ const fn foo() -> impl core::future::F$0uture<Output = ()>;
"#,
);
@@ -463,7 +543,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- pub(crate) unsafe f$0n foo() -> impl core::future::Future<Output = usize>;
+ pub(crate) unsafe fn foo() -> impl core::future::F$0uture<Output = usize>;
"#,
r#"
pub(crate) async unsafe fn foo() -> usize;
@@ -474,7 +554,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- unsafe f$0n foo() -> impl core::future::Future<Output = ()>;
+ unsafe fn foo() -> impl core::future::F$0uture<Output = ()>;
"#,
r#"
async unsafe fn foo();
@@ -485,7 +565,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- unsafe extern "C" f$0n foo() -> impl core::future::Future<Output = ()>;
+ unsafe extern "C" fn foo() -> impl core::future::F$0uture<Output = ()>;
"#,
r#"
async unsafe extern "C" fn foo();
@@ -496,7 +576,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo<T>() -> impl core::future::Future<Output = T>;
+ fn foo<T>() -> impl core::future::F$0uture<Output = T>;
"#,
r#"
async fn foo<T>() -> T;
@@ -507,7 +587,7 @@ mod tests {
sugar_impl_future_into_async,
r#"
//- minicore: future
- f$0n foo<T>() -> impl core::future::Future<Output = T>
+ fn foo<T>() -> impl core::future::F$0uture<Output = T>
where
T: Sized;
"#,
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 5f187880b0..94d9e5edef 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -805,12 +805,13 @@ fn doctest_desugar_async_into_impl_future() {
check_doc_test(
"desugar_async_into_impl_future",
r#####"
-pub async f$0n foo() -> usize {
+//- minicore: future
+pub as$0ync fn foo() -> usize {
0
}
"#####,
r#####"
-pub fn foo() -> impl Future<Output = usize> {
+pub fn foo() -> impl core::future::Future<Output = usize> {
0
}
"#####,
@@ -3043,7 +3044,7 @@ fn doctest_sugar_impl_future_into_async() {
"sugar_impl_future_into_async",
r#####"
//- minicore: future
-pub f$0n foo() -> impl core::future::Future<Output = usize> {
+pub fn foo() -> impl core::future::F$0uture<Output = usize> {
async { 0 }
}
"#####,