Skip to content

Commit 3d77a2b

Browse files
committed
Use break api config for enum_variant_names
1 parent ee79077 commit 3d77a2b

File tree

5 files changed

+59
-83
lines changed

5 files changed

+59
-83
lines changed

clippy_lints/src/deprecated_lints.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ declare_deprecated_lint! {
142142
"this lint has been replaced by `manual_filter_map`, a more specific lint"
143143
}
144144

145+
declare_deprecated_lint! {
146+
/// **What it does:** Nothing. This lint has been deprecated.
147+
///
148+
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
149+
/// enables the `enum_variant_names` lint for public items.
150+
/// ```
151+
pub PUB_ENUM_VARIANT_NAMES,
152+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
153+
}
154+
145155
declare_deprecated_lint! {
146156
/// **What it does:** Nothing. This lint has been deprecated.
147157
///

clippy_lints/src/enum_variants.rs

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use clippy_utils::camel_case;
44
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
55
use clippy_utils::source::is_present_in_source;
6-
use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
7-
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
6+
use rustc_hir::{EnumDef, Item, ItemKind};
7+
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::{declare_tool_lint, impl_lint_pass};
99
use rustc_span::source_map::Span;
1010
use rustc_span::symbol::Symbol;
@@ -39,36 +39,6 @@ declare_clippy_lint! {
3939
"enums where all variants share a prefix/postfix"
4040
}
4141

42-
declare_clippy_lint! {
43-
/// **What it does:** Detects public enumeration variants that are
44-
/// prefixed or suffixed by the same characters.
45-
///
46-
/// **Why is this bad?** Public enumeration variant names should specify their variant,
47-
/// not repeat the enumeration name.
48-
///
49-
/// **Known problems:** None.
50-
///
51-
/// **Example:**
52-
/// ```rust
53-
/// pub enum Cake {
54-
/// BlackForestCake,
55-
/// HummingbirdCake,
56-
/// BattenbergCake,
57-
/// }
58-
/// ```
59-
/// Could be written as:
60-
/// ```rust
61-
/// pub enum Cake {
62-
/// BlackForest,
63-
/// Hummingbird,
64-
/// Battenberg,
65-
/// }
66-
/// ```
67-
pub PUB_ENUM_VARIANT_NAMES,
68-
pedantic,
69-
"public enums where all variants share a prefix/postfix"
70-
}
71-
7242
declare_clippy_lint! {
7343
/// **What it does:** Detects type names that are prefixed or suffixed by the
7444
/// containing module's name.
@@ -127,21 +97,22 @@ declare_clippy_lint! {
12797
pub struct EnumVariantNames {
12898
modules: Vec<(Symbol, String)>,
12999
threshold: u64,
100+
avoid_breaking_exported_api: bool,
130101
}
131102

132103
impl EnumVariantNames {
133104
#[must_use]
134-
pub fn new(threshold: u64) -> Self {
105+
pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
135106
Self {
136107
modules: Vec::new(),
137108
threshold,
109+
avoid_breaking_exported_api,
138110
}
139111
}
140112
}
141113

142114
impl_lint_pass!(EnumVariantNames => [
143115
ENUM_VARIANT_NAMES,
144-
PUB_ENUM_VARIANT_NAMES,
145116
MODULE_NAME_REPETITIONS,
146117
MODULE_INCEPTION
147118
]);
@@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
167138
}
168139

169140
fn check_variant(
170-
cx: &EarlyContext<'_>,
141+
cx: &LateContext<'_>,
171142
threshold: u64,
172-
def: &EnumDef,
143+
def: &EnumDef<'_>,
173144
item_name: &str,
174145
item_name_chars: usize,
175146
span: Span,
176-
lint: &'static Lint,
177147
) {
178148
if (def.variants.len() as u64) < threshold {
179149
return;
180150
}
181-
for var in &def.variants {
151+
for var in def.variants {
182152
let name = var.ident.name.as_str();
183153
if partial_match(item_name, &name) == item_name_chars
184154
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
185155
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
186156
{
187-
span_lint(cx, lint, var.span, "variant name starts with the enum's name");
157+
span_lint(
158+
cx,
159+
ENUM_VARIANT_NAMES,
160+
var.span,
161+
"variant name starts with the enum's name",
162+
);
188163
}
189164
if partial_rmatch(item_name, &name) == item_name_chars {
190-
span_lint(cx, lint, var.span, "variant name ends with the enum's name");
165+
span_lint(
166+
cx,
167+
ENUM_VARIANT_NAMES,
168+
var.span,
169+
"variant name ends with the enum's name",
170+
);
191171
}
192172
}
193173
let first = &def.variants[0].ident.name.as_str();
194174
let mut pre = &first[..camel_case::until(&*first)];
195175
let mut post = &first[camel_case::from(&*first)..];
196-
for var in &def.variants {
176+
for var in def.variants {
197177
let name = var.ident.name.as_str();
198178

199179
let pre_match = partial_match(pre, &name);
@@ -226,7 +206,7 @@ fn check_variant(
226206
};
227207
span_lint_and_help(
228208
cx,
229-
lint,
209+
ENUM_VARIANT_NAMES,
230210
span,
231211
&format!("all variants have the same {}fix: `{}`", what, value),
232212
None,
@@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String {
261241
s
262242
}
263243

264-
impl EarlyLintPass for EnumVariantNames {
265-
fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) {
244+
impl LateLintPass<'_> for EnumVariantNames {
245+
fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
266246
let last = self.modules.pop();
267247
assert!(last.is_some());
268248
}
269249

270250
#[allow(clippy::similar_names)]
271-
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
251+
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
272252
let item_name = item.ident.name.as_str();
273253
let item_name_chars = item_name.chars().count();
274254
let item_camel = to_camel_case(&item_name);
@@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames {
286266
);
287267
}
288268
}
289-
if item.vis.kind.is_pub() {
269+
if item.vis.node.is_pub() {
290270
let matching = partial_match(mod_camel, &item_camel);
291271
let rmatching = partial_rmatch(mod_camel, &item_camel);
292272
let nchars = mod_camel.chars().count();
@@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames {
317297
}
318298
}
319299
if let ItemKind::Enum(ref def, _) = item.kind {
320-
let lint = match item.vis.kind {
321-
VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES,
322-
_ => ENUM_VARIANT_NAMES,
323-
};
324-
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint);
300+
if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) {
301+
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
302+
}
325303
}
326304
self.modules.push((item.ident.name, item_camel));
327305
}

clippy_lints/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
505505
"clippy::filter_map",
506506
"this lint has been replaced by `manual_filter_map`, a more specific lint",
507507
);
508+
store.register_removed(
509+
"clippy::pub_enum_variant_names",
510+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
511+
);
508512
store.register_removed(
509513
"clippy::wrong_pub_self_convention",
510514
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
@@ -622,7 +626,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
622626
enum_variants::ENUM_VARIANT_NAMES,
623627
enum_variants::MODULE_INCEPTION,
624628
enum_variants::MODULE_NAME_REPETITIONS,
625-
enum_variants::PUB_ENUM_VARIANT_NAMES,
626629
eq_op::EQ_OP,
627630
eq_op::OP_REF,
628631
erasing_op::ERASING_OP,
@@ -1080,7 +1083,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10801083
LintId::of(doc::MISSING_PANICS_DOC),
10811084
LintId::of(empty_enum::EMPTY_ENUM),
10821085
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
1083-
LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
10841086
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
10851087
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
10861088
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
@@ -2015,7 +2017,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
20152017
let literal_representation_threshold = conf.literal_representation_threshold;
20162018
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
20172019
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
2018-
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
2020+
store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api));
20192021
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
20202022
let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
20212023
store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive));

tests/ui/enum_variants.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#![feature(non_ascii_idents)]
2-
#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)]
1+
#![warn(clippy::enum_variant_names)]
32
#![allow(non_camel_case_types, clippy::upper_case_acronyms)]
43

54
enum FakeCallType {
@@ -97,8 +96,8 @@ pub enum PubSeall {
9796
WithOut,
9897
}
9998

100-
#[allow(clippy::pub_enum_variant_names)]
101-
mod allowed {
99+
#[allow(clippy::enum_variant_names)]
100+
pub mod allowed {
102101
pub enum PubAllowed {
103102
SomeThis,
104103
SomeThat,

tests/ui/enum_variants.stderr

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
error: variant name ends with the enum's name
2-
--> $DIR/enum_variants.rs:16:5
2+
--> $DIR/enum_variants.rs:15:5
33
|
44
LL | cFoo,
55
| ^^^^
66
|
77
= note: `-D clippy::enum-variant-names` implied by `-D warnings`
88

99
error: variant name starts with the enum's name
10-
--> $DIR/enum_variants.rs:27:5
10+
--> $DIR/enum_variants.rs:26:5
1111
|
1212
LL | FoodGood,
1313
| ^^^^^^^^
1414

1515
error: variant name starts with the enum's name
16-
--> $DIR/enum_variants.rs:28:5
16+
--> $DIR/enum_variants.rs:27:5
1717
|
1818
LL | FoodMiddle,
1919
| ^^^^^^^^^^
2020

2121
error: variant name starts with the enum's name
22-
--> $DIR/enum_variants.rs:29:5
22+
--> $DIR/enum_variants.rs:28:5
2323
|
2424
LL | FoodBad,
2525
| ^^^^^^^
2626

2727
error: all variants have the same prefix: `Food`
28-
--> $DIR/enum_variants.rs:26:1
28+
--> $DIR/enum_variants.rs:25:1
2929
|
3030
LL | / enum Food {
3131
LL | | FoodGood,
@@ -37,7 +37,7 @@ LL | | }
3737
= help: remove the prefixes and use full paths to the variants instead of glob imports
3838

3939
error: all variants have the same prefix: `CallType`
40-
--> $DIR/enum_variants.rs:36:1
40+
--> $DIR/enum_variants.rs:35:1
4141
|
4242
LL | / enum BadCallType {
4343
LL | | CallTypeCall,
@@ -49,7 +49,7 @@ LL | | }
4949
= help: remove the prefixes and use full paths to the variants instead of glob imports
5050

5151
error: all variants have the same prefix: `Constant`
52-
--> $DIR/enum_variants.rs:48:1
52+
--> $DIR/enum_variants.rs:47:1
5353
|
5454
LL | / enum Consts {
5555
LL | | ConstantInt,
@@ -61,7 +61,7 @@ LL | | }
6161
= help: remove the prefixes and use full paths to the variants instead of glob imports
6262

6363
error: all variants have the same prefix: `With`
64-
--> $DIR/enum_variants.rs:82:1
64+
--> $DIR/enum_variants.rs:81:1
6565
|
6666
LL | / enum Seallll {
6767
LL | | WithOutCake,
@@ -73,7 +73,7 @@ LL | | }
7373
= help: remove the prefixes and use full paths to the variants instead of glob imports
7474

7575
error: all variants have the same prefix: `Prefix`
76-
--> $DIR/enum_variants.rs:88:1
76+
--> $DIR/enum_variants.rs:87:1
7777
|
7878
LL | / enum NonCaps {
7979
LL | | Prefix的,
@@ -84,21 +84,8 @@ LL | | }
8484
|
8585
= help: remove the prefixes and use full paths to the variants instead of glob imports
8686

87-
error: all variants have the same prefix: `With`
88-
--> $DIR/enum_variants.rs:94:1
89-
|
90-
LL | / pub enum PubSeall {
91-
LL | | WithOutCake,
92-
LL | | WithOutTea,
93-
LL | | WithOut,
94-
LL | | }
95-
| |_^
96-
|
97-
= note: `-D clippy::pub-enum-variant-names` implied by `-D warnings`
98-
= help: remove the prefixes and use full paths to the variants instead of glob imports
99-
10087
error: all variants have the same postfix: `IData`
101-
--> $DIR/enum_variants.rs:137:1
88+
--> $DIR/enum_variants.rs:136:1
10289
|
10390
LL | / enum IDataRequest {
10491
LL | | PutIData(String),
@@ -110,7 +97,7 @@ LL | | }
11097
= help: remove the postfixes and use full paths to the variants instead of glob imports
11198

11299
error: all variants have the same postfix: `HIData`
113-
--> $DIR/enum_variants.rs:143:1
100+
--> $DIR/enum_variants.rs:142:1
114101
|
115102
LL | / enum HIDataRequest {
116103
LL | | PutHIData(String),
@@ -121,5 +108,5 @@ LL | | }
121108
|
122109
= help: remove the postfixes and use full paths to the variants instead of glob imports
123110

124-
error: aborting due to 12 previous errors
111+
error: aborting due to 11 previous errors
125112

0 commit comments

Comments
 (0)