rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs

73 lines
2.0 KiB
Rust

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() {}
}
"#,
)
}
}