Update lint declaration example (#713)
This commit is contained in:
parent
01f01823ed
commit
6b85d54752
|
|
@ -482,35 +482,45 @@ declare_lint! {
|
||||||
"suggest using `loop { }` instead of `while true { }`"
|
"suggest using `loop { }` instead of `while true { }`"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a struct and `impl LintPass` for it.
|
// This declares a struct and a lint pass, providing a list of associated lints. The
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct WhileTrue;
|
|
||||||
|
|
||||||
// This declares a lint pass, providing a list of associated lints. The
|
|
||||||
// compiler currently doesn't use the associated lints directly (e.g., to not
|
// compiler currently doesn't use the associated lints directly (e.g., to not
|
||||||
// run the pass or otherwise check that the pass emits the appropriate set of
|
// run the pass or otherwise check that the pass emits the appropriate set of
|
||||||
// lints). However, it's good to be accurate here as it's possible that we're
|
// lints). However, it's good to be accurate here as it's possible that we're
|
||||||
// going to register the lints via the get_lints method on our lint pass (that
|
// going to register the lints via the get_lints method on our lint pass (that
|
||||||
// this macro generates).
|
// this macro generates).
|
||||||
impl_lint_pass!(
|
declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
|
||||||
WhileTrue => [WHILE_TRUE],
|
|
||||||
);
|
|
||||||
|
|
||||||
// LateLintPass has lots of methods. We only override the definition of
|
// Helper function for `WhileTrue` lint.
|
||||||
|
// Traverse through any amount of parenthesis and return the first non-parens expression.
|
||||||
|
fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
|
||||||
|
while let ast::ExprKind::Paren(sub) = &expr.kind {
|
||||||
|
expr = sub;
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// `EarlyLintPass` has lots of methods. We only override the definition of
|
||||||
// `check_expr` for this lint because that's all we need, but you could
|
// `check_expr` for this lint because that's all we need, but you could
|
||||||
// override other methods for your own lint. See the rustc docs for a full
|
// override other methods for your own lint. See the rustc docs for a full
|
||||||
// list of methods.
|
// list of methods.
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
|
impl EarlyLintPass for WhileTrue {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||||
if let hir::ExprWhile(ref cond, ..) = e.node {
|
if let ast::ExprKind::While(cond, ..) = &e.kind {
|
||||||
if let hir::ExprLit(ref lit) = cond.node {
|
if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
|
||||||
if let ast::LitKind::Bool(true) = lit.node {
|
if let ast::LitKind::Bool(true) = lit.kind {
|
||||||
if lit.span.ctxt() == SyntaxContext::empty() {
|
if !lit.span.from_expansion() {
|
||||||
let msg = "denote infinite loops with `loop { ... }`";
|
let msg = "denote infinite loops with `loop { ... }`";
|
||||||
let condition_span = cx.tcx.sess.source_map().def_span(e.span);
|
let condition_span = cx.sess.source_map().guess_head_span(e.span);
|
||||||
let mut err = cx.struct_span_lint(WHILE_TRUE, condition_span, msg);
|
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
|
||||||
err.span_suggestion_short(condition_span, "use `loop`", "loop".to_owned());
|
lint.build(msg)
|
||||||
err.emit();
|
.span_suggestion_short(
|
||||||
|
condition_span,
|
||||||
|
"use `loop`",
|
||||||
|
"loop".to_owned(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue