Skip to content

Commit bd3b54b

Browse files
committed
Add lint long_variable_names
The lint is configurable by using `max-variable-name-length` and it is set to 100 by default.
1 parent 40bead0 commit bd3b54b

File tree

10 files changed

+135
-0
lines changed

10 files changed

+135
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5938,6 +5938,7 @@ Released 2018-09-13
59385938
[`literal_string_with_formatting_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#literal_string_with_formatting_args
59395939
[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes
59405940
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
5941+
[`long_variable_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#long_variable_names
59415942
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
59425943
[`macro_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe
59435944
[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
@@ -6535,6 +6536,7 @@ Released 2018-09-13
65356536
[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools
65366537
[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length
65376538
[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
6539+
[`max-variable-name-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-variable-name-length
65386540
[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
65396541
[`missing-docs-allow-unused`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-allow-unused
65406542
[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items

book/src/lint_configuration.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,16 @@ The maximum number of bounds a trait can have to be linted
734734
* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
735735

736736

737+
## `max-variable-name-length`
738+
The maximum length of a variable
739+
740+
**Default Value:** `100`
741+
742+
---
743+
**Affected lints:**
744+
* [`long_variable_names`](https://rust-lang.github.io/rust-clippy/master/index.html#long_variable_names)
745+
746+
737747
## `min-ident-chars-threshold`
738748
Minimum chars an ident can have, anything below or equal to this will be linted.
739749

clippy_config/src/conf.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,9 @@ define_Conf! {
675675
/// The maximum number of bounds a trait can have to be linted
676676
#[lints(type_repetition_in_bounds)]
677677
max_trait_bounds: u64 = 3,
678+
/// The maximum length of a variable
679+
#[lints(long_variable_names)]
680+
max_variable_name_length: u32 = 100,
678681
/// Minimum chars an ident can have, anything below or equal to this will be linted.
679682
#[lints(min_ident_chars)]
680683
min_ident_chars_threshold: u64 = 1,

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
260260
crate::literal_representation::UNREADABLE_LITERAL_INFO,
261261
crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO,
262262
crate::literal_string_with_formatting_args::LITERAL_STRING_WITH_FORMATTING_ARGS_INFO,
263+
crate::long_variable_names::LONG_VARIABLE_NAMES_INFO,
263264
crate::loops::CHAR_INDICES_AS_BYTE_INDICES_INFO,
264265
crate::loops::EMPTY_LOOP_INFO,
265266
crate::loops::EXPLICIT_COUNTER_LOOP_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ mod lifetimes;
199199
mod lines_filter_map_ok;
200200
mod literal_representation;
201201
mod literal_string_with_formatting_args;
202+
mod long_variable_names;
202203
mod loops;
203204
mod macro_metavars_in_unsafe;
204205
mod macro_use;
@@ -944,5 +945,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
944945
store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap));
945946
store.register_late_pass(move |_| Box::new(redundant_test_prefix::RedundantTestPrefix));
946947
store.register_late_pass(|_| Box::new(cloned_ref_to_slice_refs::ClonedRefToSliceRefs::new(conf)));
948+
store.register_late_pass(move |_| Box::new(long_variable_names::LongVariableNames::new(conf)));
947949
// add lints here, do not remove this comment, it's used in `new_lint`
948950
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::rustc_lint::LintContext;
2+
use crate::rustc_span::Pos;
3+
use clippy_config::Conf;
4+
use clippy_utils::diagnostics::span_lint_and_help;
5+
use rustc_hir::{Pat, PatKind};
6+
use rustc_lint::{LateContext, LateLintPass};
7+
use rustc_session::impl_lint_pass;
8+
9+
declare_clippy_lint! {
10+
/// ### What it does
11+
/// Checks for variable that exceeds a configurable number characters.
12+
///
13+
/// ### Why is this bad?
14+
/// Long variable names can make code harder to read and thus to maintain.
15+
///
16+
/// ### Example
17+
/// ```no_run
18+
/// let ferris_fixes_more_bugs_than_your_entire_devops_team_does = "content of a string";
19+
/// ```
20+
/// Use instead:
21+
/// ```no_run
22+
/// let ferris_fixes_more_bugs = "content of a string";
23+
/// ```
24+
#[clippy::version = "1.88.0"]
25+
pub LONG_VARIABLE_NAMES,
26+
style,
27+
"usage of a long variable"
28+
}
29+
pub struct LongVariableNames {
30+
pub max_variable_name_length: u32,
31+
}
32+
33+
impl LongVariableNames {
34+
pub fn new(conf: &'static Conf) -> Self {
35+
Self {
36+
max_variable_name_length: conf.max_variable_name_length,
37+
}
38+
}
39+
}
40+
41+
impl_lint_pass!(LongVariableNames => [LONG_VARIABLE_NAMES]);
42+
43+
impl<'tcx> LateLintPass<'tcx> for LongVariableNames {
44+
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
45+
if let PatKind::Binding(.., ident, _) = pat.kind {
46+
let length_bytes = if ident.span.from_expansion() {
47+
// since the span can't be calculated, we can't lint this
48+
// so we just return
49+
return;
50+
} else {
51+
let higher_bound = cx.sess().source_map().lookup_char_pos(ident.span.hi()).col;
52+
let lower_bound = cx.sess().source_map().lookup_char_pos(ident.span.lo()).col;
53+
(higher_bound - lower_bound).to_u32() + 1
54+
};
55+
if length_bytes > self.max_variable_name_length {
56+
let variable_name_length = u32::try_from(ident.name.to_ident_string().chars().count())
57+
.expect("the variable name length exceeds u32::MAX");
58+
if variable_name_length > self.max_variable_name_length {
59+
let length_diff = variable_name_length - self.max_variable_name_length;
60+
61+
span_lint_and_help(
62+
cx,
63+
LONG_VARIABLE_NAMES,
64+
ident.span,
65+
format!(
66+
"variable name is longer than the configured `max-variable-name-length` of ({} characters)",
67+
self.max_variable_name_length
68+
),
69+
None,
70+
format!("reduce the length of the variable name with at least {length_diff} characters"),
71+
);
72+
}
73+
}
74+
}
75+
}
76+
}

tests/clippy.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
# default config for tests, overrides clippy.toml at the project root
22
lint-commented-code = false
3+
4+
# override the default length of variables to test the configuration
5+
max-variable-name-length = 50

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
5757
max-struct-bools
5858
max-suggested-slice-pattern-length
5959
max-trait-bounds
60+
max-variable-name-length
6061
min-ident-chars-threshold
6162
missing-docs-allow-unused
6263
missing-docs-in-crate-items
@@ -151,6 +152,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
151152
max-struct-bools
152153
max-suggested-slice-pattern-length
153154
max-trait-bounds
155+
max-variable-name-length
154156
min-ident-chars-threshold
155157
missing-docs-allow-unused
156158
missing-docs-in-crate-items
@@ -245,6 +247,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
245247
max-struct-bools
246248
max-suggested-slice-pattern-length
247249
max-trait-bounds
250+
max-variable-name-length
248251
min-ident-chars-threshold
249252
missing-docs-allow-unused
250253
missing-docs-in-crate-items

tests/ui/long_variable_names.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![warn(clippy::long_variable_names)]
2+
3+
fn a_function(ferris_singlehandedly_refactored_the_monolith_while_juggling_crates_and_lifetimes: &str) {
4+
//~^ long_variable_names
5+
}
6+
7+
fn another_function(just_a_short_name: &str) {
8+
// should not cause a problem
9+
}
10+
11+
fn main() {
12+
// `ferris_singlehandedly_refactored_the_monolith_while_juggling_crates_and_lifetimes` is too long
13+
let ferris_singlehandedly_refactored_the_monolith_while_juggling_crates_and_lifetimes = "very long indeed";
14+
//~^ long_variable_names
15+
}

tests/ui/long_variable_names.stderr

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: variable name is longer than the configured `max-variable-name-length` of (50 characters)
2+
--> tests/ui/long_variable_names.rs:3:15
3+
|
4+
LL | fn a_function(ferris_singlehandedly_refactored_the_monolith_while_juggling_crates_and_lifetimes: &str) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: reduce the length of the variable name with at least 31 characters
8+
= note: `-D clippy::long-variable-names` implied by `-D warnings`
9+
= help: to override `-D warnings` add `#[allow(clippy::long_variable_names)]`
10+
11+
error: variable name is longer than the configured `max-variable-name-length` of (50 characters)
12+
--> tests/ui/long_variable_names.rs:13:9
13+
|
14+
LL | let ferris_singlehandedly_refactored_the_monolith_while_juggling_crates_and_lifetimes = "very long indeed";
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= help: reduce the length of the variable name with at least 31 characters
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)