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;
11 declare_clippy_lint! {
12 /// **What it does:** Checks for camel case name containing a capitalized acronym.
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)
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.
25 /// struct HTTPResponse;
29 /// struct HttpResponse;
31 pub UPPER_CASE_ACRONYMS,
33 "capitalized acronyms are against the naming convention"
36 declare_lint_pass!(UpperCaseAcronyms => [UPPER_CASE_ACRONYMS]);
38 fn correct_ident(ident: &str) -> String {
39 let ident = ident.chars().rev().collect::<String>();
41 .split_inclusive(|x: char| !x.is_ascii_lowercase())
43 .map(|x| x.chars().rev().collect::<String>());
45 let mut ident = fragments.clone().next().unwrap();
46 for (ref prev, ref curr) in fragments.tuple_windows() {
49 .all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase())
51 ident.push_str(&curr.to_ascii_lowercase());
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 {
68 &format!("name `{}` contains a capitalized acronym", ident),
69 "consider making the acronym lowercase, except the initial letter",
71 Applicability::MaybeIncorrect,
76 impl EarlyLintPass for UpperCaseAcronyms {
77 fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) {
79 if !in_external_macro(cx.sess(), it.span);
82 ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
85 check_ident(cx, &it.ident);
90 fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &Variant) {
91 check_ident(cx, &v.ident);