X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Fpanic_unimplemented.rs;h=d06e7f8fe1e0e58eef7f89cf37700c67da0d67bc;hb=b094bb1bd7f1cc702823c91ca509f338fedee24a;hp=617ac2393d511aa7511ca9572b73b6816eba947a;hpb=49dff2c9f34995af9d2d665e712fcf17924b33e3;p=rust.git diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 617ac2393d5..d06e7f8fe1e 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,29 +1,25 @@ -use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, paths, resolve_node, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_expn_of, match_panic_call}; use if_chain::if_chain; -use rustc::hir::ptr::P; -use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; -use syntax_pos::Span; +use rustc_hir::Expr; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; declare_clippy_lint! { - /// **What it does:** Checks for missing parameters in `panic!`. + /// **What it does:** Checks for usage of `panic!`. /// - /// **Why is this bad?** Contrary to the `format!` family of macros, there are - /// two forms of `panic!`: if there are no parameters given, the first argument - /// is not a format string and used literally. So while `format!("{}")` will - /// fail to compile, `panic!("{}")` will not. + /// **Why is this bad?** `panic!` will stop the execution of the executable /// /// **Known problems:** None. /// /// **Example:** /// ```no_run - /// panic!("This `panic!` is probably missing a parameter there: {}"); + /// panic!("even with a good reason"); /// ``` - pub PANIC_PARAMS, - style, - "missing parameters in `panic!` calls" + pub PANIC, + restriction, + "usage of the `panic!` macro" } declare_clippy_lint! { @@ -42,32 +38,63 @@ "`unimplemented!` should not be present in production code" } -declare_lint_pass!(PanicUnimplemented => [PANIC_PARAMS, UNIMPLEMENTED]); +declare_clippy_lint! { + /// **What it does:** Checks for usage of `todo!`. + /// + /// **Why is this bad?** This macro should not be present in production code + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```no_run + /// todo!(); + /// ``` + pub TODO, + restriction, + "`todo!` should not be present in production code" +} + +declare_clippy_lint! { + /// **What it does:** Checks for usage of `unreachable!`. + /// + /// **Why is this bad?** This macro can cause code to panic + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```no_run + /// unreachable!(); + /// ``` + pub UNREACHABLE, + restriction, + "usage of the `unreachable!` macro" +} + +declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PanicUnimplemented { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_chain! { - if let ExprKind::Block(ref block, _) = expr.node; - if let Some(ref ex) = block.expr; - if let ExprKind::Call(ref fun, ref params) = ex.node; - if let ExprKind::Path(ref qpath) = fun.node; - if let Some(fun_def_id) = resolve_node(cx, qpath, fun.hir_id).opt_def_id(); - if match_def_path(cx, fun_def_id, &paths::BEGIN_PANIC); - if params.len() == 2; - then { - if is_expn_of(expr.span, "unimplemented").is_some() { - let span = get_outer_span(expr); - span_lint(cx, UNIMPLEMENTED, span, - "`unimplemented` should not be present in production code"); - } else { - match_panic(params, expr, cx); - } +impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if match_panic_call(cx, expr).is_some() { + let span = get_outer_span(expr); + if is_expn_of(expr.span, "unimplemented").is_some() { + span_lint( + cx, + UNIMPLEMENTED, + span, + "`unimplemented` should not be present in production code", + ); + } else if is_expn_of(expr.span, "todo").is_some() { + span_lint(cx, TODO, span, "`todo` should not be present in production code"); + } else if is_expn_of(expr.span, "unreachable").is_some() { + span_lint(cx, UNREACHABLE, span, "usage of the `unreachable!` macro"); + } else if is_expn_of(expr.span, "panic").is_some() { + span_lint(cx, PANIC, span, "`panic` should not be present in production code"); } } } } -fn get_outer_span(expr: &Expr) -> Span { +fn get_outer_span(expr: &Expr<'_>) -> Span { if_chain! { if expr.span.from_expansion(); let first = expr.span.ctxt().outer_expn_data(); @@ -80,20 +107,3 @@ fn get_outer_span(expr: &Expr) -> Span { } } } - -fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext<'_, '_>) { - if_chain! { - if let ExprKind::Lit(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"); - } - } -}