Skip to content

Commit e6665e4

Browse files
committed
Auto merge of rust-lang#6475 - matsujika:capitalized_acronyms, r=flip1995
Add new lint `upper_case_acronyms` Close rust-lang#1335 I need some reviews on the English sentences because I feel they're messed up. ;) changelog: Add new lint `upper_case_acronyms`
2 parents fb0d7f1 + 0ccb491 commit e6665e4

22 files changed

+255
-52
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,7 @@ Released 2018-09-13
22742274
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
22752275
[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
22762276
[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
2277+
[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
22772278
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
22782279
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
22792280
[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding

clippy_lints/src/cognitive_complexity.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ impl CognitiveComplexity {
5757

5858
let expr = &body.value;
5959

60-
let mut helper = CCHelper { cc: 1, returns: 0 };
60+
let mut helper = CcHelper { cc: 1, returns: 0 };
6161
helper.visit_expr(expr);
62-
let CCHelper { cc, returns } = helper;
62+
let CcHelper { cc, returns } = helper;
6363
let ret_ty = cx.typeck_results().node_type(expr.hir_id);
6464
let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::result_type) {
6565
returns
@@ -136,12 +136,12 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
136136
}
137137
}
138138

139-
struct CCHelper {
139+
struct CcHelper {
140140
cc: u64,
141141
returns: u64,
142142
}
143143

144-
impl<'tcx> Visitor<'tcx> for CCHelper {
144+
impl<'tcx> Visitor<'tcx> for CcHelper {
145145
type Map = Map<'tcx>;
146146

147147
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {

clippy_lints/src/int_plus_one.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ declare_lint_pass!(IntPlusOne => [INT_PLUS_ONE]);
4646

4747
#[derive(Copy, Clone)]
4848
enum Side {
49-
LHS,
50-
RHS,
49+
Lhs,
50+
Rhs,
5151
}
5252

5353
impl IntPlusOne {
@@ -66,11 +66,11 @@ impl IntPlusOne {
6666
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
6767
// `-1 + x`
6868
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
69-
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
69+
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
7070
},
7171
// `x - 1`
7272
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
73-
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
73+
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
7474
},
7575
_ => None,
7676
}
@@ -82,10 +82,10 @@ impl IntPlusOne {
8282
match (&rhslhs.kind, &rhsrhs.kind) {
8383
// `y + 1` and `1 + y`
8484
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
85-
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
85+
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
8686
},
8787
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
88-
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
88+
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
8989
},
9090
_ => None,
9191
}
@@ -97,10 +97,10 @@ impl IntPlusOne {
9797
match (&lhslhs.kind, &lhsrhs.kind) {
9898
// `1 + x` and `x + 1`
9999
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
100-
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
100+
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
101101
},
102102
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
103-
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
103+
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
104104
},
105105
_ => None,
106106
}
@@ -110,11 +110,11 @@ impl IntPlusOne {
110110
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
111111
// `-1 + y`
112112
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
113-
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
113+
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
114114
},
115115
// `y - 1`
116116
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
117-
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
117+
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
118118
},
119119
_ => None,
120120
}
@@ -138,8 +138,8 @@ impl IntPlusOne {
138138
if let Some(snippet) = snippet_opt(cx, node.span) {
139139
if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
140140
let rec = match side {
141-
Side::LHS => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)),
142-
Side::RHS => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)),
141+
Side::Lhs => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)),
142+
Side::Rhs => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)),
143143
};
144144
return rec;
145145
}

clippy_lints/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ mod unused_self;
341341
mod unused_unit;
342342
mod unwrap;
343343
mod unwrap_in_result;
344+
mod upper_case_acronyms;
344345
mod use_self;
345346
mod useless_conversion;
346347
mod vec;
@@ -944,6 +945,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
944945
&unwrap::PANICKING_UNWRAP,
945946
&unwrap::UNNECESSARY_UNWRAP,
946947
&unwrap_in_result::UNWRAP_IN_RESULT,
948+
&upper_case_acronyms::UPPER_CASE_ACRONYMS,
947949
&use_self::USE_SELF,
948950
&useless_conversion::USELESS_CONVERSION,
949951
&vec::USELESS_VEC,
@@ -983,7 +985,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
983985
}
984986
store.register_late_pass(|| box utils::author::Author);
985987
store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
986-
store.register_late_pass(|| box serde_api::SerdeAPI);
988+
store.register_late_pass(|| box serde_api::SerdeApi);
987989
let vec_box_size_threshold = conf.vec_box_size_threshold;
988990
store.register_late_pass(move || box types::Types::new(vec_box_size_threshold));
989991
store.register_late_pass(|| box booleans::NonminimalBool);
@@ -1174,6 +1176,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11741176
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
11751177
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
11761178
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
1179+
store.register_early_pass(|| box upper_case_acronyms::UpperCaseAcronyms);
11771180
store.register_late_pass(|| box default::Default::default());
11781181
store.register_late_pass(|| box unused_self::UnusedSelf);
11791182
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
@@ -1659,6 +1662,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16591662
LintId::of(&unused_unit::UNUSED_UNIT),
16601663
LintId::of(&unwrap::PANICKING_UNWRAP),
16611664
LintId::of(&unwrap::UNNECESSARY_UNWRAP),
1665+
LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS),
16621666
LintId::of(&useless_conversion::USELESS_CONVERSION),
16631667
LintId::of(&vec::USELESS_VEC),
16641668
LintId::of(&vec_init_then_push::VEC_INIT_THEN_PUSH),
@@ -1776,6 +1780,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
17761780
LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
17771781
LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
17781782
LintId::of(&unused_unit::UNUSED_UNIT),
1783+
LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS),
17791784
LintId::of(&write::PRINTLN_EMPTY_STRING),
17801785
LintId::of(&write::PRINT_LITERAL),
17811786
LintId::of(&write::PRINT_WITH_NEWLINE),

clippy_lints/src/serde_api.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ declare_clippy_lint! {
1818
"various things that will negatively affect your serde experience"
1919
}
2020

21-
declare_lint_pass!(SerdeAPI => [SERDE_API_MISUSE]);
21+
declare_lint_pass!(SerdeApi => [SERDE_API_MISUSE]);
2222

23-
impl<'tcx> LateLintPass<'tcx> for SerdeAPI {
23+
impl<'tcx> LateLintPass<'tcx> for SerdeApi {
2424
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
2525
if let ItemKind::Impl(Impl {
2626
of_trait: Some(ref trait_ref),
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::utils::span_lint_and_sugg;
2+
use if_chain::if_chain;
3+
use itertools::Itertools;
4+
use rustc_ast::ast::{Item, ItemKind, Variant};
5+
use rustc_errors::Applicability;
6+
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
7+
use rustc_middle::lint::in_external_macro;
8+
use rustc_session::{declare_lint_pass, declare_tool_lint};
9+
use rustc_span::symbol::Ident;
10+
11+
declare_clippy_lint! {
12+
/// **What it does:** Checks for camel case name containing a capitalized acronym.
13+
///
14+
/// **Why is this bad?** In CamelCase, acronyms count as one word.
15+
/// See [naming conventions](https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case)
16+
/// for more.
17+
///
18+
/// **Known problems:** When two acronyms are contiguous, the lint can't tell where
19+
/// the first acronym ends and the second starts, so it suggests to lowercase all of
20+
/// the letters in the second acronym.
21+
///
22+
/// **Example:**
23+
///
24+
/// ```rust
25+
/// struct HTTPResponse;
26+
/// ```
27+
/// Use instead:
28+
/// ```rust
29+
/// struct HttpResponse;
30+
/// ```
31+
pub UPPER_CASE_ACRONYMS,
32+
style,
33+
"capitalized acronyms are against the naming convention"
34+
}
35+
36+
declare_lint_pass!(UpperCaseAcronyms => [UPPER_CASE_ACRONYMS]);
37+
38+
fn correct_ident(ident: &str) -> String {
39+
let ident = ident.chars().rev().collect::<String>();
40+
let fragments = ident
41+
.split_inclusive(|x: char| !x.is_ascii_lowercase())
42+
.rev()
43+
.map(|x| x.chars().rev().collect::<String>());
44+
45+
let mut ident = fragments.clone().next().unwrap();
46+
for (ref prev, ref curr) in fragments.tuple_windows() {
47+
if [prev, curr]
48+
.iter()
49+
.all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase())
50+
{
51+
ident.push_str(&curr.to_ascii_lowercase());
52+
} else {
53+
ident.push_str(curr);
54+
}
55+
}
56+
ident
57+
}
58+
59+
fn check_ident(cx: &EarlyContext<'_>, ident: &Ident) {
60+
let span = ident.span;
61+
let ident = &ident.as_str();
62+
let corrected = correct_ident(ident);
63+
if ident != &corrected {
64+
span_lint_and_sugg(
65+
cx,
66+
UPPER_CASE_ACRONYMS,
67+
span,
68+
&format!("name `{}` contains a capitalized acronym", ident),
69+
"consider making the acronym lowercase, except the initial letter",
70+
corrected,
71+
Applicability::MaybeIncorrect,
72+
)
73+
}
74+
}
75+
76+
impl EarlyLintPass for UpperCaseAcronyms {
77+
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) {
78+
if_chain! {
79+
if !in_external_macro(cx.sess(), it.span);
80+
if matches!(
81+
it.kind,
82+
ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
83+
);
84+
then {
85+
check_ident(cx, &it.ident);
86+
}
87+
}
88+
}
89+
90+
fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &Variant) {
91+
check_ident(cx, &v.ident);
92+
}
93+
}

tests/ui/complex_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct S {
1111
f: Vec<Vec<Box<(u32, u32, u32, u32)>>>,
1212
}
1313

14-
struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
14+
struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
1515

1616
enum E {
1717
Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>),

tests/ui/complex_types.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | f: Vec<Vec<Box<(u32, u32, u32, u32)>>>,
2121
error: very complex type used. Consider factoring parts into `type` definitions
2222
--> $DIR/complex_types.rs:14:11
2323
|
24-
LL | struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
24+
LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

2727
error: very complex type used. Consider factoring parts into `type` definitions

tests/ui/crashes/ice-6256.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// originally from rustc ./src/test/ui/regions/issue-78262.rs
22
// ICE: to get the signature of a closure, use substs.as_closure().sig() not fn_sig()
3+
#![allow(clippy::upper_case_acronyms)]
34

45
trait TT {}
56

tests/ui/crashes/ice-6256.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0308]: mismatched types
2-
--> $DIR/ice-6256.rs:11:28
2+
--> $DIR/ice-6256.rs:12:28
33
|
44
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
55
| ^^^^ lifetime mismatch
66
|
77
= note: expected reference `&(dyn TT + 'static)`
88
found reference `&dyn TT`
9-
note: the anonymous lifetime #1 defined on the body at 11:13...
10-
--> $DIR/ice-6256.rs:11:13
9+
note: the anonymous lifetime #1 defined on the body at 12:13...
10+
--> $DIR/ice-6256.rs:12:13
1111
|
1212
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
1313
| ^^^^^^^^^^^^^^^^^^^^^

tests/ui/enum_variants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(non_ascii_idents)]
22
#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)]
3-
#![allow(non_camel_case_types)]
3+
#![allow(non_camel_case_types, clippy::upper_case_acronyms)]
44

55
enum FakeCallType {
66
CALL,

tests/ui/needless_question_mark.fixed

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// run-rustfix
22

33
#![warn(clippy::needless_question_mark)]
4-
#![allow(clippy::needless_return, clippy::unnecessary_unwrap, dead_code, unused_must_use)]
4+
#![allow(
5+
clippy::needless_return,
6+
clippy::unnecessary_unwrap,
7+
clippy::upper_case_acronyms,
8+
dead_code,
9+
unused_must_use
10+
)]
511
#![feature(custom_inner_attributes)]
612

713
struct TO {

tests/ui/needless_question_mark.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// run-rustfix
22

33
#![warn(clippy::needless_question_mark)]
4-
#![allow(clippy::needless_return, clippy::unnecessary_unwrap, dead_code, unused_must_use)]
4+
#![allow(
5+
clippy::needless_return,
6+
clippy::unnecessary_unwrap,
7+
clippy::upper_case_acronyms,
8+
dead_code,
9+
unused_must_use
10+
)]
511
#![feature(custom_inner_attributes)]
612

713
struct TO {

0 commit comments

Comments
 (0)