|
3 | 3 | use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
|
4 | 4 | use clippy_utils::source::is_present_in_source;
|
5 | 5 | use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start};
|
6 |
| -use rustc_hir::{EnumDef, Item, ItemKind, Variant}; |
| 6 | +use rustc_hir::{EnumDef, Item, ItemKind, OwnerId, Variant}; |
7 | 7 | use rustc_lint::{LateContext, LateLintPass};
|
8 | 8 | use rustc_session::{declare_tool_lint, impl_lint_pass};
|
9 | 9 | use rustc_span::source_map::Span;
|
@@ -105,18 +105,20 @@ declare_clippy_lint! {
|
105 | 105 | }
|
106 | 106 |
|
107 | 107 | pub struct EnumVariantNames {
|
108 |
| - modules: Vec<(Symbol, String)>, |
| 108 | + modules: Vec<(Symbol, String, OwnerId)>, |
109 | 109 | threshold: u64,
|
110 | 110 | avoid_breaking_exported_api: bool,
|
| 111 | + allow_private_module_inception: bool, |
111 | 112 | }
|
112 | 113 |
|
113 | 114 | impl EnumVariantNames {
|
114 | 115 | #[must_use]
|
115 |
| - pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self { |
| 116 | + pub fn new(threshold: u64, avoid_breaking_exported_api: bool, allow_private_module_inception: bool) -> Self { |
116 | 117 | Self {
|
117 | 118 | modules: Vec::new(),
|
118 | 119 | threshold,
|
119 | 120 | avoid_breaking_exported_api,
|
| 121 | + allow_private_module_inception, |
120 | 122 | }
|
121 | 123 | }
|
122 | 124 | }
|
@@ -252,18 +254,19 @@ impl LateLintPass<'_> for EnumVariantNames {
|
252 | 254 | let item_name = item.ident.name.as_str();
|
253 | 255 | let item_camel = to_camel_case(item_name);
|
254 | 256 | if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
|
255 |
| - if let Some((mod_name, mod_camel)) = self.modules.last() { |
| 257 | + if let [.., (mod_name, mod_camel, owner_id)] = &*self.modules { |
256 | 258 | // constants don't have surrounding modules
|
257 | 259 | if !mod_camel.is_empty() {
|
258 |
| - if mod_name == &item.ident.name { |
259 |
| - if let ItemKind::Mod(..) = item.kind { |
260 |
| - span_lint( |
261 |
| - cx, |
262 |
| - MODULE_INCEPTION, |
263 |
| - item.span, |
264 |
| - "module has the same name as its containing module", |
265 |
| - ); |
266 |
| - } |
| 260 | + if mod_name == &item.ident.name |
| 261 | + && let ItemKind::Mod(..) = item.kind |
| 262 | + && (!self.allow_private_module_inception || cx.tcx.visibility(owner_id.def_id).is_public()) |
| 263 | + { |
| 264 | + span_lint( |
| 265 | + cx, |
| 266 | + MODULE_INCEPTION, |
| 267 | + item.span, |
| 268 | + "module has the same name as its containing module", |
| 269 | + ); |
267 | 270 | }
|
268 | 271 | // The `module_name_repetitions` lint should only trigger if the item has the module in its
|
269 | 272 | // name. Having the same name is accepted.
|
@@ -302,6 +305,6 @@ impl LateLintPass<'_> for EnumVariantNames {
|
302 | 305 | check_variant(cx, self.threshold, def, item_name, item.span);
|
303 | 306 | }
|
304 | 307 | }
|
305 |
| - self.modules.push((item.ident.name, item_camel)); |
| 308 | + self.modules.push((item.ident.name, item_camel, item.owner_id)); |
306 | 309 | }
|
307 | 310 | }
|
0 commit comments