Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
index 36031f15a0..1ec49f017f 100644
--- a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
@@ -3,7 +3,9 @@ use crate::{
assist_context::{AssistContext, Assists},
utils::add_cfg_attrs_to,
};
+use hir::Semantics;
use ide_db::{
+ RootDatabase,
assists::{AssistId, AssistKind, ExprFillDefaultMode},
syntax_helpers::suggest_name,
};
@@ -61,6 +63,11 @@ pub(crate) fn generate_blanket_trait_impl(
let name = ctx.find_node_at_offset::<ast::Name>()?;
let traitd = ast::Trait::cast(name.syntax().parent()?)?;
+ if existing_any_impl(&traitd, &ctx.sema).is_some() {
+ cov_mark::hit!(existing_any_impl);
+ return None;
+ }
+
acc.add(
AssistId("generate_blanket_trait_impl", AssistKind::Generate, None),
"Generate blanket trait implementation",
@@ -143,6 +150,16 @@ pub(crate) fn generate_blanket_trait_impl(
Some(())
}
+fn existing_any_impl(traitd: &ast::Trait, sema: &Semantics<'_, RootDatabase>) -> Option<hir::Impl> {
+ let db = sema.db;
+ let traitd = sema.to_def(traitd)?;
+ traitd
+ .module(db)
+ .impl_defs(db)
+ .into_iter()
+ .find(|impl_| impl_.trait_(db).is_some_and(|it| it == traitd))
+}
+
fn has_sized(traitd: &ast::Trait) -> bool {
if let Some(sized) = find_bound("Sized", traitd.type_bound_list()) {
sized.question_mark_token().is_none()
@@ -1423,6 +1440,51 @@ where
}
#[test]
+ fn test_gen_blanket_existing_impl() {
+ cov_mark::check!(existing_any_impl);
+ check_assist_not_applicable(
+ generate_blanket_trait_impl,
+ r#"
+trait $0Foo: Default {
+ fn foo(&self) -> Self;
+}
+impl Foo for () {}
+"#,
+ );
+ }
+
+ #[test]
+ fn test_gen_blanket_existing_other_impl() {
+ check_assist(
+ generate_blanket_trait_impl,
+ r#"
+trait $0Foo: Default {
+ fn foo(&self) -> Self;
+}
+trait Bar: Default {
+ fn bar(&self) -> Self;
+}
+impl Bar for () {}
+"#,
+ r#"
+trait Foo: Default {
+ fn foo(&self) -> Self;
+}
+
+impl<T: Default> Foo for $0T {
+ fn foo(&self) -> Self {
+ todo!()
+ }
+}
+trait Bar: Default {
+ fn bar(&self) -> Self;
+}
+impl Bar for () {}
+"#,
+ );
+ }
+
+ #[test]
fn test_gen_blanket_apply_on_other_impl_block() {
check_assist(
generate_blanket_trait_impl,