| use clippy_utils::diagnostics::span_lint_and_then; |
| use rustc_ast::{Item, ItemKind, UseTreeKind}; |
| use rustc_errors::Applicability; |
| use rustc_lint::{EarlyContext, EarlyLintPass}; |
| use rustc_session::declare_lint_pass; |
| use rustc_span::symbol::kw; |
| |
| declare_clippy_lint! { |
| /// ### What it does |
| /// Checks for imports ending in `::{self}`. |
| /// |
| /// ### Why restrict this? |
| /// In most cases, this can be written much more cleanly by omitting `::{self}`. |
| /// |
| /// ### Known problems |
| /// Removing `::{self}` will cause any non-module items at the same path to also be imported. |
| /// This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt |
| /// to detect this scenario and that is why it is a restriction lint. |
| /// |
| /// ### Example |
| /// ```no_run |
| /// use std::io::{self}; |
| /// ``` |
| /// Use instead: |
| /// ```no_run |
| /// use std::io; |
| /// ``` |
| #[clippy::version = "1.53.0"] |
| pub UNNECESSARY_SELF_IMPORTS, |
| restriction, |
| "imports ending in `::{self}`, which can be omitted" |
| } |
| |
| declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]); |
| |
| impl EarlyLintPass for UnnecessarySelfImports { |
| fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { |
| if let ItemKind::Use(use_tree) = &item.kind |
| && let UseTreeKind::Nested { items, .. } = &use_tree.kind |
| && let [(self_tree, _)] = &**items |
| && let [self_seg] = &*self_tree.prefix.segments |
| && self_seg.ident.name == kw::SelfLower |
| && let Some(last_segment) = use_tree.prefix.segments.last() |
| { |
| span_lint_and_then( |
| cx, |
| UNNECESSARY_SELF_IMPORTS, |
| item.span, |
| "import ending with `::{self}`", |
| |diag| { |
| diag.span_suggestion( |
| last_segment.span().with_hi(item.span.hi()), |
| "consider omitting `::{self}`", |
| format!( |
| "{}{};", |
| last_segment.ident, |
| if let UseTreeKind::Simple(Some(alias)) = self_tree.kind { |
| format!(" as {alias}") |
| } else { |
| String::new() |
| }, |
| ), |
| Applicability::MaybeIncorrect, |
| ); |
| diag.note("this will slightly change semantics; any non-module items at the same path will also be imported"); |
| }, |
| ); |
| } |
| } |
| } |