Unnamed repository; edit this file 'description' to name the repository.
update: make each trait_impl_reduntant_assoc_item into individual diagnostic
Young-Flash 2023-12-06
parent 5d84edd · commit 861e474
-rw-r--r--crates/hir/src/diagnostics.rs12
-rw-r--r--crates/hir/src/lib.rs22
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs72
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs56
-rw-r--r--crates/ide-diagnostics/src/lib.rs4
5 files changed, 91 insertions, 75 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 74c1b97a2e..52c1c27a7f 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -12,7 +12,7 @@ use hir_def::path::ModPath;
use hir_expand::{name::Name, HirFileId, InFile};
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
-use crate::{AssocItem, Field, Local, MacroKind, Type};
+use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
macro_rules! diagnostics {
($($diag:ident,)*) => {
@@ -55,7 +55,7 @@ diagnostics![
ReplaceFilterMapNextWithFindMap,
TraitImplIncorrectSafety,
TraitImplMissingAssocItems,
- TraitImplReduntantAssocItems,
+ TraitImplRedundantAssocItems,
TraitImplOrphan,
TypedHole,
TypeMismatch,
@@ -313,8 +313,8 @@ pub struct TraitImplMissingAssocItems {
}
#[derive(Debug, PartialEq, Eq)]
-pub struct TraitImplReduntantAssocItems {
+pub struct TraitImplRedundantAssocItems {
pub file_id: HirFileId,
- pub impl_: AstPtr<ast::Impl>,
- pub reduntant: Vec<(Name, AssocItem)>,
-} \ No newline at end of file
+ pub trait_: Trait,
+ pub assoc_item: (Name, AssocItem),
+}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5e6f3c7a99..4db1a02c0c 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -693,20 +693,20 @@ impl Module {
},
));
- let reduntant: Vec<_> = impl_assoc_items_scratch.iter()
- .filter(|(id, name)| {
- !required_items.clone().any(|(impl_name, impl_item)| {
- discriminant(impl_item) == discriminant(id) && impl_name == name
+ let redundant = impl_assoc_items_scratch
+ .iter()
+ .filter(|(id, name)| {
+ !items.iter().any(|(impl_name, impl_item)| {
+ discriminant(impl_item) == discriminant(id) && impl_name == name
+ })
})
- })
- .map(|(item, name)| (name.clone(), AssocItem::from(*item)))
- .collect();
- if !reduntant.is_empty() {
+ .map(|(item, name)| (name.clone(), AssocItem::from(*item)));
+ for (name, assoc_item) in redundant {
acc.push(
- TraitImplReduntantAssocItems {
- impl_: ast_id_map.get(node.ast_id()),
+ TraitImplRedundantAssocItems {
+ trait_,
file_id,
- reduntant,
+ assoc_item: (name, assoc_item),
}
.into(),
)
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
new file mode 100644
index 0000000000..6aded11382
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -0,0 +1,72 @@
+use hir::{db::ExpandDatabase, Const, Function, HasSource, TypeAlias};
+
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: trait-impl-redundant-assoc_item
+//
+// Diagnoses redundant trait items in a trait impl.
+pub(crate) fn trait_impl_redundant_assoc_item(
+ ctx: &DiagnosticsContext<'_>,
+ d: &hir::TraitImplRedundantAssocItems,
+) -> Diagnostic {
+ let name = d.assoc_item.0.clone();
+ let assoc_item = d.assoc_item.1;
+ let db = ctx.sema.db;
+
+ let range = db.parse_or_expand(d.file_id).text_range();
+ let trait_name = d.trait_.name(db).to_smol_str();
+
+ let (redundant_item_name, diagnostic_range) = match assoc_item {
+ hir::AssocItem::Function(id) => (
+ format!("`fn {}`", name.display(db)),
+ Function::from(id).source(db).map(|it| it.syntax().value.text_range()).unwrap_or(range),
+ ),
+ hir::AssocItem::Const(id) => (
+ format!("`const {}`", name.display(db)),
+ Const::from(id).source(db).map(|it| it.syntax().value.text_range()).unwrap_or(range),
+ ),
+ hir::AssocItem::TypeAlias(id) => (
+ format!("`type {}`", name.display(db)),
+ TypeAlias::from(id)
+ .source(db)
+ .map(|it| it.syntax().value.text_range())
+ .unwrap_or(range),
+ ),
+ };
+
+ Diagnostic::new(
+ DiagnosticCode::RustcHardError("E0407"),
+ format!("{redundant_item_name} is not a member of trait `{trait_name}`"),
+ diagnostic_range,
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn trait_with_default_value() {
+ check_diagnostics(
+ r#"
+trait Marker {
+ const FLAG: bool = false;
+ fn boo();
+ fn foo () {}
+}
+struct Foo;
+impl Marker for Foo {
+ type T = i32;
+ //^^^^^^^^^^^^^ error: `type T` is not a member of trait `Marker`
+
+ const FLAG: bool = true;
+
+ fn bar() {}
+ //^^^^^^^^^^^ error: `fn bar` is not a member of trait `Marker`
+
+ fn boo() {}
+}
+ "#,
+ )
+ }
+}
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs
deleted file mode 100644
index 446ce7d9fe..0000000000
--- a/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-use hir::InFile;
-use itertools::Itertools;
-use syntax::{ast, AstNode};
-
-use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext};
-
-// Diagnostic: trait-impl-reduntant-assoc_item
-//
-// Diagnoses reduntant trait items in a trait impl.
-pub(crate) fn trait_impl_reduntant_assoc_item(
- ctx: &DiagnosticsContext<'_>,
- d: &hir::TraitImplReduntantAssocItems,
-) -> Diagnostic {
- let reduntant = d.reduntant.iter().format_with(", ", |(name, item), f| {
- f(&match *item {
- hir::AssocItem::Function(_) => "`fn ",
- hir::AssocItem::Const(_) => "`const ",
- hir::AssocItem::TypeAlias(_) => "`type ",
- })?;
- f(&name.display(ctx.sema.db))?;
- f(&"`")
- });
- Diagnostic::new(
- DiagnosticCode::RustcHardError("E0407"),
- format!("{reduntant} is not a member of trait"),
- adjusted_display_range::<ast::Impl>(
- ctx,
- InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() },
- &|impl_| impl_.trait_().map(|t| t.syntax().text_range()),
- ),
- )
-}
-
-#[cfg(test)]
-mod tests {
- use crate::tests::check_diagnostics;
-
- #[test]
- fn trait_with_default_value() {
- check_diagnostics(
- r#"
-trait Marker {
- fn boo();
-}
-struct Foo;
-impl Marker for Foo {
- //^^^^^^ error: `type T`, `const FLAG`, `fn bar` is not a member of trait
- type T = i32;
- const FLAG: bool = false;
- fn bar() {}
- fn boo() {}
-}
- "#,
- )
- }
-}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index c39e572b42..6cfd5f1832 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -47,7 +47,7 @@ mod handlers {
pub(crate) mod trait_impl_orphan;
pub(crate) mod trait_impl_incorrect_safety;
pub(crate) mod trait_impl_missing_assoc_item;
- pub(crate) mod trait_impl_reduntant_assoc_item;
+ pub(crate) mod trait_impl_redundant_assoc_item;
pub(crate) mod typed_hole;
pub(crate) mod type_mismatch;
pub(crate) mod unimplemented_builtin_macro;
@@ -365,7 +365,7 @@ pub fn diagnostics(
AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d),
AnyDiagnostic::TraitImplIncorrectSafety(d) => handlers::trait_impl_incorrect_safety::trait_impl_incorrect_safety(&ctx, &d),
AnyDiagnostic::TraitImplMissingAssocItems(d) => handlers::trait_impl_missing_assoc_item::trait_impl_missing_assoc_item(&ctx, &d),
- AnyDiagnostic::TraitImplReduntantAssocItems(d) => handlers::trait_impl_reduntant_assoc_item::trait_impl_reduntant_assoc_item(&ctx, &d),
+ AnyDiagnostic::TraitImplRedundantAssocItems(d) => handlers::trait_impl_redundant_assoc_item::trait_impl_redundant_assoc_item(&ctx, &d),
AnyDiagnostic::TraitImplOrphan(d) => handlers::trait_impl_orphan::trait_impl_orphan(&ctx, &d),
AnyDiagnostic::TypedHole(d) => handlers::typed_hole::typed_hole(&ctx, &d),
AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d),