From 5574182b4d2d08c848a88a1ac5633fc194e0465e Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Fri, 28 Aug 2020 18:40:22 +0900 Subject: [PATCH] Add a new lint to prevent `create_dir` from being used --- CHANGELOG.md | 1 + clippy_lints/src/create_dir.rs | 50 ++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 4 +++ src/lintlist/mod.rs | 7 +++++ tests/ui/create_dir.fixed | 13 +++++++++ tests/ui/create_dir.rs | 13 +++++++++ tests/ui/create_dir.stderr | 16 +++++++++++ 7 files changed, 104 insertions(+) create mode 100644 clippy_lints/src/create_dir.rs create mode 100644 tests/ui/create_dir.fixed create mode 100644 tests/ui/create_dir.rs create mode 100644 tests/ui/create_dir.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 137b56102..b37273af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1444,6 +1444,7 @@ Released 2018-09-13 [`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator +[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir [`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute [`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro [`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs new file mode 100644 index 000000000..229536bd6 --- /dev/null +++ b/clippy_lints/src/create_dir.rs @@ -0,0 +1,50 @@ +use crate::utils::{match_qpath, snippet, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead. + /// + /// **Why is this bad?** Sometimes `std::fs::crate_dir` is mistakenly chosen over `std::fs::create_dir_all`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// std::fs::create_dir("foo") + /// ``` + /// Use instead: + /// ```rust + /// std::fs::create_dir_all("foo") + /// ``` + pub CREATE_DIR, + restriction, + "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`" +} + +declare_lint_pass!(CreateDir => [CREATE_DIR]); + +impl LateLintPass<'_> for CreateDir { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::Call(ref func, ref args) = expr.kind; + if let ExprKind::Path(ref path) = func.kind; + if match_qpath(path, &["std", "fs", "create_dir"]); + then { + span_lint_and_sugg( + cx, + CREATE_DIR, + expr.span, + "calling `std::fs::create_dir` where there may be a better way", + "consider calling `std::fs::create_dir_all` instead", + format!("std::fs::create_dir_all({})", snippet(cx, args[0].span, "..")), + Applicability::MachineApplicable, + ) + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 577ce6523..7943be34c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -169,6 +169,7 @@ mod collapsible_if; mod comparison_chain; mod copies; mod copy_iterator; +mod create_dir; mod dbg_macro; mod default_trait_access; mod dereference; @@ -511,6 +512,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &copies::MATCH_SAME_ARMS, &copies::SAME_FUNCTIONS_IN_IF_CONDITION, ©_iterator::COPY_ITERATOR, + &create_dir::CREATE_DIR, &dbg_macro::DBG_MACRO, &default_trait_access::DEFAULT_TRAIT_ACCESS, &dereference::EXPLICIT_DEREF_METHODS, @@ -1042,6 +1044,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); store.register_early_pass(|| box needless_continue::NeedlessContinue); + store.register_late_pass(|| box create_dir::CreateDir); store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType); store.register_early_pass(|| box redundant_static_lifetimes::RedundantStaticLifetimes); store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata); @@ -1104,6 +1107,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&arithmetic::FLOAT_ARITHMETIC), LintId::of(&arithmetic::INTEGER_ARITHMETIC), LintId::of(&as_conversions::AS_CONVERSIONS), + LintId::of(&create_dir::CREATE_DIR), LintId::of(&dbg_macro::DBG_MACRO), LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), LintId::of(&exit::EXIT), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 687fac7ba..e51345109 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -290,6 +290,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "copy_iterator", }, + Lint { + name: "create_dir", + group: "restriction", + desc: "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`", + deprecation: None, + module: "create_dir", + }, Lint { name: "crosspointer_transmute", group: "complexity", diff --git a/tests/ui/create_dir.fixed b/tests/ui/create_dir.fixed new file mode 100644 index 000000000..50f31f0c9 --- /dev/null +++ b/tests/ui/create_dir.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_must_use)] +#![warn(clippy::create_dir)] + +fn not_create_dir() {} + +fn main() { + std::fs::create_dir_all("foo"); + std::fs::create_dir_all("bar").unwrap(); + + not_create_dir(); + std::fs::create_dir_all("foobar"); +} diff --git a/tests/ui/create_dir.rs b/tests/ui/create_dir.rs new file mode 100644 index 000000000..00ef37f41 --- /dev/null +++ b/tests/ui/create_dir.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_must_use)] +#![warn(clippy::create_dir)] + +fn not_create_dir() {} + +fn main() { + std::fs::create_dir("foo"); + std::fs::create_dir("bar").unwrap(); + + not_create_dir(); + std::fs::create_dir_all("foobar"); +} diff --git a/tests/ui/create_dir.stderr b/tests/ui/create_dir.stderr new file mode 100644 index 000000000..3ae4680d9 --- /dev/null +++ b/tests/ui/create_dir.stderr @@ -0,0 +1,16 @@ +error: calling `std::fs::create_dir` where there may be a better way + --> $DIR/create_dir.rs:8:5 + | +LL | std::fs::create_dir("foo"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `std::fs::create_dir_all("foo")` + | + = note: `-D clippy::create-dir` implied by `-D warnings` + +error: calling `std::fs::create_dir` where there may be a better way + --> $DIR/create_dir.rs:9:5 + | +LL | std::fs::create_dir("bar").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `std::fs::create_dir_all("bar")` + +error: aborting due to 2 previous errors +