mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
feat: add trait_impl_reduntant_assoc_item diagnostic
This commit is contained in:
parent
77e362c34d
commit
5d84edd430
4 changed files with 85 additions and 0 deletions
|
@ -55,6 +55,7 @@ diagnostics![
|
|||
ReplaceFilterMapNextWithFindMap,
|
||||
TraitImplIncorrectSafety,
|
||||
TraitImplMissingAssocItems,
|
||||
TraitImplReduntantAssocItems,
|
||||
TraitImplOrphan,
|
||||
TypedHole,
|
||||
TypeMismatch,
|
||||
|
@ -310,3 +311,10 @@ pub struct TraitImplMissingAssocItems {
|
|||
pub impl_: AstPtr<ast::Impl>,
|
||||
pub missing: Vec<(Name, AssocItem)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct TraitImplReduntantAssocItems {
|
||||
pub file_id: HirFileId,
|
||||
pub impl_: AstPtr<ast::Impl>,
|
||||
pub reduntant: Vec<(Name, AssocItem)>,
|
||||
}
|
|
@ -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)| {
|
||||
|
|
|
@ -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::<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() {}
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue