diff --git a/CHANGELOG.md b/CHANGELOG.md index 78020c2dac611..d5dbbabb3c5cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1284,6 +1284,7 @@ Released 2018-09-13 [`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern +[`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next diff --git a/README.md b/README.md index 8f65ff94ca8e6..0cb14eda6a881 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 349 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 350 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 91240362445a7..7008c6d6839de 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -284,6 +284,7 @@ pub mod replace_consts; pub mod returns; pub mod serde_api; pub mod shadow; +pub mod single_component_path_imports; pub mod slow_vector_initialization; pub mod strings; pub mod suspicious_trait_impl; @@ -741,6 +742,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, &shadow::SHADOW_UNRELATED, + &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, @@ -993,6 +995,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box utils::internal_lints::ProduceIce); store.register_late_pass(|| box let_underscore::LetUnderscore); store.register_late_pass(|| box atomic_ordering::AtomicOrdering); + store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1296,6 +1299,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), + LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), @@ -1431,6 +1435,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&returns::LET_AND_RETURN), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), + LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d00d8dfbd3ed8..6e5015eb84496 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2310,7 +2310,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi &format!("used `unwrap()` on `{}` value", kind,), &format!( "if you don't want to handle the `{}` case gracefully, consider \ - using `expect()` to provide a better panic message", + using `expect()` to provide a better panic message", none_value, ), ); @@ -2679,7 +2679,7 @@ fn lint_filter_flat_map<'a, 'tcx>( if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an `Iterator`"; let hint = "this is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning `iter::empty()`"; + and filtering by returning `iter::empty()`"; span_lint_and_help(cx, FILTER_MAP, expr.span, msg, hint); } } @@ -2695,7 +2695,7 @@ fn lint_filter_map_flat_map<'a, 'tcx>( if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`"; let hint = "this is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning `iter::empty()`"; + and filtering by returning `iter::empty()`"; span_lint_and_help(cx, FILTER_MAP, expr.span, msg, hint); } } @@ -3148,7 +3148,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>( let msg = format!( "called `{0}` (or with one of deref aliases) on an Option value. \ - This can be done more directly by calling `{1}` instead", + This can be done more directly by calling `{1}` instead", current_method, hint ); span_lint_and_sugg( diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs new file mode 100644 index 0000000000000..eb3261bebe315 --- /dev/null +++ b/clippy_lints/src/single_component_path_imports.rs @@ -0,0 +1,61 @@ +use crate::utils::span_lint_and_sugg; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::edition::Edition; +use syntax::ast::{Item, ItemKind, UseTreeKind}; + +declare_clippy_lint! { + /// **What it does:** Checking for imports with single component use path. + /// + /// **Why is this bad?** Import with single component use path such as `use cratename;` + /// is not necessary, and thus should be removed. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust, ignore + /// use regex; + /// + /// fn main() { + /// regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); + /// } + /// ``` + /// Better as + /// ```rust, ignore + /// fn main() { + /// regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); + /// } + /// ``` + pub SINGLE_COMPONENT_PATH_IMPORTS, + style, + "imports with single component path are redundant" +} + +declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]); + +impl EarlyLintPass for SingleComponentPathImports { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if_chain! { + if cx.sess.opts.edition == Edition::Edition2018; + if !item.vis.node.is_pub(); + if let ItemKind::Use(use_tree) = &item.kind; + if let segments = &use_tree.prefix.segments; + if segments.len() == 1; + if let UseTreeKind::Simple(None, _, _) = use_tree.kind; + then { + span_lint_and_sugg( + cx, + SINGLE_COMPONENT_PATH_IMPORTS, + item.span, + "this import is redundant", + "remove it entirely", + String::new(), + Applicability::MachineApplicable + ); + } + } + } +} diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4fcf39d214288..e47f2480a541d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -316,7 +316,7 @@ impl Types { OPTION_OPTION, hir_ty.span, "consider using `Option` instead of `Option>` or a custom \ - enum if you need to distinguish all 3 cases", + enum if you need to distinguish all 3 cases", ); return; // don't recurse into the type } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5dbcb4483f2eb..b762c8d139514 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 349] = [ +pub const ALL_LINTS: [Lint; 350] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1855,6 +1855,13 @@ pub const ALL_LINTS: [Lint; 349] = [ deprecation: None, module: "methods", }, + Lint { + name: "single_component_path_imports", + group: "style", + desc: "imports with single component path are redundant", + deprecation: None, + module: "single_component_path_imports", + }, Lint { name: "single_match", group: "style", diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed new file mode 100644 index 0000000000000..7a882efc4d18a --- /dev/null +++ b/tests/ui/single_component_path_imports.fixed @@ -0,0 +1,12 @@ +// run-rustfix +// compile-flags: --edition 2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + + +use serde as edres; +pub use serde; + +fn main() { + regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); +} diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs new file mode 100644 index 0000000000000..d084425cd70f3 --- /dev/null +++ b/tests/ui/single_component_path_imports.rs @@ -0,0 +1,12 @@ +// run-rustfix +// compile-flags: --edition 2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +use regex; +use serde as edres; +pub use serde; + +fn main() { + regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); +} diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr new file mode 100644 index 0000000000000..519ada0169a6d --- /dev/null +++ b/tests/ui/single_component_path_imports.stderr @@ -0,0 +1,10 @@ +error: this import is redundant + --> $DIR/single_component_path_imports.rs:6:1 + | +LL | use regex; + | ^^^^^^^^^^ help: remove it entirely + | + = note: `-D clippy::single-component-path-imports` implied by `-D warnings` + +error: aborting due to previous error +