Review fixes: Split into 2, check tuple fields

This commit is contained in:
maxwase 2024-05-24 01:10:18 +03:00
parent 2657078573
commit 624f99b4b9
3 changed files with 137 additions and 57 deletions

View file

@ -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>;
@ -388,10 +402,57 @@ 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>

View file

@ -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,

View file

@ -800,6 +800,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(
@ -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 }
}
"#####,
)