Review fixes: Assist scope, trait qualify

This commit is contained in:
maxwase 2024-05-24 01:39:46 +03:00
parent 624f99b4b9
commit 61f8ef5d57
2 changed files with 126 additions and 45 deletions

View file

@ -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!()
}
"#,
@ -249,6 +282,23 @@ mod tests {
fn foo() -> impl Future<Output = usize> {
todo!()
}
"#,
);
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!()
}
"#,
);
}
@ -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,10 +510,21 @@ 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;
"#,
);
}
@ -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;
"#,

View file

@ -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 }
}
"#####,