From 77794e91e219b85663cf693d35f677e564151420 Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Wed, 23 May 2018 16:43:05 +0200 Subject: [PATCH] Create lint for unimplemented!() --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/panic.rs | 56 ++++++++++++++++++++++++++++++--------- tests/ui/panic.rs | 7 ++++- tests/ui/panic.stderr | 11 +++++++- 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3deece422..9e233837b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -815,6 +815,7 @@ All notable changes to this project will be documented in this file. [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity [`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc +[`unimplemented`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unimplemented [`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast diff --git a/README.md b/README.md index 9472156ec..506615014 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 258 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 259 lints included in this crate!](https://rust-lang-nursery.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 7864e90c1..9dd9a364b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -627,6 +627,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic::PANIC_PARAMS, + panic::UNIMPLEMENTED, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, ptr::CMP_NULL, @@ -749,6 +750,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic::PANIC_PARAMS, + panic::UNIMPLEMENTED, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index bd44b8d9b..7f1b6775b 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,8 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; +use syntax::ptr::P; +use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// @@ -22,12 +23,28 @@ declare_clippy_lint! { "missing parameters in `panic!` calls" } +/// **What it does:** Checks for usage of `unimplemented!`. +/// +/// **Why is this bad?** This macro should not be present in production code +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// unimplemented!(); +/// ``` +declare_clippy_lint! { + pub UNIMPLEMENTED, + style, + "`unimplemented!` should not be present in production code" +} + #[allow(missing_copy_implementations)] pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(PANIC_PARAMS) + lint_array!(PANIC_PARAMS, UNIMPLEMENTED) } } @@ -37,22 +54,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprBlock(ref block, _) = expr.node; if let Some(ref ex) = block.expr; if let ExprCall(ref fun, ref params) = ex.node; - if params.len() == 2; if let ExprPath(ref qpath) = fun.node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); - if let ExprLit(ref lit) = params[0].node; - if is_direct_expn_of(expr.span, "panic").is_some(); - if let LitKind::Str(ref string, _) = lit.node; - let string = string.as_str().replace("{{", "").replace("}}", ""); - if let Some(par) = string.find('{'); - if string[par..].contains('}'); - if params[0].span.source_callee().is_none(); - if params[0].span.lo() != params[0].span.hi(); + if params.len() == 2; then { - span_lint(cx, PANIC_PARAMS, params[0].span, - "you probably are missing some parameter in your format string"); + if is_expn_of(expr.span, "unimplemented").is_some() { + span_lint(cx, UNIMPLEMENTED, expr.span, + "`unimplemented` should not be present in production code"); + } else { + match_panic(params, expr, cx); + } } } } } + +fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { + if_chain! { + if let ExprLit(ref lit) = params[0].node; + if is_direct_expn_of(expr.span, "panic").is_some(); + if let LitKind::Str(ref string, _) = lit.node; + let string = string.as_str().replace("{{", "").replace("}}", ""); + if let Some(par) = string.find('{'); + if string[par..].contains('}'); + if params[0].span.source_callee().is_none(); + if params[0].span.lo() != params[0].span.hi(); + then { + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); + } + } +} diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs index d833d2651..56d06f239 100644 --- a/tests/ui/panic.rs +++ b/tests/ui/panic.rs @@ -1,7 +1,7 @@ -#![warn(panic_params)] +#![warn(panic_params, unimplemented)] fn missing() { if true { @@ -53,6 +53,10 @@ fn ok_escaped() { panic!("{case }}"); } +fn unimplemented() { + unimplemented!(); +} + fn main() { missing(); ok_single(); @@ -61,4 +65,5 @@ fn main() { ok_inner(); ok_nomsg(); ok_escaped(); + unimplemented(); } diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index 165c33cac..786a20c03 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -24,5 +24,14 @@ error: you probably are missing some parameter in your format string 15 | panic!("{{{this}}}"); | ^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: `unimplemented` should not be present in production code + --> $DIR/panic.rs:57:5 + | +57 | unimplemented!(); + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D unimplemented` implied by `-D warnings` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 5 previous errors