1 use crate::utils::{in_macro, snippet_with_macro_callsite, span_lint_and_sugg, sugg};
2 use if_chain::if_chain;
3 use rustc_errors::Applicability;
4 use rustc_hir::{Block, ExprKind};
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
9 /// **What it does:** Looks for blocks of expressions and fires if the last expression returns `()`
10 /// but is not followed by a semicolon.
12 /// **Why is this bad?** The semicolon might be optional but when
13 /// extending the block with new code, it doesn't require a change in previous last line.
15 /// **Known problems:** None.
21 /// println!("Hello world")
27 /// println!("Hello world");
30 pub SEMICOLON_IF_NOTHING_RETURNED,
32 "add a semicolon if nothing is returned"
35 declare_lint_pass!(SemicolonIfNothingReturned => [SEMICOLON_IF_NOTHING_RETURNED]);
37 impl LateLintPass<'_> for SemicolonIfNothingReturned {
38 fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
40 if !in_macro(block.span);
41 if let Some(expr) = block.expr;
42 let t_expr = cx.typeck_results().expr_ty(expr);
44 if let snippet = snippet_with_macro_callsite(cx, expr.span, "}");
45 if !snippet.ends_with('}');
47 // filter out the desugared `for` loop
48 if let ExprKind::DropTemps(..) = &expr.kind {
52 let sugg = sugg::Sugg::hir_with_macro_callsite(cx, &expr, "..");
53 let suggestion = format!("{0};", sugg);
56 SEMICOLON_IF_NOTHING_RETURNED,
57 expr.span.source_callsite(),
58 "consider adding a `;` to the last statement for consistent formatting",
61 Applicability::MaybeIncorrect,