Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs')
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs | 72 |
1 files changed, 72 insertions, 0 deletions
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() {} +} + "#, + ) + } +} |