|
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