1 use clippy_utils
::diagnostics
::{span_lint_and_help, span_lint_and_sugg}
;
2 use rustc_ast
::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind, VisibilityKind}
;
3 use rustc_errors
::Applicability
;
4 use rustc_lint
::{EarlyContext, EarlyLintPass, LintContext}
;
5 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
6 use rustc_span
::{edition::Edition, symbol::kw, Span, Symbol}
;
10 /// Checking for imports with single component use path.
12 /// ### Why is this bad?
13 /// Import with single component use path such as `use cratename;`
14 /// is not necessary, and thus should be removed.
21 /// regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
27 /// regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
30 #[clippy::version = "1.43.0"]
31 pub SINGLE_COMPONENT_PATH_IMPORTS
,
33 "imports with single component path are redundant"
36 declare_lint_pass
!(SingleComponentPathImports
=> [SINGLE_COMPONENT_PATH_IMPORTS
]);
38 impl EarlyLintPass
for SingleComponentPathImports
{
39 fn check_crate(&mut self, cx
: &EarlyContext
<'_
>, krate
: &Crate
) {
40 if cx
.sess().opts
.edition
< Edition
::Edition2018
{
43 check_mod(cx
, &krate
.items
);
47 fn check_mod(cx
: &EarlyContext
<'_
>, items
: &[P
<Item
>]) {
48 // keep track of imports reused with `self` keyword,
49 // such as `self::crypto_hash` in the example below
51 // use self::crypto_hash::{Algorithm, Hasher};
53 let mut imports_reused_with_self
= Vec
::new();
55 // keep track of single use statements
56 // such as `crypto_hash` in the example below
60 let mut single_use_usages
= Vec
::new();
62 // keep track of macros defined in the module as we don't want it to trigger on this (#7106)
64 // macro_rules! foo { () => {} };
65 // pub(crate) use foo;
67 let mut macros
= Vec
::new();
73 &mut imports_reused_with_self
,
74 &mut single_use_usages
,
79 for single_use
in &single_use_usages
{
80 if !imports_reused_with_self
.contains(&single_use
.0) {
81 let can_suggest
= single_use
.2;
85 SINGLE_COMPONENT_PATH_IMPORTS
,
87 "this import is redundant",
90 Applicability
::MachineApplicable
,
95 SINGLE_COMPONENT_PATH_IMPORTS
,
97 "this import is redundant",
107 cx
: &EarlyContext
<'_
>,
109 imports_reused_with_self
: &mut Vec
<Symbol
>,
110 single_use_usages
: &mut Vec
<(Symbol
, Span
, bool
)>,
111 macros
: &mut Vec
<Symbol
>,
113 if item
.span
.from_expansion() || item
.vis
.kind
.is_pub() {
118 ItemKind
::Mod(_
, ModKind
::Loaded(ref items
, ..)) => {
119 check_mod(cx
, items
);
121 ItemKind
::MacroDef(MacroDef { macro_rules: true, .. }
) => {
122 macros
.push(item
.ident
.name
);
124 ItemKind
::Use(use_tree
) => {
125 let segments
= &use_tree
.prefix
.segments
;
128 |name
: &Symbol
| !macros
.contains(name
) || matches
!(item
.vis
.kind
, VisibilityKind
::Inherited
);
130 // keep track of `use some_module;` usages
131 if segments
.len() == 1 {
132 if let UseTreeKind
::Simple(None
, _
, _
) = use_tree
.kind
{
133 let name
= segments
[0].ident
.name
;
134 if should_report(&name
) {
135 single_use_usages
.push((name
, item
.span
, true));
141 if segments
.is_empty() {
142 // keep track of `use {some_module, some_other_module};` usages
143 if let UseTreeKind
::Nested(trees
) = &use_tree
.kind
{
145 let segments
= &tree
.0.prefix
.segments
;
146 if segments
.len() == 1 {
147 if let UseTreeKind
::Simple(None
, _
, _
) = tree
.0.kind
{
148 let name
= segments
[0].ident
.name
;
149 if should_report(&name
) {
150 single_use_usages
.push((name
, tree
.0.span
, false));
157 // keep track of `use self::some_module` usages
158 if segments
[0].ident
.name
== kw
::SelfLower
{
159 // simple case such as `use self::module::SomeStruct`
160 if segments
.len() > 1 {
161 imports_reused_with_self
.push(segments
[1].ident
.name
);
165 // nested case such as `use self::{module1::Struct1, module2::Struct2}`
166 if let UseTreeKind
::Nested(trees
) = &use_tree
.kind
{
168 let segments
= &tree
.0.prefix
.segments
;
169 if !segments
.is_empty() {
170 imports_reused_with_self
.push(segments
[0].ident
.name
);