From 5d84edd4306600a844010dfb4356e0e8e1febc31 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Tue, 28 Nov 2023 21:15:45 +0800 Subject: [PATCH] feat: add trait_impl_reduntant_assoc_item diagnostic --- crates/hir/src/diagnostics.rs | 8 +++ crates/hir/src/lib.rs | 19 +++++++ .../trait_impl_reduntant_assoc_item.rs | 56 +++++++++++++++++++ crates/ide-diagnostics/src/lib.rs | 2 + 4 files changed, 85 insertions(+) create mode 100644 crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index cf9a2b73d9..74c1b97a2e 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -55,6 +55,7 @@ diagnostics![ ReplaceFilterMapNextWithFindMap, TraitImplIncorrectSafety, TraitImplMissingAssocItems, + TraitImplReduntantAssocItems, TraitImplOrphan, TypedHole, TypeMismatch, @@ -310,3 +311,10 @@ pub struct TraitImplMissingAssocItems { pub impl_: AstPtr, pub missing: Vec<(Name, AssocItem)>, } + +#[derive(Debug, PartialEq, Eq)] +pub struct TraitImplReduntantAssocItems { + pub file_id: HirFileId, + pub impl_: AstPtr, + pub reduntant: Vec<(Name, AssocItem)>, +} \ No newline at end of file diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4a0c384e8a..5e6f3c7a99 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -693,6 +693,25 @@ 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 + }) + }) + .map(|(item, name)| (name.clone(), AssocItem::from(*item))) + .collect(); + if !reduntant.is_empty() { + acc.push( + TraitImplReduntantAssocItems { + impl_: ast_id_map.get(node.ast_id()), + file_id, + reduntant, + } + .into(), + ) + } + let missing: Vec<_> = required_items .filter(|(name, id)| { !impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| { 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 new file mode 100644 index 0000000000..446ce7d9fe --- /dev/null +++ b/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs @@ -0,0 +1,56 @@ +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::( + 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 35272e8726..c39e572b42 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -47,6 +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 typed_hole; pub(crate) mod type_mismatch; pub(crate) mod unimplemented_builtin_macro; @@ -364,6 +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::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),