Skip to content

Commit 05e734b

Browse files
authored
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`
2 parents cb49e4e + 40ce3a8 commit 05e734b

File tree

5 files changed

+65
-65
lines changed

5 files changed

+65
-65
lines changed

clippy_lints/src/enum_variants.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,32 @@ declare_lint! {
4747
"type names prefixed/postfixed with their containing module's name"
4848
}
4949

50+
/// **What it does:** Checks for modules that have the same name as their parent module
51+
///
52+
/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. }` in `foo.rs`.
53+
/// The expectation is that items inside the inner `mod foo { .. }` are then available
54+
/// through `foo::x`, but they are only available through `foo::foo::x`.
55+
/// If this is done on purpose, it would be better to choose a more representative module name.
56+
///
57+
/// **Known problems:** None.
58+
///
59+
/// **Example:**
60+
/// ```rust
61+
/// // lib.rs
62+
/// mod foo;
63+
/// // foo.rs
64+
/// mod foo {
65+
/// ...
66+
/// }
67+
/// ```
68+
declare_lint! {
69+
pub MODULE_INCEPTION,
70+
Warn,
71+
"modules that have the same name as their parent module"
72+
}
73+
5074
pub struct EnumVariantNames {
51-
modules: Vec<String>,
75+
modules: Vec<(InternedString, String)>,
5276
threshold: u64,
5377
}
5478

@@ -60,7 +84,7 @@ impl EnumVariantNames {
6084

6185
impl LintPass for EnumVariantNames {
6286
fn get_lints(&self) -> LintArray {
63-
lint_array!(ENUM_VARIANT_NAMES, STUTTER)
87+
lint_array!(ENUM_VARIANT_NAMES, STUTTER, MODULE_INCEPTION)
6488
}
6589
}
6690

@@ -170,25 +194,32 @@ impl EarlyLintPass for EnumVariantNames {
170194
let item_name = item.ident.name.as_str();
171195
let item_name_chars = item_name.chars().count();
172196
let item_camel = to_camel_case(&item_name);
173-
if item.vis == Visibility::Public && !in_macro(cx, item.span) {
174-
if let Some(mod_camel) = self.modules.last() {
197+
if !in_macro(cx, item.span) {
198+
if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() {
175199
// constants don't have surrounding modules
176200
if !mod_camel.is_empty() {
177-
let matching = partial_match(mod_camel, &item_camel);
178-
let rmatching = partial_rmatch(mod_camel, &item_camel);
179-
let nchars = mod_camel.chars().count();
180-
if matching == nchars {
181-
span_lint(cx, STUTTER, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel));
201+
if mod_name == &item_name {
202+
if let ItemKind::Mod(..) = item.node {
203+
span_lint(cx, MODULE_INCEPTION, item.span, "module has the same name as its containing module");
204+
}
182205
}
183-
if rmatching == nchars {
184-
span_lint(cx, STUTTER, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel));
206+
if item.vis == Visibility::Public {
207+
let matching = partial_match(mod_camel, &item_camel);
208+
let rmatching = partial_rmatch(mod_camel, &item_camel);
209+
let nchars = mod_camel.chars().count();
210+
if matching == nchars {
211+
span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name");
212+
}
213+
if rmatching == nchars {
214+
span_lint(cx, STUTTER, item.span, "item name ends with its containing module's name");
215+
}
185216
}
186217
}
187218
}
188219
}
189220
if let ItemKind::Enum(ref def, _) = item.node {
190221
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
191222
}
192-
self.modules.push(item_camel);
223+
self.modules.push((item_name, item_camel));
193224
}
194225
}

clippy_lints/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ pub mod minmax;
9696
pub mod misc;
9797
pub mod misc_early;
9898
pub mod missing_doc;
99-
pub mod module_inception;
10099
pub mod mut_mut;
101100
pub mod mut_reference;
102101
pub mod mutex_atomic;
@@ -175,7 +174,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
175174
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
176175
reg.register_late_lint_pass(box types::TypePass);
177176
reg.register_late_lint_pass(box booleans::NonminimalBool);
178-
reg.register_early_lint_pass(box module_inception::Pass);
179177
reg.register_late_lint_pass(box eq_op::EqOp);
180178
reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold));
181179
reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse);
@@ -329,6 +327,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
329327
entry::MAP_ENTRY,
330328
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
331329
enum_variants::ENUM_VARIANT_NAMES,
330+
enum_variants::MODULE_INCEPTION,
332331
eq_op::EQ_OP,
333332
escape::BOXED_LOCAL,
334333
eta_reduction::REDUNDANT_CLOSURE,
@@ -391,7 +390,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
391390
misc_early::REDUNDANT_CLOSURE_CALL,
392391
misc_early::UNNEEDED_FIELD_PATTERN,
393392
misc_early::ZERO_PREFIXED_LITERAL,
394-
module_inception::MODULE_INCEPTION,
395393
mut_reference::UNNECESSARY_MUT_PASSED,
396394
mutex_atomic::MUTEX_ATOMIC,
397395
needless_bool::BOOL_COMPARISON,

clippy_lints/src/module_inception.rs

Lines changed: 0 additions & 50 deletions
This file was deleted.

tests/compile-fail/module_inception.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,11 @@ mod foo {
1414
}
1515
}
1616

17+
// No warning. See <https://github.com/Manishearth/rust-clippy/issues/1220>.
18+
mod bar {
19+
#[allow(module_inception)]
20+
mod bar {
21+
}
22+
}
23+
1724
fn main() {}

tests/compile-fail/stutter.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(plugin)]
2+
#![plugin(clippy)]
3+
#![deny(stutter)]
4+
#![allow(dead_code)]
5+
6+
mod foo {
7+
pub fn foo() {}
8+
pub fn foo_bar() {} //~ ERROR: item name starts with its containing module's name
9+
pub fn bar_foo() {} //~ ERROR: item name ends with its containing module's name
10+
pub struct FooCake {} //~ ERROR: item name starts with its containing module's name
11+
pub enum CakeFoo {} //~ ERROR: item name ends with its containing module's name
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)