Skip to content

Commit 4f23676

Browse files
committed
Add configuration options
1 parent ce02c8a commit 4f23676

File tree

14 files changed

+663
-38
lines changed

14 files changed

+663
-38
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5422,4 +5422,6 @@ Released 2018-09-13
54225422
[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
54235423
[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
54245424
[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
5425+
[`absolute-symbol-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-symbol-paths-max-segments
5426+
[`absolute-symbol-paths-allow-std`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-symbol-paths-allow-std
54255427
<!-- end autogenerated links to configuration documentation -->

book/src/lint_configuration.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,3 +729,23 @@ Whether to allow `r#""#` when `r""` can be used
729729
* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
730730

731731

732+
## `absolute-symbol-paths-max-segments`
733+
The max number of segments a path can have before being linted
734+
735+
**Default Value:** `3` (`u64`)
736+
737+
---
738+
**Affected lints:**
739+
* [`absolute_symbol_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_symbol_paths)
740+
741+
742+
## `absolute-symbol-paths-allow-std`
743+
Whether to allow paths originating from `core`/`std`/`alloc`
744+
745+
**Default Value:** `false` (`bool`)
746+
747+
---
748+
**Affected lints:**
749+
* [`absolute_symbol_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_symbol_paths)
750+
751+

clippy_lints/src/absolute_symbol_paths.rs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use clippy_utils::diagnostics::span_lint;
22
use clippy_utils::is_from_proc_macro;
33
use rustc_hir::intravisit::{walk_qpath, Visitor};
4-
use rustc_hir::{HirId, QPath};
4+
use rustc_hir::{def_id::LOCAL_CRATE, HirId, QPath};
55
use rustc_lint::{LateContext, LateLintPass};
66
use rustc_middle::hir::nested_filter::OnlyBodies;
7-
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
use rustc_session::{declare_tool_lint, impl_lint_pass};
88
use rustc_span::Span;
9+
use std::iter::once;
910

1011
declare_clippy_lint! {
1112
/// ### What it does
@@ -39,16 +40,32 @@ declare_clippy_lint! {
3940
style,
4041
"checks for usage of a symbol without a `use` statement"
4142
}
42-
declare_lint_pass!(AbsoluteSymbolPaths => [ABSOLUTE_SYMBOL_PATHS]);
43+
impl_lint_pass!(AbsoluteSymbolPaths => [ABSOLUTE_SYMBOL_PATHS]);
44+
45+
pub struct AbsoluteSymbolPaths {
46+
pub absolute_symbol_paths_max_segments: u64,
47+
pub absolute_symbol_paths_allow_std: bool,
48+
}
4349

4450
impl LateLintPass<'_> for AbsoluteSymbolPaths {
4551
fn check_crate(&mut self, cx: &LateContext<'_>) {
46-
cx.tcx.hir().visit_all_item_likes_in_crate(&mut V { cx });
52+
let Self {
53+
absolute_symbol_paths_max_segments,
54+
absolute_symbol_paths_allow_std,
55+
} = *self;
56+
57+
cx.tcx.hir().visit_all_item_likes_in_crate(&mut V {
58+
cx,
59+
absolute_symbol_paths_max_segments,
60+
absolute_symbol_paths_allow_std,
61+
});
4762
}
4863
}
4964

5065
struct V<'a, 'tcx> {
5166
cx: &'a LateContext<'tcx>,
67+
absolute_symbol_paths_max_segments: u64,
68+
absolute_symbol_paths_allow_std: bool,
5269
}
5370

5471
impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
@@ -58,29 +75,43 @@ impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
5875
self.cx.tcx.hir()
5976
}
6077

78+
#[expect(clippy::cast_possible_truncation)]
6179
fn visit_qpath(&mut self, qpath: &'tcx QPath<'tcx>, hir_id: HirId, span: Span) {
62-
let Self { cx } = *self;
80+
let Self {
81+
cx,
82+
absolute_symbol_paths_max_segments,
83+
absolute_symbol_paths_allow_std,
84+
} = *self;
6385

6486
if !span.from_expansion()
6587
&& let QPath::Resolved(_, path) = qpath
6688
&& let Some(def_id) = path.res.opt_def_id()
89+
&& let def_path = cx.tcx.def_path(def_id)
90+
&& let crate_name = cx.tcx.crate_name(def_path.krate)
91+
&& let segments = once(crate_name)
92+
.chain(def_path.data.iter().filter_map(|segment| segment.data.get_opt_name()))
93+
&& path.segments.len() > absolute_symbol_paths_max_segments as usize
94+
&& let is_std = matches!(crate_name.as_str(), "alloc" | "core" | "std")
95+
&& !(absolute_symbol_paths_allow_std && is_std)
96+
// If this is local, keep the crate name, if it is not, remove it, as we don't need to
97+
// check that (and results in FNs on reexports from one crate to another)
98+
//
99+
// `def_path_str` handles this for us, but unfortunately requires converting every
100+
// `Symbol` to a `&str`, which is a very slow operation.
101+
&& segments.skip(1).eq(
102+
path.segments.iter()
103+
// I love clippy :)
104+
.skip(usize::from(def_path.krate != LOCAL_CRATE))
105+
.map(|segment| segment.ident.name)
106+
)
107+
&& !is_from_proc_macro(cx, qpath)
67108
{
68-
let def_path = cx.tcx.def_path_str(def_id);
69-
let segments = def_path.split("::");
70-
71-
// FIXME: I only allowed 3 segment paths because there's tons of them in clippy :D
72-
// To my humble reviewer: thoughts?
73-
if path.segments.len() >= 4 // A 2 segment path seems okay, like `std::println!`
74-
&& segments.eq(path.segments.iter().map(|segment| segment.ident.name.as_str()))
75-
&& !is_from_proc_macro(cx, qpath)
76-
{
77-
span_lint(
78-
cx,
79-
ABSOLUTE_SYMBOL_PATHS,
80-
span,
81-
"consider referring to this symbol by adding a `use` statement for consistent formatting",
82-
);
83-
}
109+
span_lint(
110+
cx,
111+
ABSOLUTE_SYMBOL_PATHS,
112+
span,
113+
"consider referring to this symbol by adding a `use` statement for consistent formatting",
114+
);
84115
}
85116

86117
walk_qpath(self, qpath, hir_id);

clippy_lints/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10791079
store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns));
10801080
store.register_early_pass(|| Box::new(visibility::Visibility));
10811081
store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
1082+
let absolute_symbol_paths_max_segments = conf.absolute_symbol_paths_max_segments;
1083+
let absolute_symbol_paths_allow_std = conf.absolute_symbol_paths_allow_std;
1084+
store.register_late_pass(move |_| {
1085+
Box::new(absolute_symbol_paths::AbsoluteSymbolPaths {
1086+
absolute_symbol_paths_max_segments,
1087+
absolute_symbol_paths_allow_std,
1088+
})
1089+
});
10821090
// add lints here, do not remove this comment, it's used in `new_lint`
10831091
}
10841092

clippy_lints/src/utils/conf.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,14 @@ define_Conf! {
551551
///
552552
/// Whether to allow `r#""#` when `r""` can be used
553553
(allow_one_hash_in_raw_strings: bool = false),
554+
/// Lint: ABSOLUTE_SYMBOL_PATHS.
555+
///
556+
/// The max number of segments a path can have before being linted
557+
(absolute_symbol_paths_max_segments: u64 = 3),
558+
/// Lint: ABSOLUTE_SYMBOL_PATHS.
559+
///
560+
/// Whether to allow paths originating from `core`/`std`/`alloc`
561+
(absolute_symbol_paths_allow_std: bool = false),
554562
}
555563

556564
/// Search for the configuration file.

clippy_utils/src/usage.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate as utils;
22
use crate::visitors::{for_each_expr, for_each_expr_with_closures, Descend};
33
use core::ops::ControlFlow;
4+
use hir::def::Res;
45
use rustc_hir as hir;
56
use rustc_hir::intravisit::{self, Visitor};
67
use rustc_hir::HirIdSet;
@@ -129,7 +130,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
129130
}
130131

131132
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
132-
if let hir::def::Res::Local(id) = path.res {
133+
if let Res::Local(id) = path.res {
133134
if self.binding_ids.contains(&id) {
134135
self.usage_found = true;
135136
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
2+
--> $DIR/absolute_symbol_paths.rs:40:5
3+
|
4+
LL | a::b::c::C;
5+
| ^^^^^^^^^^
6+
|
7+
= note: `-D clippy::absolute-symbol-paths` implied by `-D warnings`
8+
9+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
10+
--> $DIR/absolute_symbol_paths.rs:41:5
11+
|
12+
LL | a::b::c::d::e::f::F;
13+
| ^^^^^^^^^^^^^^^^^^^
14+
15+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
16+
--> $DIR/absolute_symbol_paths.rs:43:5
17+
|
18+
LL | a::b::B;
19+
| ^^^^^^^
20+
21+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
22+
--> $DIR/absolute_symbol_paths.rs:44:5
23+
|
24+
LL | a::b::c::C::ZERO;
25+
| ^^^^^^^^^^
26+
27+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
28+
--> $DIR/absolute_symbol_paths.rs:45:15
29+
|
30+
LL | fn b() -> a::b::B {
31+
| ^^^^^^^
32+
33+
error: aborting due to 5 previous errors
34+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
2+
--> $DIR/absolute_symbol_paths.rs:38:5
3+
|
4+
LL | std::f32::MAX;
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::absolute-symbol-paths` implied by `-D warnings`
8+
9+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
10+
--> $DIR/absolute_symbol_paths.rs:39:5
11+
|
12+
LL | core::f32::MAX;
13+
| ^^^^^^^^^^^^^^
14+
15+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
16+
--> $DIR/absolute_symbol_paths.rs:40:5
17+
|
18+
LL | a::b::c::C;
19+
| ^^^^^^^^^^
20+
21+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
22+
--> $DIR/absolute_symbol_paths.rs:41:5
23+
|
24+
LL | a::b::c::d::e::f::F;
25+
| ^^^^^^^^^^^^^^^^^^^
26+
27+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
28+
--> $DIR/absolute_symbol_paths.rs:43:5
29+
|
30+
LL | a::b::B;
31+
| ^^^^^^^
32+
33+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
34+
--> $DIR/absolute_symbol_paths.rs:44:5
35+
|
36+
LL | a::b::c::C::ZERO;
37+
| ^^^^^^^^^^
38+
39+
error: consider referring to this symbol by adding a `use` statement for consistent formatting
40+
--> $DIR/absolute_symbol_paths.rs:45:15
41+
|
42+
LL | fn b() -> a::b::B {
43+
| ^^^^^^^
44+
45+
error: aborting due to 7 previous errors
46+

tests/ui/absolute_symbol_paths.rs renamed to tests/ui-toml/absolute_symbol_paths/absolute_symbol_paths.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
//@aux-build:proc_macros.rs:proc-macro
2+
//@revisions: allow_std disallow_std
3+
//@[allow_std] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_symbol_paths/allow_std
4+
//@[disallow_std] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_symbol_paths/disallow_std
25
#![allow(clippy::no_effect, unused)]
36
#![warn(clippy::absolute_symbol_paths)]
47
#![feature(decl_macro)]
@@ -14,6 +17,14 @@ pub mod a {
1417
impl C {
1518
pub const ZERO: u32 = 0;
1619
}
20+
21+
pub mod d {
22+
pub mod e {
23+
pub mod f {
24+
pub struct F;
25+
}
26+
}
27+
}
1728
}
1829

1930
pub struct B;
@@ -27,6 +38,7 @@ fn main() {
2738
std::f32::MAX;
2839
core::f32::MAX;
2940
a::b::c::C;
41+
a::b::c::d::e::f::F;
3042
a::A;
3143
a::b::B;
3244
a::b::c::C::ZERO;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
absolute-symbol-paths-max-segments = 2
2+
absolute-symbol-paths-allow-std = true

0 commit comments

Comments
 (0)