From 4a7f5cac9dee32f3c8e43425339a2413b645bf39 Mon Sep 17 00:00:00 2001 From: koka Date: Sat, 29 Oct 2022 01:14:44 +0900 Subject: [PATCH 1/2] fix: async trait method for `unnecessary_async` --- .../src/handlers/unnecessary_async.rs | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/unnecessary_async.rs b/crates/ide-assists/src/handlers/unnecessary_async.rs index d5cd2d55134..44f8dbdef35 100644 --- a/crates/ide-assists/src/handlers/unnecessary_async.rs +++ b/crates/ide-assists/src/handlers/unnecessary_async.rs @@ -1,12 +1,14 @@ +use hir::AssocItem; use ide_db::{ assists::{AssistId, AssistKind}, base_db::FileId, defs::Definition, search::FileReference, syntax_helpers::node_ext::full_path_of_name_ref, + traits::resolve_target_trait, }; use syntax::{ - ast::{self, NameLike, NameRef}, + ast::{self, HasName, NameLike, NameRef}, AstNode, SyntaxKind, TextRange, }; @@ -44,7 +46,16 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() { return None; } - + // Do nothing if the method is an async member of trait. + if let Some(fname) = function.name() { + if let Some(trait_item) = find_corresponding_trait_member(ctx, fname.to_string()) { + if let AssocItem::Function(method) = trait_item { + if method.is_async(ctx.db()) { + return None; + } + } + } + } // Remove the `async` keyword plus whitespace after it, if any. let async_range = { let async_token = function.async_token()?; @@ -88,6 +99,23 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O ) } +fn find_corresponding_trait_member( + ctx: &AssistContext<'_>, + function_name: String, +) -> Option { + let impl_ = ctx.find_node_at_offset::()?; + let trait_ = resolve_target_trait(&ctx.sema, &impl_)?; + + trait_ + .items(ctx.db()) + .iter() + .find(|item| match item.name(ctx.db()) { + Some(method_name) => method_name.to_string() == function_name, + _ => false, + }) + .cloned() +} + fn find_all_references( ctx: &AssistContext<'_>, def: &Definition, @@ -254,4 +282,39 @@ pub async fn f(s: &S) { s.f2() }"#, fn does_not_apply_when_not_on_prototype() { check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }") } + + #[test] + fn applies_on_unnecessary_async_on_trait_method() { + check_assist( + unnecessary_async, + r#" +trait Trait { + fn foo(); +} +impl Trait for () { + $0async fn foo() {} +}"#, + r#" +trait Trait { + fn foo(); +} +impl Trait for () { + fn foo() {} +}"#, + ); + } + + #[test] + fn does_not_apply_on_async_trait_method() { + check_assist_not_applicable( + unnecessary_async, + r#" +trait Trait { + async fn foo(); +} +impl Trait for () { + $0async fn foo() {} +}"#, + ); + } } From cf90e4f32b677ac1cea2a14d1d041c0c0cb3db28 Mon Sep 17 00:00:00 2001 From: koka Date: Sun, 30 Oct 2022 00:57:42 +0900 Subject: [PATCH 2/2] Simplify the procedure fix: remove unused import --- .../src/handlers/unnecessary_async.rs | 55 ++----------------- 1 file changed, 6 insertions(+), 49 deletions(-) diff --git a/crates/ide-assists/src/handlers/unnecessary_async.rs b/crates/ide-assists/src/handlers/unnecessary_async.rs index 44f8dbdef35..04398832253 100644 --- a/crates/ide-assists/src/handlers/unnecessary_async.rs +++ b/crates/ide-assists/src/handlers/unnecessary_async.rs @@ -1,14 +1,12 @@ -use hir::AssocItem; use ide_db::{ assists::{AssistId, AssistKind}, base_db::FileId, defs::Definition, search::FileReference, syntax_helpers::node_ext::full_path_of_name_ref, - traits::resolve_target_trait, }; use syntax::{ - ast::{self, HasName, NameLike, NameRef}, + ast::{self, NameLike, NameRef}, AstNode, SyntaxKind, TextRange, }; @@ -46,16 +44,13 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() { return None; } - // Do nothing if the method is an async member of trait. - if let Some(fname) = function.name() { - if let Some(trait_item) = find_corresponding_trait_member(ctx, fname.to_string()) { - if let AssocItem::Function(method) = trait_item { - if method.is_async(ctx.db()) { - return None; - } - } + // Do nothing if the method is a member of trait. + if let Some(impl_) = function.syntax().ancestors().nth(2).and_then(ast::Impl::cast) { + if let Some(_) = impl_.trait_() { + return None; } } + // Remove the `async` keyword plus whitespace after it, if any. let async_range = { let async_token = function.async_token()?; @@ -99,23 +94,6 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O ) } -fn find_corresponding_trait_member( - ctx: &AssistContext<'_>, - function_name: String, -) -> Option { - let impl_ = ctx.find_node_at_offset::()?; - let trait_ = resolve_target_trait(&ctx.sema, &impl_)?; - - trait_ - .items(ctx.db()) - .iter() - .find(|item| match item.name(ctx.db()) { - Some(method_name) => method_name.to_string() == function_name, - _ => false, - }) - .cloned() -} - fn find_all_references( ctx: &AssistContext<'_>, def: &Definition, @@ -283,27 +261,6 @@ pub async fn f(s: &S) { s.f2() }"#, check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }") } - #[test] - fn applies_on_unnecessary_async_on_trait_method() { - check_assist( - unnecessary_async, - r#" -trait Trait { - fn foo(); -} -impl Trait for () { - $0async fn foo() {} -}"#, - r#" -trait Trait { - fn foo(); -} -impl Trait for () { - fn foo() {} -}"#, - ); - } - #[test] fn does_not_apply_on_async_trait_method() { check_assist_not_applicable(