mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Fix ICE in upper_case_acronyms
and remove most of the string allocations.
This commit is contained in:
parent
0ea88b90d8
commit
059eaf1386
2 changed files with 69 additions and 43 deletions
|
@ -1,5 +1,5 @@
|
||||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||||
use itertools::Itertools;
|
use core::mem::replace;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{HirId, Item, ItemKind};
|
use rustc_hir::{HirId, Item, ItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
|
@ -56,55 +56,71 @@ impl UpperCaseAcronyms {
|
||||||
|
|
||||||
impl_lint_pass!(UpperCaseAcronyms => [UPPER_CASE_ACRONYMS]);
|
impl_lint_pass!(UpperCaseAcronyms => [UPPER_CASE_ACRONYMS]);
|
||||||
|
|
||||||
fn correct_ident(ident: &str) -> String {
|
fn contains_acronym(s: &str) -> bool {
|
||||||
let ident = ident.chars().rev().collect::<String>();
|
let mut count = 0;
|
||||||
let fragments = ident
|
for c in s.chars() {
|
||||||
.split_inclusive(|x: char| !x.is_ascii_lowercase())
|
if c.is_ascii_uppercase() {
|
||||||
.rev()
|
count += 1;
|
||||||
.map(|x| x.chars().rev().collect::<String>());
|
if count == 3 {
|
||||||
|
return true;
|
||||||
let mut ident = fragments.clone().next().unwrap();
|
}
|
||||||
for (ref prev, ref curr) in fragments.tuple_windows() {
|
|
||||||
if <[&String; 2]>::from((prev, curr))
|
|
||||||
.iter()
|
|
||||||
.all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase())
|
|
||||||
{
|
|
||||||
ident.push_str(&curr.to_ascii_lowercase());
|
|
||||||
} else {
|
} else {
|
||||||
ident.push_str(curr);
|
count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ident
|
count == 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive: bool) {
|
fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive: bool) {
|
||||||
let span = ident.span;
|
let s = ident.as_str();
|
||||||
let ident = ident.as_str();
|
|
||||||
let corrected = correct_ident(ident);
|
// By default, only warn for upper case identifiers with at least 3 characters.
|
||||||
// warn if we have pure-uppercase idents
|
let replacement = if s.len() > 2 && s.bytes().all(|c| c.is_ascii_uppercase()) {
|
||||||
// assume that two-letter words are some kind of valid abbreviation like FP for false positive
|
let mut r = String::with_capacity(s.len());
|
||||||
// (and don't warn)
|
let mut s = s.chars();
|
||||||
if (ident.chars().all(|c| c.is_ascii_uppercase()) && ident.len() > 2)
|
r.push(s.next().unwrap());
|
||||||
// otherwise, warn if we have SOmeTHING lIKE THIs but only warn with the aggressive
|
r.extend(s.map(|c| c.to_ascii_lowercase()));
|
||||||
// upper-case-acronyms-aggressive config option enabled
|
r
|
||||||
|| (be_aggressive && ident != corrected)
|
} else if be_aggressive
|
||||||
|
// Only lint if the ident starts with an upper case character.
|
||||||
|
&& let unprefixed = s.trim_start_matches('_')
|
||||||
|
&& unprefixed.starts_with(|c: char| c.is_ascii_uppercase())
|
||||||
|
&& contains_acronym(unprefixed)
|
||||||
{
|
{
|
||||||
span_lint_hir_and_then(
|
let mut r = String::with_capacity(s.len());
|
||||||
cx,
|
let mut s = s.chars();
|
||||||
UPPER_CASE_ACRONYMS,
|
let mut prev_upper = false;
|
||||||
hir_id,
|
while let Some(c) = s.next() {
|
||||||
span,
|
r.push(
|
||||||
format!("name `{ident}` contains a capitalized acronym"),
|
if replace(&mut prev_upper, c.is_ascii_uppercase())
|
||||||
|diag| {
|
&& s.clone().next().map_or(true, |c| c.is_ascii_uppercase())
|
||||||
diag.span_suggestion(
|
{
|
||||||
span,
|
c.to_ascii_lowercase()
|
||||||
"consider making the acronym lowercase, except the initial letter",
|
} else {
|
||||||
corrected,
|
c
|
||||||
Applicability::MaybeIncorrect,
|
},
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
);
|
r
|
||||||
}
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint_hir_and_then(
|
||||||
|
cx,
|
||||||
|
UPPER_CASE_ACRONYMS,
|
||||||
|
hir_id,
|
||||||
|
ident.span,
|
||||||
|
format!("name `{ident}` contains a capitalized acronym"),
|
||||||
|
|diag| {
|
||||||
|
diag.span_suggestion(
|
||||||
|
ident.span,
|
||||||
|
"consider making the acronym lowercase, except the initial letter",
|
||||||
|
replacement,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass<'_> for UpperCaseAcronyms {
|
impl LateLintPass<'_> for UpperCaseAcronyms {
|
||||||
|
|
10
tests/ui/crashes/ice-12284.rs
Normal file
10
tests/ui/crashes/ice-12284.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(unnamed_fields)]
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct Foo {
|
||||||
|
_: struct {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in a new issue