Add redundant_method_names lint
This commit is contained in:
parent
64d74df19c
commit
357a8f0344
19 changed files with 253 additions and 65 deletions
|
|
@ -330,6 +330,7 @@ mod regex;
|
|||
mod repeat_once;
|
||||
mod returns;
|
||||
mod self_assignment;
|
||||
mod self_named_constructor;
|
||||
mod semicolon_if_nothing_returned;
|
||||
mod serde_api;
|
||||
mod shadow;
|
||||
|
|
@ -900,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
returns::LET_AND_RETURN,
|
||||
returns::NEEDLESS_RETURN,
|
||||
self_assignment::SELF_ASSIGNMENT,
|
||||
self_named_constructor::SELF_NAMED_CONSTRUCTOR,
|
||||
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
|
||||
serde_api::SERDE_API_MISUSE,
|
||||
shadow::SHADOW_REUSE,
|
||||
|
|
@ -1406,6 +1408,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(returns::LET_AND_RETURN),
|
||||
LintId::of(returns::NEEDLESS_RETURN),
|
||||
LintId::of(self_assignment::SELF_ASSIGNMENT),
|
||||
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
|
||||
LintId::of(serde_api::SERDE_API_MISUSE),
|
||||
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
|
||||
|
|
@ -1559,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
||||
LintId::of(returns::LET_AND_RETURN),
|
||||
LintId::of(returns::NEEDLESS_RETURN),
|
||||
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
|
||||
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||
|
|
@ -2101,6 +2105,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
let scripts = conf.allowed_scripts.clone();
|
||||
store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts));
|
||||
store.register_late_pass(|| box strlen_on_c_strings::StrlenOnCStrings);
|
||||
store.register_late_pass(move || box self_named_constructor::SelfNamedConstructor);
|
||||
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
|
|
|||
91
clippy_lints/src/self_named_constructor.rs
Normal file
91
clippy_lints/src/self_named_constructor.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::return_ty;
|
||||
use clippy_utils::ty::{contains_adt_constructor, contains_ty};
|
||||
use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Warns when constructors have the same name as their types.
|
||||
///
|
||||
/// **Why is this bad?** Repeating the name of the type is redundant.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// struct Foo {}
|
||||
///
|
||||
/// impl Foo {
|
||||
/// pub fn foo() -> Foo {
|
||||
/// Foo {}
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust,ignore
|
||||
/// struct Foo {}
|
||||
///
|
||||
/// impl Foo {
|
||||
/// pub fn new() -> Foo {
|
||||
/// Foo {}
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub SELF_NAMED_CONSTRUCTOR,
|
||||
style,
|
||||
"method should not have the same name as the type it is implemented for"
|
||||
}
|
||||
|
||||
declare_lint_pass!(SelfNamedConstructor => [SELF_NAMED_CONSTRUCTOR]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructor {
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
|
||||
match impl_item.kind {
|
||||
ImplItemKind::Fn(ref sig, _) => {
|
||||
if sig.decl.implicit_self.has_implicit_self() {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
|
||||
let item = cx.tcx.hir().expect_item(parent);
|
||||
let self_ty = cx.tcx.type_of(item.def_id);
|
||||
let ret_ty = return_ty(cx, impl_item.hir_id());
|
||||
|
||||
// Do not check trait impls
|
||||
if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure method is constructor-like
|
||||
if let Some(self_adt) = self_ty.ty_adt_def() {
|
||||
if !contains_adt_constructor(ret_ty, self_adt) {
|
||||
return;
|
||||
}
|
||||
} else if !contains_ty(ret_ty, self_ty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if let Some(self_def) = self_ty.ty_adt_def();
|
||||
if let Some(self_local_did) = self_def.did.as_local();
|
||||
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
|
||||
if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
|
||||
let type_name = x.ident.name.as_str().to_lowercase();
|
||||
if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace("_", "") == type_name;
|
||||
|
||||
then {
|
||||
span_lint(
|
||||
cx,
|
||||
SELF_NAMED_CONSTRUCTOR,
|
||||
impl_item.span,
|
||||
&format!("constructor `{}` has the same name as the type", impl_item.ident.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue