From 72151507f56fd7b6b25db16a2a520711dc80aa19 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 7 Nov 2024 14:14:19 +0800 Subject: [PATCH 01/23] wip doctest don't lint `use self::` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + .../src/use_crate_prefix_for_self_imports.rs | 79 +++++++++++++++++++ .../fail/Cargo.stderr | 10 +++ .../fail/Cargo.toml | 7 ++ .../fail/src/foo.rs | 1 + .../fail/src/main.rs | 7 ++ .../pass/Cargo.toml | 7 ++ .../pass/src/foo.rs | 1 + .../pass/src/main.rs | 7 ++ tests/ui/use_crate_prefix_for_self_imports.rs | 5 ++ 12 files changed, 128 insertions(+) create mode 100644 clippy_lints/src/use_crate_prefix_for_self_imports.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs create mode 100644 tests/ui/use_crate_prefix_for_self_imports.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e9f6d1dd3e..f0a6af0e0a3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6940,6 +6940,7 @@ Released 2018-09-13 [`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default [`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used [`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms +[`use_crate_prefix_for_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_crate_prefix_for_self_imports [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 375d179681da..c4512a073e46 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -774,6 +774,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::unwrap::UNNECESSARY_UNWRAP_INFO, crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO, crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO, + crate::use_crate_prefix_for_self_imports::USE_CRATE_PREFIX_FOR_SELF_IMPORTS_INFO, crate::use_self::USE_SELF_INFO, crate::useless_concat::USELESS_CONCAT_INFO, crate::useless_conversion::USELESS_CONVERSION_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 149785c59447..27281b3635c8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -394,6 +394,7 @@ mod unused_unit; mod unwrap; mod unwrap_in_result; mod upper_case_acronyms; +mod use_crate_prefix_for_self_imports; mod use_self; mod useless_concat; mod useless_conversion; @@ -834,5 +835,6 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(|_| Box::new(toplevel_ref_arg::ToplevelRefArg)); store.register_late_pass(|_| Box::new(volatile_composites::VolatileComposites)); store.register_late_pass(|_| Box::new(replace_box::ReplaceBox)); + store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs new file mode 100644 index 000000000000..25c070337535 --- /dev/null +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -0,0 +1,79 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use def_id::LOCAL_CRATE; +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// This lint checks for imports from the current crate that do not use the `crate::` prefix. + /// It suggests using `crate::` to make it clear that the item is from the same crate. + /// + /// ### Why is this bad? + /// When imports from the current crate lack the `crate::` prefix, it can make the code less readable + /// because it’s not immediately clear if the imported item is from the current crate or an external dependency. + /// Using `crate::` for self-imports provides a consistent style, making the origin of each import clear. + /// This helps reduce confusion and maintain a uniform codebase. + /// + /// ### Example + /// ```rust,ignore + /// // lib.rs + /// mod foo; + /// use foo::bar; + /// ``` + /// + /// ```rust,ignore + /// // foo.rs + /// #[path = "./foo.rs"] + /// pub fn bar() {} + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// // lib.rs + /// mod foo; + /// use crate::foo::bar; + /// ``` + /// + /// ```rust,ignore + /// // foo.rs + /// #[path = "./foo.rs"] + /// pub fn bar() {} + /// ``` + #[clippy::version = "1.84.0"] + pub USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + style, + "checks that imports from the current crate use the `crate::` prefix" +} + +declare_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); + +impl LateLintPass<'_> for UseCratePrefixForSelfImports { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if let ItemKind::Use(use_path, _) = &item.kind { + if let Some(segment) = use_path.segments.first() + && let Res::Def(_, def_id) = segment.res + && def_id.krate == LOCAL_CRATE + { + let root = segment.ident.name; + if root != rustc_span::symbol::kw::Crate + && root != rustc_span::symbol::kw::Super + && root != rustc_span::symbol::kw::SelfLower + { + span_lint_and_sugg( + cx, + USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + use_path.span, + "this import is not clear", + "prefix with `crate::`", + format!("crate::{}", snippet_opt(cx, use_path.span).unwrap()), + Applicability::MachineApplicable, + ); + } + } + } + } +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr new file mode 100644 index 000000000000..de315117be8e --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr @@ -0,0 +1,10 @@ +error: this import is not clear + --> src/main.rs:1:5 + | +1 | use foo::Foo; + | ^^^^^^^^ help: prefix with `crate::`: `crate::foo::Foo` + | + = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]` + +error: could not compile `fail` (bin "fail") due to 1 previous error diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml new file mode 100644 index 000000000000..e2d17bfe9a76 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fail" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs new file mode 100644 index 000000000000..321e2777a0fc --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs @@ -0,0 +1,7 @@ +use foo::Foo; + +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml new file mode 100644 index 000000000000..68783fafe997 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs new file mode 100644 index 000000000000..20a8096034a2 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs @@ -0,0 +1,7 @@ +use crate::foo::Foo; + +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui/use_crate_prefix_for_self_imports.rs b/tests/ui/use_crate_prefix_for_self_imports.rs new file mode 100644 index 000000000000..00038a286279 --- /dev/null +++ b/tests/ui/use_crate_prefix_for_self_imports.rs @@ -0,0 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +fn main() { + // test code goes here +} From 2f103ff9789e1001cca257f6d37d36c00ce11ec7 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 7 Nov 2024 17:16:40 +0800 Subject: [PATCH 02/23] only check `main.rs` and `lib.rs` cargo uibless --- .../src/use_crate_prefix_for_self_imports.rs | 20 +++++++++++++++---- .../fail/Cargo.stderr | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 25c070337535..bd0455097045 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -3,9 +3,10 @@ use clippy_utils::source::snippet_opt; use def_id::LOCAL_CRATE; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::*; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::{Item, ItemKind, def_id}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; +use rustc_span::{FileName, RealFileName}; declare_clippy_lint! { /// ### What it does @@ -53,6 +54,17 @@ declare_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IM impl LateLintPass<'_> for UseCratePrefixForSelfImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(item.span) else { + return; + }; + let Some(file_name) = p.file_name() else { + return; + }; + // only check `main.rs` and `lib.rs` + if !(file_name == "main.rs" || file_name == "lib.rs") { + return; + } + if let ItemKind::Use(use_path, _) = &item.kind { if let Some(segment) = use_path.segments.first() && let Res::Def(_, def_id) = segment.res @@ -66,10 +78,10 @@ impl LateLintPass<'_> for UseCratePrefixForSelfImports { span_lint_and_sugg( cx, USE_CRATE_PREFIX_FOR_SELF_IMPORTS, - use_path.span, + segment.ident.span, "this import is not clear", "prefix with `crate::`", - format!("crate::{}", snippet_opt(cx, use_path.span).unwrap()), + format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), Applicability::MachineApplicable, ); } diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr index de315117be8e..6b336640e2c1 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr @@ -2,7 +2,7 @@ error: this import is not clear --> src/main.rs:1:5 | 1 | use foo::Foo; - | ^^^^^^^^ help: prefix with `crate::`: `crate::foo::Foo` + | ^^^ help: prefix with `crate::`: `crate::foo` | = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]` From db08e51464cf2b3c1b1f3b54bcd1ca33d829b90c Mon Sep 17 00:00:00 2001 From: lengyijun Date: Tue, 28 Jan 2025 08:21:43 +0800 Subject: [PATCH 03/23] rm useless test --- tests/ui/use_crate_prefix_for_self_imports.rs | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 tests/ui/use_crate_prefix_for_self_imports.rs diff --git a/tests/ui/use_crate_prefix_for_self_imports.rs b/tests/ui/use_crate_prefix_for_self_imports.rs deleted file mode 100644 index 00038a286279..000000000000 --- a/tests/ui/use_crate_prefix_for_self_imports.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(clippy::use_crate_prefix_for_self_imports)] - -fn main() { - // test code goes here -} From 56b0e8e2b4a105a1376d9d90096e8b26c064b743 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Tue, 28 Jan 2025 09:36:00 +0800 Subject: [PATCH 04/23] don't lint ``` mod foo; use foo; ``` --- clippy_lints/src/lib.rs | 2 +- .../src/use_crate_prefix_for_self_imports.rs | 40 +++++++++++++------ .../fail_sibling/Cargo.stderr | 10 +++++ .../fail_sibling/Cargo.toml | 7 ++++ .../fail_sibling/src/foo.rs | 1 + .../fail_sibling/src/main.rs | 6 +++ .../pass_sibling/Cargo.toml | 7 ++++ .../pass_sibling/src/foo.rs | 1 + .../pass_sibling/src/main.rs | 6 +++ 9 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 27281b3635c8..b199a1d118a9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -835,6 +835,6 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(|_| Box::new(toplevel_ref_arg::ToplevelRefArg)); store.register_late_pass(|_| Box::new(volatile_composites::VolatileComposites)); store.register_late_pass(|_| Box::new(replace_box::ReplaceBox)); - store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports)); + store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports::default())); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index bd0455097045..2eeb8da73337 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; use def_id::LOCAL_CRATE; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Item, ItemKind, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::declare_lint_pass; -use rustc_span::{FileName, RealFileName}; +use rustc_session::impl_lint_pass; +use rustc_span::{BytePos, FileName, RealFileName, Symbol}; declare_clippy_lint! { /// ### What it does @@ -50,7 +51,12 @@ declare_clippy_lint! { "checks that imports from the current crate use the `crate::` prefix" } -declare_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); +#[derive(Clone, Default)] +pub struct UseCratePrefixForSelfImports { + mod_line: FxHashMap, +} + +impl_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); impl LateLintPass<'_> for UseCratePrefixForSelfImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { @@ -65,6 +71,10 @@ impl LateLintPass<'_> for UseCratePrefixForSelfImports { return; } + if let ItemKind::Mod(_) = &item.kind { + self.mod_line.insert(item.ident.name, item.span.hi()); + } + if let ItemKind::Use(use_path, _) = &item.kind { if let Some(segment) = use_path.segments.first() && let Res::Def(_, def_id) = segment.res @@ -75,15 +85,21 @@ impl LateLintPass<'_> for UseCratePrefixForSelfImports { && root != rustc_span::symbol::kw::Super && root != rustc_span::symbol::kw::SelfLower { - span_lint_and_sugg( - cx, - USE_CRATE_PREFIX_FOR_SELF_IMPORTS, - segment.ident.span, - "this import is not clear", - "prefix with `crate::`", - format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), - Applicability::MachineApplicable, - ); + let should_lint = match self.mod_line.get(&root) { + Some(bytepos) => item.span.lo() - *bytepos != BytePos(1), + None => true, + }; + if should_lint { + span_lint_and_sugg( + cx, + USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + segment.ident.span, + "this import is not clear", + "prefix with `crate::`", + format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), + Applicability::MachineApplicable, + ); + } } } } diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr new file mode 100644 index 000000000000..0d1f169f81d5 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr @@ -0,0 +1,10 @@ +error: this import is not clear + --> src/main.rs:1:5 + | +1 | use foo::Foo; + | ^^^ help: prefix with `crate::`: `crate::foo` + | + = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]` + +error: could not compile `fail_sibling` (bin "fail_sibling") due to 1 previous error diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml new file mode 100644 index 000000000000..808236b00741 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fail_sibling" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs new file mode 100644 index 000000000000..403832996771 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs @@ -0,0 +1,6 @@ +use foo::Foo; +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml new file mode 100644 index 000000000000..c1abf357a802 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs new file mode 100644 index 000000000000..96011581b01a --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs @@ -0,0 +1,6 @@ +mod foo; +use foo::Foo; + +fn main() { + let _foo = Foo; +} From 02f0e66e5881d6103a66c831dd2b1b366aa5339c Mon Sep 17 00:00:00 2001 From: lengyijun Date: Wed, 29 Jan 2025 19:59:11 +0800 Subject: [PATCH 05/23] don't lint ``` use foo; mod foo; ``` --- .../src/use_crate_prefix_for_self_imports.rs | 74 +++++++++++++------ .../fail_sibling/Cargo.stderr | 10 --- .../Cargo.toml | 2 +- .../src/foo.rs | 0 .../src/main.rs | 0 5 files changed, 53 insertions(+), 33 deletions(-) delete mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr rename tests/ui-cargo/use_crate_prefix_for_self_imports/{fail_sibling => pass_sibling_2}/Cargo.toml (76%) rename tests/ui-cargo/use_crate_prefix_for_self_imports/{fail_sibling => pass_sibling_2}/src/foo.rs (100%) rename tests/ui-cargo/use_crate_prefix_for_self_imports/{fail_sibling => pass_sibling_2}/src/main.rs (100%) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 2eeb8da73337..200fbfbcddbe 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; use def_id::LOCAL_CRATE; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Item, ItemKind, def_id}; @@ -52,44 +52,74 @@ declare_clippy_lint! { } #[derive(Clone, Default)] -pub struct UseCratePrefixForSelfImports { - mod_line: FxHashMap, +pub struct UseCratePrefixForSelfImports<'a, 'tcx> { + /// code block of `use ` or `mod ` + use_block: Vec<&'a Item<'tcx>>, } -impl_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); +impl_lint_pass!(UseCratePrefixForSelfImports<'_, '_> => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); -impl LateLintPass<'_> for UseCratePrefixForSelfImports { - fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { +impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'a Item<'tcx>) { let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(item.span) else { + self.use_block.clear(); return; }; let Some(file_name) = p.file_name() else { + self.use_block.clear(); return; }; // only check `main.rs` and `lib.rs` if !(file_name == "main.rs" || file_name == "lib.rs") { + self.use_block.clear(); return; } - if let ItemKind::Mod(_) = &item.kind { - self.mod_line.insert(item.ident.name, item.span.hi()); + match item.kind { + ItemKind::Mod(_) | ItemKind::Use(_, _) => {}, + _ => return, } - if let ItemKind::Use(use_path, _) = &item.kind { - if let Some(segment) = use_path.segments.first() - && let Res::Def(_, def_id) = segment.res - && def_id.krate == LOCAL_CRATE - { - let root = segment.ident.name; - if root != rustc_span::symbol::kw::Crate - && root != rustc_span::symbol::kw::Super - && root != rustc_span::symbol::kw::SelfLower + match self.use_block.last() { + Some(prev_item) => { + if item.span.lo() - prev_item.span.hi() == BytePos(1) { + self.use_block.push(item); + } else { + self.deal(cx); + self.use_block.clear(); + self.use_block.push(item); + } + }, + None => { + self.use_block.push(item); + }, + } + } +} + +impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { + fn deal(&self, cx: &LateContext<'tcx>) { + let mod_names: FxHashSet = self + .use_block + .iter() + .filter_map(|item| match item.kind { + ItemKind::Mod(_) => Some(item.ident.name), + _ => None, + }) + .collect(); + + for item in &self.use_block { + if let ItemKind::Use(use_path, _) = &item.kind { + if let Some(segment) = use_path.segments.first() + && let Res::Def(_, def_id) = segment.res + && def_id.krate == LOCAL_CRATE { - let should_lint = match self.mod_line.get(&root) { - Some(bytepos) => item.span.lo() - *bytepos != BytePos(1), - None => true, - }; - if should_lint { + let root = segment.ident.name; + if root != rustc_span::symbol::kw::Crate + && root != rustc_span::symbol::kw::Super + && root != rustc_span::symbol::kw::SelfLower + && !mod_names.contains(&root) + { span_lint_and_sugg( cx, USE_CRATE_PREFIX_FOR_SELF_IMPORTS, diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr deleted file mode 100644 index 0d1f169f81d5..000000000000 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: this import is not clear - --> src/main.rs:1:5 - | -1 | use foo::Foo; - | ^^^ help: prefix with `crate::`: `crate::foo` - | - = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]` - -error: could not compile `fail_sibling` (bin "fail_sibling") due to 1 previous error diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml similarity index 76% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml index 808236b00741..a1d2fd853185 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "fail_sibling" +name = "pass_sibling_2" version = "0.1.0" edition = "2021" publish = false diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/foo.rs similarity index 100% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/foo.rs rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/foo.rs diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs similarity index 100% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/fail_sibling/src/main.rs rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs From 8fc4cce13f58ff27b61cddb2800130fef1f03491 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Wed, 29 Jan 2025 20:56:23 +0800 Subject: [PATCH 06/23] another test --- .../src/use_crate_prefix_for_self_imports.rs | 34 ++++++++++++------- .../pass_sibling_3/Cargo.toml | 7 ++++ .../pass_sibling_3/src/foo.rs | 2 ++ .../pass_sibling_3/src/main.rs | 7 ++++ 4 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 200fbfbcddbe..3ffabc54bb40 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -80,24 +80,32 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { _ => return, } - match self.use_block.last() { - Some(prev_item) => { - if item.span.lo() - prev_item.span.hi() == BytePos(1) { - self.use_block.push(item); - } else { - self.deal(cx); - self.use_block.clear(); - self.use_block.push(item); - } - }, - None => { - self.use_block.push(item); - }, + if self.in_same_block(item) { + self.use_block.push(item); + } else { + self.deal(cx); + self.use_block.clear(); + self.use_block.push(item); } } } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { + fn in_same_block(&self, item: &Item<'tcx>) -> bool { + if self.use_block.is_empty() { + return true; + } + if self.use_block.iter().any(|x| x.span.contains(item.span)) { + return true; + } + if let Some(prev_item) = self.use_block.last() + && item.span.lo() - prev_item.span.hi() == BytePos(1) + { + return true; + } + false + } + fn deal(&self, cx: &LateContext<'tcx>) { let mod_names: FxHashSet = self .use_block diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml new file mode 100644 index 000000000000..b03557dce1a2 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling_3" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs new file mode 100644 index 000000000000..3e1446bda001 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs @@ -0,0 +1,2 @@ +pub struct Foo; +pub struct Bar; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs new file mode 100644 index 000000000000..7e23e0ff3ddc --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs @@ -0,0 +1,7 @@ +mod foo; +pub use foo::{Bar, Foo}; + +fn main() { + let _foo = Foo; + let _bar = Bar; +} From 83c9271bbfcf811a4112519c2600f33f0a9e10ac Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 30 Jan 2025 08:28:04 +0800 Subject: [PATCH 07/23] stronger test --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 6 ++++-- .../pass_sibling_4/Cargo.toml | 7 +++++++ .../pass_sibling_4/src/foo.rs | 2 ++ .../pass_sibling_4/src/main.rs | 7 +++++++ 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 3ffabc54bb40..b37ac00b1fd8 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -98,8 +98,10 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { if self.use_block.iter().any(|x| x.span.contains(item.span)) { return true; } - if let Some(prev_item) = self.use_block.last() - && item.span.lo() - prev_item.span.hi() == BytePos(1) + if self + .use_block + .iter() + .any(|x| item.span.lo() - x.span.hi() == BytePos(1)) { return true; } diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml new file mode 100644 index 000000000000..1a7f71070fce --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling_4" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs new file mode 100644 index 000000000000..3e1446bda001 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs @@ -0,0 +1,2 @@ +pub struct Foo; +pub struct Bar; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs new file mode 100644 index 000000000000..664c8b270a39 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs @@ -0,0 +1,7 @@ +pub use foo::{Bar, Foo}; +mod foo; + +fn main() { + let _foo = Foo; + let _bar = Bar; +} From 0c0b1de3e199fdfde45d2143fe0128dc5036b89d Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 30 Jan 2025 09:32:56 +0800 Subject: [PATCH 08/23] lint `dylint` --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index b37ac00b1fd8..784c66244669 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -71,7 +71,6 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { }; // only check `main.rs` and `lib.rs` if !(file_name == "main.rs" || file_name == "lib.rs") { - self.use_block.clear(); return; } From 351212913b79b85cf56f65df923565cc8264abaa Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 30 Jan 2025 11:12:52 +0800 Subject: [PATCH 09/23] wip --- .../src/use_crate_prefix_for_self_imports.rs | 130 +++++++++++------- 1 file changed, 79 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 784c66244669..ee0dc267b4ce 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -4,10 +4,10 @@ use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{Item, ItemKind, def_id}; +use rustc_hir::{Attribute, Item, ItemKind, UsePath, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::{BytePos, FileName, RealFileName, Symbol}; +use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -53,8 +53,12 @@ declare_clippy_lint! { #[derive(Clone, Default)] pub struct UseCratePrefixForSelfImports<'a, 'tcx> { - /// code block of `use ` or `mod ` - use_block: Vec<&'a Item<'tcx>>, + /// collect `use` in current block + use_block: Vec<&'a UsePath<'tcx>>, + /// collect `mod` in current block + mod_names: FxHashSet, + /// spans of `mod`, `use`, and attributes + spans: Vec, } impl_lint_pass!(UseCratePrefixForSelfImports<'_, '_> => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); @@ -62,11 +66,11 @@ impl_lint_pass!(UseCratePrefixForSelfImports<'_, '_> => [USE_CRATE_PREFIX_FOR_SE impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'a Item<'tcx>) { let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(item.span) else { - self.use_block.clear(); + self.clear(); return; }; let Some(file_name) = p.file_name() else { - self.use_block.clear(); + self.clear(); return; }; // only check `main.rs` and `lib.rs` @@ -74,73 +78,97 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { return; } - match item.kind { - ItemKind::Mod(_) | ItemKind::Use(_, _) => {}, - _ => return, + if self.in_same_block(item.span) { + self.insert_item(item); + } else { + self.deal(cx); + self.clear(); + self.insert_item(item); } + } - if self.in_same_block(item) { - self.use_block.push(item); + fn check_attribute(&mut self, cx: &LateContext<'tcx>, attribute: &'a Attribute) { + let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(attribute.span()) + else { + self.clear(); + return; + }; + let Some(file_name) = p.file_name() else { + self.clear(); + return; + }; + // only check `main.rs` and `lib.rs` + if !(file_name == "main.rs" || file_name == "lib.rs") { + return; + } + + if self.in_same_block(attribute.span()) { + self.spans.push(attribute.span()); } else { self.deal(cx); - self.use_block.clear(); - self.use_block.push(item); + self.clear(); + self.spans.push(attribute.span()); } } } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { - fn in_same_block(&self, item: &Item<'tcx>) -> bool { - if self.use_block.is_empty() { + fn in_same_block(&self, span: Span) -> bool { + if self.spans.is_empty() { return true; } - if self.use_block.iter().any(|x| x.span.contains(item.span)) { + if self.spans.iter().any(|x| x.contains(span)) { return true; } - if self - .use_block - .iter() - .any(|x| item.span.lo() - x.span.hi() == BytePos(1)) - { + if self.spans.iter().any(|x| span.lo() - x.hi() == BytePos(1)) { return true; } false } - fn deal(&self, cx: &LateContext<'tcx>) { - let mod_names: FxHashSet = self - .use_block - .iter() - .filter_map(|item| match item.kind { - ItemKind::Mod(_) => Some(item.ident.name), - _ => None, - }) - .collect(); + fn insert_item(&mut self, item: &Item<'tcx>) { + match item.kind { + ItemKind::Mod(_) => { + self.spans.push(item.span); + self.mod_names.insert(item.ident.name); + }, + ItemKind::Use(use_tree, _) => { + self.spans.push(item.span); + self.use_block.push(use_tree); + }, + _ => {}, + } + } - for item in &self.use_block { - if let ItemKind::Use(use_path, _) = &item.kind { - if let Some(segment) = use_path.segments.first() - && let Res::Def(_, def_id) = segment.res - && def_id.krate == LOCAL_CRATE + fn deal(&self, cx: &LateContext<'tcx>) { + for use_path in &self.use_block { + if let Some(segment) = use_path.segments.first() + && let Res::Def(_, def_id) = segment.res + && def_id.krate == LOCAL_CRATE + { + let root = segment.ident.name; + if root != rustc_span::symbol::kw::Crate + && root != rustc_span::symbol::kw::Super + && root != rustc_span::symbol::kw::SelfLower + && !self.mod_names.contains(&root) { - let root = segment.ident.name; - if root != rustc_span::symbol::kw::Crate - && root != rustc_span::symbol::kw::Super - && root != rustc_span::symbol::kw::SelfLower - && !mod_names.contains(&root) - { - span_lint_and_sugg( - cx, - USE_CRATE_PREFIX_FOR_SELF_IMPORTS, - segment.ident.span, - "this import is not clear", - "prefix with `crate::`", - format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), - Applicability::MachineApplicable, - ); - } + span_lint_and_sugg( + cx, + USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + segment.ident.span, + "this import is not clear", + "prefix with `crate::`", + format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), + Applicability::MachineApplicable, + ); } } } } + + fn clear(&mut self) { + self.use_block.clear(); + self.mod_names.clear(); + self.spans.clear(); + } } From 1d361a4a3e20c5aaf1d126eb5203e7c7917dbe25 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 30 Jan 2025 12:29:00 +0800 Subject: [PATCH 10/23] no unwrap --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index ee0dc267b4ce..d4cfdee43480 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -158,7 +157,7 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { segment.ident.span, "this import is not clear", "prefix with `crate::`", - format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()), + format!("crate::{root}"), Applicability::MachineApplicable, ); } From 40cf7c0edd87ecab04a16124dc5b19107c24d7e8 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 13 Feb 2025 09:33:28 +0800 Subject: [PATCH 11/23] style => nursery --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index d4cfdee43480..22b30b0dc617 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -46,7 +46,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.84.0"] pub USE_CRATE_PREFIX_FOR_SELF_IMPORTS, - style, + nursery, "checks that imports from the current crate use the `crate::` prefix" } From f2856b670e571bea2d587295176da5a486fe0e53 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 30 Jan 2025 11:55:11 +0800 Subject: [PATCH 12/23] fix tests --- .../fail/Cargo.stderr | 4 ++-- .../fail/src/main.rs | 2 ++ .../pass/src/main.rs | 2 ++ .../pass_attribute/Cargo.toml | 11 +++++++++++ .../pass_attribute/src/foo.rs | 1 + .../pass_attribute/src/lib.rs | 6 ++++++ .../pass_attribute_2/Cargo.toml | 7 +++++++ .../pass_attribute_2/src/foo.rs | 1 + .../pass_attribute_2/src/lib.rs | 5 +++++ .../pass_sibling/src/main.rs | 2 ++ .../pass_sibling_2/src/main.rs | 2 ++ .../pass_sibling_3/src/main.rs | 2 ++ .../pass_sibling_4/src/main.rs | 2 ++ 13 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs create mode 100644 tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr index 6b336640e2c1..e559b590f5f7 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr @@ -1,7 +1,7 @@ error: this import is not clear - --> src/main.rs:1:5 + --> src/main.rs:3:5 | -1 | use foo::Foo; +3 | use foo::Foo; | ^^^ help: prefix with `crate::`: `crate::foo` | = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs index 321e2777a0fc..7e75c10f1b5b 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + use foo::Foo; mod foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs index 20a8096034a2..820faee159b7 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + use crate::foo::Foo; mod foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml new file mode 100644 index 000000000000..a9248778777a --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pass_attribute" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] + +[features] +default = ["bar"] +bar = [] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs new file mode 100644 index 000000000000..1ebe7984e084 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs @@ -0,0 +1,6 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +#[cfg(feature = "bar")] +mod foo; +#[cfg(feature = "bar")] +pub use foo::Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml new file mode 100644 index 000000000000..202d81f7a503 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_attribute_2" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs new file mode 100644 index 000000000000..0633d3a88fc9 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs @@ -0,0 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +mod foo; +#[doc(hidden)] +pub use foo::Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs index 96011581b01a..6fc7b021514a 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + mod foo; use foo::Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs index 403832996771..9502ca88022f 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + use foo::Foo; mod foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs index 7e23e0ff3ddc..0f62eabb5fef 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + mod foo; pub use foo::{Bar, Foo}; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs index 664c8b270a39..22fc2fafb4df 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + pub use foo::{Bar, Foo}; mod foo; From 8fc104ab40080c9e1a7813bc0e7d16ef23766bae Mon Sep 17 00:00:00 2001 From: lengyijun Date: Sat, 12 Apr 2025 13:24:35 +0800 Subject: [PATCH 13/23] fix after toolchain update --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 22b30b0dc617..b8b0885cb31c 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -127,9 +127,9 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { fn insert_item(&mut self, item: &Item<'tcx>) { match item.kind { - ItemKind::Mod(_) => { + ItemKind::Mod(ident, _) => { self.spans.push(item.span); - self.mod_names.insert(item.ident.name); + self.mod_names.insert(ident.name); }, ItemKind::Use(use_tree, _) => { self.spans.push(item.span); From 93bd82c0b0e70b909cbd8a6b39aaa09bc74c9ae8 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 18 Sep 2025 15:06:52 +0800 Subject: [PATCH 14/23] no check_attribute --- .../src/use_crate_prefix_for_self_imports.rs | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index b8b0885cb31c..67220e687553 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -3,7 +3,7 @@ use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{Attribute, Item, ItemKind, UsePath, def_id}; +use rustc_hir::{Item, ItemKind, UsePath, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol}; @@ -86,29 +86,6 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { } } - fn check_attribute(&mut self, cx: &LateContext<'tcx>, attribute: &'a Attribute) { - let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(attribute.span()) - else { - self.clear(); - return; - }; - let Some(file_name) = p.file_name() else { - self.clear(); - return; - }; - // only check `main.rs` and `lib.rs` - if !(file_name == "main.rs" || file_name == "lib.rs") { - return; - } - - if self.in_same_block(attribute.span()) { - self.spans.push(attribute.span()); - } else { - self.deal(cx); - self.clear(); - self.spans.push(attribute.span()); - } - } } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { From 2722eac881227fd82b17a236527f561886da40ec Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 18 Sep 2025 15:48:19 +0800 Subject: [PATCH 15/23] fmt --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 67220e687553..5e7bb651c0a6 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -85,7 +85,6 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { self.insert_item(item); } } - } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { From ba3548216e12a9000dcc1012585e3a89bc5bdbed Mon Sep 17 00:00:00 2001 From: lengyijun Date: Fri, 19 Sep 2025 14:01:44 +0800 Subject: [PATCH 16/23] 2024 --- .../ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml | 2 +- .../ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml | 2 +- .../use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml | 2 +- .../pass_attribute_2/Cargo.toml | 2 +- .../use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml | 2 +- .../use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml | 2 +- .../use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml | 2 +- .../use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml index e2d17bfe9a76..4fd6d77abc86 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "fail" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml index 68783fafe997..2400bd010748 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml index a9248778777a..793f14562d91 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_attribute" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml index 202d81f7a503..ceb763d04aa9 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_attribute_2" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml index c1abf357a802..0924d8d033a1 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_sibling" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml index a1d2fd853185..3e7b3ad1343b 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_sibling_2" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml index b03557dce1a2..f0889780811b 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_sibling_3" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml index 1a7f71070fce..5be4b1276615 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pass_sibling_4" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] From 1d80a385ef768067a2b20735e184f7844078129f Mon Sep 17 00:00:00 2001 From: lengyijun Date: Fri, 19 Sep 2025 14:06:16 +0800 Subject: [PATCH 17/23] typo --- clippy_lints/src/lib.rs | 4 +++- .../src/use_crate_prefix_for_self_imports.rs | 16 ++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b199a1d118a9..f3dd9732a6f6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -835,6 +835,8 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(|_| Box::new(toplevel_ref_arg::ToplevelRefArg)); store.register_late_pass(|_| Box::new(volatile_composites::VolatileComposites)); store.register_late_pass(|_| Box::new(replace_box::ReplaceBox)); - store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports::default())); + store.register_late_pass(|_| { + Box::>::default() + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 5e7bb651c0a6..9ac627d21367 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -6,7 +6,7 @@ use rustc_hir::def::Res; use rustc_hir::{Item, ItemKind, UsePath, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol}; +use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol, kw}; declare_clippy_lint! { /// ### What it does @@ -44,7 +44,7 @@ declare_clippy_lint! { /// #[path = "./foo.rs"] /// pub fn bar() {} /// ``` - #[clippy::version = "1.84.0"] + #[clippy::version = "1.92.0"] pub USE_CRATE_PREFIX_FOR_SELF_IMPORTS, nursery, "checks that imports from the current crate use the `crate::` prefix" @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { if self.in_same_block(item.span) { self.insert_item(item); } else { - self.deal(cx); + self.try_lint(cx); self.clear(); self.insert_item(item); } @@ -115,18 +115,14 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { } } - fn deal(&self, cx: &LateContext<'tcx>) { + fn try_lint(&self, cx: &LateContext<'tcx>) { for use_path in &self.use_block { - if let Some(segment) = use_path.segments.first() + if let [segment, ..] = &use_path.segments && let Res::Def(_, def_id) = segment.res && def_id.krate == LOCAL_CRATE { let root = segment.ident.name; - if root != rustc_span::symbol::kw::Crate - && root != rustc_span::symbol::kw::Super - && root != rustc_span::symbol::kw::SelfLower - && !self.mod_names.contains(&root) - { + if !matches!(root, kw::Crate | kw::Super | kw::SelfLower) && !self.mod_names.contains(&root) { span_lint_and_sugg( cx, USE_CRATE_PREFIX_FOR_SELF_IMPORTS, From 6400f003bfb861274d1af161b016b8fd6f490f39 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Thu, 9 Oct 2025 16:47:12 +0800 Subject: [PATCH 18/23] wip --- .../src/use_crate_prefix_for_self_imports.rs | 26 ++++++++++++++++++- .../pass_sibling/src/main.rs | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 9ac627d21367..cb6753885418 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -3,7 +3,7 @@ use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{Item, ItemKind, UsePath, def_id}; +use rustc_hir::{Attribute, Item, ItemKind, UsePath, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol, kw}; @@ -85,6 +85,30 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { self.insert_item(item); } } + + fn check_attribute(&mut self, cx: &LateContext<'tcx>, attribute: &'a Attribute) { + let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(attribute.span()) + else { + self.clear(); + return; + }; + let Some(file_name) = p.file_name() else { + self.clear(); + return; + }; + // only check `main.rs` and `lib.rs` + if !(file_name == "main.rs" || file_name == "lib.rs") { + return; + } + + if self.in_same_block(attribute.span()) { + self.spans.push(attribute.span()); + } else { + self.try_lint(cx); + self.clear(); + self.spans.push(attribute.span()); + } + } } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs index 6fc7b021514a..ccd452fe6a7e 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs @@ -1,6 +1,7 @@ #![warn(clippy::use_crate_prefix_for_self_imports)] mod foo; +//fadsfsadfa use foo::Foo; fn main() { From 65043bfc6bb33d74ed16fc87591107725b8b11ad Mon Sep 17 00:00:00 2001 From: lengyijun Date: Fri, 10 Oct 2025 14:24:44 +0800 Subject: [PATCH 19/23] wip --- .../src/use_crate_prefix_for_self_imports.rs | 94 ++++++++++--------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index cb6753885418..9b1049f46154 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -1,4 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::SpanRangeExt; +use clippy_utils::tokenize_with_text; use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -56,8 +58,7 @@ pub struct UseCratePrefixForSelfImports<'a, 'tcx> { use_block: Vec<&'a UsePath<'tcx>>, /// collect `mod` in current block mod_names: FxHashSet, - /// spans of `mod`, `use`, and attributes - spans: Vec, + latest_span: Option, } impl_lint_pass!(UseCratePrefixForSelfImports<'_, '_> => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); @@ -77,41 +78,12 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { return; } - if self.in_same_block(item.span) { - self.insert_item(item); - } else { - self.try_lint(cx); - self.clear(); - self.insert_item(item); - } - } - - fn check_attribute(&mut self, cx: &LateContext<'tcx>, attribute: &'a Attribute) { - let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(attribute.span()) - else { - self.clear(); - return; - }; - let Some(file_name) = p.file_name() else { - self.clear(); - return; - }; - // only check `main.rs` and `lib.rs` - if !(file_name == "main.rs" || file_name == "lib.rs") { - return; - } - - if self.in_same_block(attribute.span()) { - self.spans.push(attribute.span()); - } else { - self.try_lint(cx); - self.clear(); - self.spans.push(attribute.span()); - } + self.insert_item(cx, item); } } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { + /* fn in_same_block(&self, span: Span) -> bool { if self.spans.is_empty() { return true; @@ -124,19 +96,53 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { } false } + */ - fn insert_item(&mut self, item: &Item<'tcx>) { - match item.kind { - ItemKind::Mod(ident, _) => { - self.spans.push(item.span); - self.mod_names.insert(ident.name); - }, - ItemKind::Use(use_tree, _) => { - self.spans.push(item.span); - self.use_block.push(use_tree); + fn in_same_block(&self, cx: &LateContext<'tcx>, span: Span) -> bool { + match self.latest_span { + Some(latest_span) => { + let gap_span = latest_span.between(span); + let gap_snippet = gap_span.get_source_text(cx).unwrap(); + for (token, source, inner_span) in tokenize_with_text(&gap_snippet) { + match token { + rustc_lexer::TokenKind::Whitespace => return false, + _ => {}, + } + } + true }, - _ => {}, + None => true, + } + } + + fn insert_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { + if self.in_same_block(cx, item.span) { + match item.kind { + ItemKind::Mod(ident, _) => { + self.mod_names.insert(ident.name); + }, + ItemKind::Use(use_tree, _) => { + self.use_block.push(use_tree); + }, + _ => {}, + } + } else { + self.try_lint(cx); + self.clear(); + match item.kind { + ItemKind::Mod(ident, _) => { + self.mod_names.insert(ident.name); + }, + ItemKind::Use(use_tree, _) => { + self.use_block.push(use_tree); + }, + _ => {}, + } } + self.latest_span = match self.latest_span { + Some(span) => Some(span.with_hi(item.span.hi())), + None => Some(item.span), + }; } fn try_lint(&self, cx: &LateContext<'tcx>) { @@ -164,6 +170,6 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { fn clear(&mut self) { self.use_block.clear(); self.mod_names.clear(); - self.spans.clear(); + // self.spans.clear(); } } From 78c1c70807e8ab8c8615ed0e06103d653b90cdfd Mon Sep 17 00:00:00 2001 From: lengyijun Date: Fri, 10 Oct 2025 14:33:04 +0800 Subject: [PATCH 20/23] wip --- .../src/use_crate_prefix_for_self_imports.rs | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 9b1049f46154..95fac5ce0207 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -101,6 +101,9 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { fn in_same_block(&self, cx: &LateContext<'tcx>, span: Span) -> bool { match self.latest_span { Some(latest_span) => { + if latest_span.contains(span) { + return true; + } let gap_span = latest_span.between(span); let gap_snippet = gap_span.get_source_text(cx).unwrap(); for (token, source, inner_span) in tokenize_with_text(&gap_snippet) { @@ -117,27 +120,18 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { fn insert_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { if self.in_same_block(cx, item.span) { - match item.kind { - ItemKind::Mod(ident, _) => { - self.mod_names.insert(ident.name); - }, - ItemKind::Use(use_tree, _) => { - self.use_block.push(use_tree); - }, - _ => {}, - } } else { self.try_lint(cx); self.clear(); - match item.kind { - ItemKind::Mod(ident, _) => { - self.mod_names.insert(ident.name); - }, - ItemKind::Use(use_tree, _) => { - self.use_block.push(use_tree); - }, - _ => {}, - } + } + match item.kind { + ItemKind::Mod(ident, _) => { + self.mod_names.insert(ident.name); + }, + ItemKind::Use(use_tree, _) => { + self.use_block.push(use_tree); + }, + _ => {}, } self.latest_span = match self.latest_span { Some(span) => Some(span.with_hi(item.span.hi())), @@ -170,6 +164,6 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { fn clear(&mut self) { self.use_block.clear(); self.mod_names.clear(); - // self.spans.clear(); + self.latest_span = None; } } From fd03d91b5983f413b8c1c481cc6a140bf29c1bbc Mon Sep 17 00:00:00 2001 From: lengyijun Date: Fri, 10 Oct 2025 15:01:04 +0800 Subject: [PATCH 21/23] wip --- clippy_lints/src/use_crate_prefix_for_self_imports.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index 95fac5ce0207..f519b15ad777 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -106,9 +106,14 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { } let gap_span = latest_span.between(span); let gap_snippet = gap_span.get_source_text(cx).unwrap(); + println!("{:?}", tokenize_with_text(&gap_snippet).collect::>()); for (token, source, inner_span) in tokenize_with_text(&gap_snippet) { match token { - rustc_lexer::TokenKind::Whitespace => return false, + rustc_lexer::TokenKind::Whitespace => { + if source.chars().filter(|c| *c == '\n').count() > 1 { + return false; + } + }, _ => {}, } } From b5ac4a47b58f964380e2305803dbec12810c5dec Mon Sep 17 00:00:00 2001 From: lengyijun Date: Sun, 12 Oct 2025 10:28:56 +0800 Subject: [PATCH 22/23] uitest --- .../{pass_sibling => pass_sibling_comment}/Cargo.toml | 2 +- .../{pass_sibling => pass_sibling_comment}/src/foo.rs | 0 .../{pass_sibling => pass_sibling_comment}/src/main.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename tests/ui-cargo/use_crate_prefix_for_self_imports/{pass_sibling => pass_sibling_comment}/Cargo.toml (71%) rename tests/ui-cargo/use_crate_prefix_for_self_imports/{pass_sibling => pass_sibling_comment}/src/foo.rs (100%) rename tests/ui-cargo/use_crate_prefix_for_self_imports/{pass_sibling => pass_sibling_comment}/src/main.rs (83%) diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/Cargo.toml similarity index 71% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/Cargo.toml index 0924d8d033a1..e6b8b5732c0a 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pass_sibling" +name = "pass_sibling_comment" version = "0.1.0" edition = "2024" publish = false diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/src/foo.rs similarity index 100% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/src/foo.rs diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/src/main.rs similarity index 83% rename from tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs rename to tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/src/main.rs index ccd452fe6a7e..27a166b0f09b 100644 --- a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_comment/src/main.rs @@ -1,7 +1,7 @@ #![warn(clippy::use_crate_prefix_for_self_imports)] mod foo; -//fadsfsadfa +// some comments here use foo::Foo; fn main() { From fcf45ca366a13e997e9f9c5dc1ea9b7fc92c0fd3 Mon Sep 17 00:00:00 2001 From: lengyijun Date: Sun, 12 Oct 2025 10:26:57 +0800 Subject: [PATCH 23/23] cargo uitest: pass --- .../src/use_crate_prefix_for_self_imports.rs | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs index f519b15ad777..6c92770dbe9e 100644 --- a/clippy_lints/src/use_crate_prefix_for_self_imports.rs +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -5,10 +5,10 @@ use def_id::LOCAL_CRATE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{Attribute, Item, ItemKind, UsePath, def_id}; +use rustc_hir::{Item, ItemKind, UsePath, def_id}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol, kw}; +use rustc_span::{FileName, RealFileName, Span, Symbol, kw}; declare_clippy_lint! { /// ### What it does @@ -83,21 +83,6 @@ impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { } impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { - /* - fn in_same_block(&self, span: Span) -> bool { - if self.spans.is_empty() { - return true; - } - if self.spans.iter().any(|x| x.contains(span)) { - return true; - } - if self.spans.iter().any(|x| span.lo() - x.hi() == BytePos(1)) { - return true; - } - false - } - */ - fn in_same_block(&self, cx: &LateContext<'tcx>, span: Span) -> bool { match self.latest_span { Some(latest_span) => { @@ -106,15 +91,10 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { } let gap_span = latest_span.between(span); let gap_snippet = gap_span.get_source_text(cx).unwrap(); - println!("{:?}", tokenize_with_text(&gap_snippet).collect::>()); - for (token, source, inner_span) in tokenize_with_text(&gap_snippet) { - match token { - rustc_lexer::TokenKind::Whitespace => { - if source.chars().filter(|c| *c == '\n').count() > 1 { - return false; - } - }, - _ => {}, + for (token, source, _) in tokenize_with_text(&gap_snippet) { + if token == rustc_lexer::TokenKind::Whitespace && source.chars().filter(|c| *c == '\n').count() > 1 + { + return false; } } true @@ -124,8 +104,10 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { } fn insert_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { - if self.in_same_block(cx, item.span) { - } else { + if item.span.from_expansion() { + return; + } + if !self.in_same_block(cx, item.span) { self.try_lint(cx); self.clear(); } @@ -139,7 +121,7 @@ impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { _ => {}, } self.latest_span = match self.latest_span { - Some(span) => Some(span.with_hi(item.span.hi())), + Some(latest_span) => Some(latest_span.with_hi(item.span.hi())), None => Some(item.span), }; }