From 695aa59c6df35343ebbcb153f6249cde0d018139 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 18 Oct 2019 21:09:42 +0200 Subject: [PATCH] Add lint for exit --- clippy_lints/src/exit.rs | 41 +++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/exit.rs | 4 ++++ tests/ui/exit.stderr | 10 ++++++++ 5 files changed, 58 insertions(+) create mode 100644 clippy_lints/src/exit.rs create mode 100644 tests/ui/exit.rs create mode 100644 tests/ui/exit.stderr diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs new file mode 100644 index 000000000000..222f84bd028e --- /dev/null +++ b/clippy_lints/src/exit.rs @@ -0,0 +1,41 @@ +use crate::utils::{match_def_path, paths, qpath_res, span_lint}; +use if_chain::if_chain; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** `exit()` terminates the program and doesn't provide a + /// stack trace. + /// + /// **Why is this bad?** Ideally a program is terminated by finishing + /// the main function. + /// + /// **Known problems:** This can be valid code in main() to return + /// errors + /// + /// **Example:** + /// ```ignore + /// std::process::exit(0) + /// ``` + pub EXIT, + restriction, + "`std::process::exit` is called, terminating the program" +} + +declare_lint_pass!(Exit => [EXIT]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Exit { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if_chain! { + if let ExprKind::Call(ref path_expr, ref _args) = e.kind; + if let ExprKind::Path(ref path) = path_expr.kind; + if let Some(def_id) = qpath_res(cx, path, path_expr.hir_id).opt_def_id(); + if match_def_path(cx, def_id, &paths::EXIT); + then { + span_lint(cx, EXIT, e.span, "usage of `process::exit`"); + } + + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1bd117dae943..99bbaf32c290 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -188,6 +188,7 @@ pub mod escape; pub mod eta_reduction; pub mod eval_order_dependence; pub mod excessive_precision; +pub mod exit; pub mod explicit_write; pub mod fallible_impl_from; pub mod format; @@ -941,6 +942,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold)); store.register_late_pass(|| box unused_self::UnusedSelf); store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall); + reg.register_late_lint_pass(||box exit::Exit); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 9787517e5055..042ca4ee7fdc 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -27,6 +27,7 @@ pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; +pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; diff --git a/tests/ui/exit.rs b/tests/ui/exit.rs new file mode 100644 index 000000000000..1850241c4768 --- /dev/null +++ b/tests/ui/exit.rs @@ -0,0 +1,4 @@ +#[warn(clippy::exit)] +fn main() { + std::process::exit(1); +} diff --git a/tests/ui/exit.stderr b/tests/ui/exit.stderr new file mode 100644 index 000000000000..4fd294395501 --- /dev/null +++ b/tests/ui/exit.stderr @@ -0,0 +1,10 @@ +error: usage of `process::exit` + --> $DIR/exit.rs:3:5 + | +LL | std::process::exit(1); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::exit` implied by `-D warnings` + +error: aborting due to previous error +