Auto merge of #5980 - matsujika:create-dir, r=flip1995

Add a lint to prevent `create_dir` from being used

This closes #5950
changelog: none
This commit is contained in:
bors 2020-09-10 14:34:22 +00:00
commit 5034d47f72
8 changed files with 114 additions and 0 deletions

View File

@ -1547,6 +1547,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

View File

@ -0,0 +1,51 @@
use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
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 let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::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!("create_dir_all({})", snippet(cx, args[0].span, "..")),
Applicability::MaybeIncorrect,
)
}
}
}
}

View File

@ -170,6 +170,7 @@ mod collapsible_if;
mod comparison_chain;
mod copies;
mod copy_iterator;
mod create_dir;
mod dbg_macro;
mod default_trait_access;
mod dereference;
@ -513,6 +514,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&copies::MATCH_SAME_ARMS,
&copies::SAME_FUNCTIONS_IN_IF_CONDITION,
&copy_iterator::COPY_ITERATOR,
&create_dir::CREATE_DIR,
&dbg_macro::DBG_MACRO,
&default_trait_access::DEFAULT_TRAIT_ACCESS,
&dereference::EXPLICIT_DEREF_METHODS,
@ -1044,6 +1046,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);
@ -1107,6 +1110,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),

View File

@ -110,6 +110,7 @@ pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"];
pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"];
pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];

View File

@ -297,6 +297,13 @@ pub static ref ALL_LINTS: Vec<Lint> = 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",

17
tests/ui/create_dir.fixed Normal file
View File

@ -0,0 +1,17 @@
// run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::create_dir)]
use std::fs::create_dir_all;
fn create_dir() {}
fn main() {
// Should be warned
create_dir_all("foo");
create_dir_all("bar").unwrap();
// Shouldn't be warned
create_dir();
std::fs::create_dir_all("foobar");
}

17
tests/ui/create_dir.rs Normal file
View File

@ -0,0 +1,17 @@
// run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::create_dir)]
use std::fs::create_dir_all;
fn create_dir() {}
fn main() {
// Should be warned
std::fs::create_dir("foo");
std::fs::create_dir("bar").unwrap();
// Shouldn't be warned
create_dir();
std::fs::create_dir_all("foobar");
}

View File

@ -0,0 +1,16 @@
error: calling `std::fs::create_dir` where there may be a better way
--> $DIR/create_dir.rs:11:5
|
LL | std::fs::create_dir("foo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `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:12:5
|
LL | std::fs::create_dir("bar").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `create_dir_all("bar")`
error: aborting due to 2 previous errors