Merge pull request #1223 from oli-obk/use_your_token_to_figure_out_if_you_are_in_reality
Let the submodule `#[allow]` in `module_inception`
This commit is contained in:
commit
05e734b555
@ -47,8 +47,32 @@
|
|||||||
"type names prefixed/postfixed with their containing module's name"
|
"type names prefixed/postfixed with their containing module's name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **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`.
|
||||||
|
/// The expectation is that items inside the inner `mod foo { .. }` are then available
|
||||||
|
/// through `foo::x`, but they are only available through `foo::foo::x`.
|
||||||
|
/// If this is done on purpose, it would be better to choose a more representative module name.
|
||||||
|
///
|
||||||
|
/// **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 EnumVariantNames {
|
pub struct EnumVariantNames {
|
||||||
modules: Vec<String>,
|
modules: Vec<(InternedString, String)>,
|
||||||
threshold: u64,
|
threshold: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +84,7 @@ pub fn new(threshold: u64) -> EnumVariantNames {
|
|||||||
|
|
||||||
impl LintPass for EnumVariantNames {
|
impl LintPass for EnumVariantNames {
|
||||||
fn get_lints(&self) -> LintArray {
|
fn get_lints(&self) -> LintArray {
|
||||||
lint_array!(ENUM_VARIANT_NAMES, STUTTER)
|
lint_array!(ENUM_VARIANT_NAMES, STUTTER, MODULE_INCEPTION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,18 +194,25 @@ fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
|
|||||||
let item_name = item.ident.name.as_str();
|
let item_name = item.ident.name.as_str();
|
||||||
let item_name_chars = item_name.chars().count();
|
let item_name_chars = item_name.chars().count();
|
||||||
let item_camel = to_camel_case(&item_name);
|
let item_camel = to_camel_case(&item_name);
|
||||||
if item.vis == Visibility::Public && !in_macro(cx, item.span) {
|
if !in_macro(cx, item.span) {
|
||||||
if let Some(mod_camel) = self.modules.last() {
|
if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() {
|
||||||
// constants don't have surrounding modules
|
// constants don't have surrounding modules
|
||||||
if !mod_camel.is_empty() {
|
if !mod_camel.is_empty() {
|
||||||
|
if mod_name == &item_name {
|
||||||
|
if let ItemKind::Mod(..) = item.node {
|
||||||
|
span_lint(cx, MODULE_INCEPTION, item.span, "module has the same name as its containing module");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if item.vis == Visibility::Public {
|
||||||
let matching = partial_match(mod_camel, &item_camel);
|
let matching = partial_match(mod_camel, &item_camel);
|
||||||
let rmatching = partial_rmatch(mod_camel, &item_camel);
|
let rmatching = partial_rmatch(mod_camel, &item_camel);
|
||||||
let nchars = mod_camel.chars().count();
|
let nchars = mod_camel.chars().count();
|
||||||
if matching == nchars {
|
if matching == nchars {
|
||||||
span_lint(cx, STUTTER, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel));
|
span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name");
|
||||||
}
|
}
|
||||||
if rmatching == nchars {
|
if rmatching == nchars {
|
||||||
span_lint(cx, STUTTER, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel));
|
span_lint(cx, STUTTER, item.span, "item name ends with its containing module's name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,6 +220,6 @@ fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
|
|||||||
if let ItemKind::Enum(ref def, _) = item.node {
|
if let ItemKind::Enum(ref def, _) = item.node {
|
||||||
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
|
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
|
||||||
}
|
}
|
||||||
self.modules.push(item_camel);
|
self.modules.push((item_name, item_camel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,6 @@ macro_rules! declare_restriction_lint {
|
|||||||
pub mod misc;
|
pub mod misc;
|
||||||
pub mod misc_early;
|
pub mod misc_early;
|
||||||
pub mod missing_doc;
|
pub mod missing_doc;
|
||||||
pub mod module_inception;
|
|
||||||
pub mod mut_mut;
|
pub mod mut_mut;
|
||||||
pub mod mut_reference;
|
pub mod mut_reference;
|
||||||
pub mod mutex_atomic;
|
pub mod mutex_atomic;
|
||||||
@ -175,7 +174,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||||||
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
|
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
|
||||||
reg.register_late_lint_pass(box types::TypePass);
|
reg.register_late_lint_pass(box types::TypePass);
|
||||||
reg.register_late_lint_pass(box booleans::NonminimalBool);
|
reg.register_late_lint_pass(box booleans::NonminimalBool);
|
||||||
reg.register_early_lint_pass(box module_inception::Pass);
|
|
||||||
reg.register_late_lint_pass(box eq_op::EqOp);
|
reg.register_late_lint_pass(box eq_op::EqOp);
|
||||||
reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold));
|
reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold));
|
||||||
reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse);
|
reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse);
|
||||||
@ -329,6 +327,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||||||
entry::MAP_ENTRY,
|
entry::MAP_ENTRY,
|
||||||
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
|
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
|
||||||
enum_variants::ENUM_VARIANT_NAMES,
|
enum_variants::ENUM_VARIANT_NAMES,
|
||||||
|
enum_variants::MODULE_INCEPTION,
|
||||||
eq_op::EQ_OP,
|
eq_op::EQ_OP,
|
||||||
escape::BOXED_LOCAL,
|
escape::BOXED_LOCAL,
|
||||||
eta_reduction::REDUNDANT_CLOSURE,
|
eta_reduction::REDUNDANT_CLOSURE,
|
||||||
@ -391,7 +390,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||||||
misc_early::REDUNDANT_CLOSURE_CALL,
|
misc_early::REDUNDANT_CLOSURE_CALL,
|
||||||
misc_early::UNNEEDED_FIELD_PATTERN,
|
misc_early::UNNEEDED_FIELD_PATTERN,
|
||||||
misc_early::ZERO_PREFIXED_LITERAL,
|
misc_early::ZERO_PREFIXED_LITERAL,
|
||||||
module_inception::MODULE_INCEPTION,
|
|
||||||
mut_reference::UNNECESSARY_MUT_PASSED,
|
mut_reference::UNNECESSARY_MUT_PASSED,
|
||||||
mutex_atomic::MUTEX_ATOMIC,
|
mutex_atomic::MUTEX_ATOMIC,
|
||||||
needless_bool::BOOL_COMPARISON,
|
needless_bool::BOOL_COMPARISON,
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
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`.
|
|
||||||
/// The expectation is that items inside the inner `mod foo { .. }` are then available
|
|
||||||
/// through `foo::x`, but they are only available through `foo::foo::x`.
|
|
||||||
/// If this is done on purpose, it would be better to choose a more representative module name.
|
|
||||||
///
|
|
||||||
/// **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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,4 +14,11 @@ mod bar {}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No warning. See <https://github.com/Manishearth/rust-clippy/issues/1220>.
|
||||||
|
mod bar {
|
||||||
|
#[allow(module_inception)]
|
||||||
|
mod bar {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
14
tests/compile-fail/stutter.rs
Normal file
14
tests/compile-fail/stutter.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(clippy)]
|
||||||
|
#![deny(stutter)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
pub fn foo() {}
|
||||||
|
pub fn foo_bar() {} //~ ERROR: item name starts with its containing module's name
|
||||||
|
pub fn bar_foo() {} //~ ERROR: item name ends with its containing module's name
|
||||||
|
pub struct FooCake {} //~ ERROR: item name starts with its containing module's name
|
||||||
|
pub enum CakeFoo {} //~ ERROR: item name ends with its containing module's name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user