diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb5ad82f..725cdcc10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -222,6 +222,7 @@ All notable changes to this project will be documented in this file. [`min_max`]: https://github.com/Manishearth/rust-clippy/wiki#min_max [`misrefactored_assign_op`]: https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op [`mixed_case_hex_literals`]: https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals +[`module_inception`]: https://github.com/Manishearth/rust-clippy/wiki#module_inception [`modulo_one`]: https://github.com/Manishearth/rust-clippy/wiki#modulo_one [`mut_mut`]: https://github.com/Manishearth/rust-clippy/wiki#mut_mut [`mutex_atomic`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic diff --git a/README.md b/README.md index 4e6f864fe..1da19a710 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 163 lints included in this crate: +There are 164 lints included in this crate: name | default | triggers on ---------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -100,6 +100,7 @@ name [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [misrefactored_assign_op](https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op) | warn | having a variable on both sides of an assign op [mixed_case_hex_literals](https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals) | warn | hex literals whose letter digits are not consistently upper- or lowercased +[module_inception](https://github.com/Manishearth/rust-clippy/wiki#module_inception) | warn | modules that have the same name as their parent module [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` [mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a mutex where an atomic value could be used instead diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 260b5c1ba..3a5051b93 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -96,6 +96,7 @@ pub mod methods; pub mod minmax; pub mod misc; pub mod misc_early; +pub mod module_inception; pub mod mut_mut; pub mod mut_reference; pub mod mutex_atomic; @@ -173,6 +174,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box utils::internal_lints::Clippy); reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box booleans::NonminimalBool); + reg.register_early_lint_pass(box module_inception::Pass); reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); @@ -384,6 +386,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc_early::MIXED_CASE_HEX_LITERALS, misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, + module_inception::MODULE_INCEPTION, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::BOOL_COMPARISON, diff --git a/clippy_lints/src/module_inception.rs b/clippy_lints/src/module_inception.rs new file mode 100644 index 000000000..821592929 --- /dev/null +++ b/clippy_lints/src/module_inception.rs @@ -0,0 +1,47 @@ +use rustc::lint::*; +use syntax::ast::*; +use utils::span_lint; + +/// **What it does:** Checks for modules that have the same name as their parent module +/// +/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. }` in `foo.rs` +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // lib.rs +/// mod foo; +/// // foo.rs +/// mod foo { +/// ... +/// } +/// ``` +declare_lint! { + pub MODULE_INCEPTION, + Warn, + "modules that have the same name as their parent module" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array![MODULE_INCEPTION] + } +} + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemKind::Mod(ref module) = item.node { + for sub_item in &module.items { + if let ItemKind::Mod(_) = sub_item.node { + if item.ident == sub_item.ident { + span_lint(cx, MODULE_INCEPTION, sub_item.span, + "module has the same name as its containing module"); + } + } + } + } + } +} diff --git a/tests/compile-fail/module_inception.rs b/tests/compile-fail/module_inception.rs new file mode 100644 index 000000000..499daadee --- /dev/null +++ b/tests/compile-fail/module_inception.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(module_inception)] + +mod foo { + mod bar { + mod bar { //~ ERROR module has the same name as its containing module + + } + } + mod foo { //~ ERROR module has the same name as its containing module + + } +} + +fn main() {}