Skip to content

Commit 4a7f5ca

Browse files
committed
fix: async trait method for unnecessary_async
1 parent d022e0e commit 4a7f5ca

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

crates/ide-assists/src/handlers/unnecessary_async.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use hir::AssocItem;
12
use ide_db::{
23
assists::{AssistId, AssistKind},
34
base_db::FileId,
45
defs::Definition,
56
search::FileReference,
67
syntax_helpers::node_ext::full_path_of_name_ref,
8+
traits::resolve_target_trait,
79
};
810
use syntax::{
9-
ast::{self, NameLike, NameRef},
11+
ast::{self, HasName, NameLike, NameRef},
1012
AstNode, SyntaxKind, TextRange,
1113
};
1214

@@ -44,7 +46,16 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
4446
if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() {
4547
return None;
4648
}
47-
49+
// Do nothing if the method is an async member of trait.
50+
if let Some(fname) = function.name() {
51+
if let Some(trait_item) = find_corresponding_trait_member(ctx, fname.to_string()) {
52+
if let AssocItem::Function(method) = trait_item {
53+
if method.is_async(ctx.db()) {
54+
return None;
55+
}
56+
}
57+
}
58+
}
4859
// Remove the `async` keyword plus whitespace after it, if any.
4960
let async_range = {
5061
let async_token = function.async_token()?;
@@ -88,6 +99,23 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
8899
)
89100
}
90101

102+
fn find_corresponding_trait_member(
103+
ctx: &AssistContext<'_>,
104+
function_name: String,
105+
) -> Option<AssocItem> {
106+
let impl_ = ctx.find_node_at_offset::<ast::Impl>()?;
107+
let trait_ = resolve_target_trait(&ctx.sema, &impl_)?;
108+
109+
trait_
110+
.items(ctx.db())
111+
.iter()
112+
.find(|item| match item.name(ctx.db()) {
113+
Some(method_name) => method_name.to_string() == function_name,
114+
_ => false,
115+
})
116+
.cloned()
117+
}
118+
91119
fn find_all_references(
92120
ctx: &AssistContext<'_>,
93121
def: &Definition,
@@ -254,4 +282,39 @@ pub async fn f(s: &S) { s.f2() }"#,
254282
fn does_not_apply_when_not_on_prototype() {
255283
check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }")
256284
}
285+
286+
#[test]
287+
fn applies_on_unnecessary_async_on_trait_method() {
288+
check_assist(
289+
unnecessary_async,
290+
r#"
291+
trait Trait {
292+
fn foo();
293+
}
294+
impl Trait for () {
295+
$0async fn foo() {}
296+
}"#,
297+
r#"
298+
trait Trait {
299+
fn foo();
300+
}
301+
impl Trait for () {
302+
fn foo() {}
303+
}"#,
304+
);
305+
}
306+
307+
#[test]
308+
fn does_not_apply_on_async_trait_method() {
309+
check_assist_not_applicable(
310+
unnecessary_async,
311+
r#"
312+
trait Trait {
313+
async fn foo();
314+
}
315+
impl Trait for () {
316+
$0async fn foo() {}
317+
}"#,
318+
);
319+
}
257320
}

0 commit comments

Comments
 (0)