about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--book/src/development/emitting_lints.md114
1 files changed, 62 insertions, 52 deletions
diff --git a/book/src/development/emitting_lints.md b/book/src/development/emitting_lints.md
index a716ae315d1..e803aa126d6 100644
--- a/book/src/development/emitting_lints.md
+++ b/book/src/development/emitting_lints.md
@@ -1,17 +1,18 @@
 # Emitting a lint
 
-Once we have [defined a lint](define_lints.md), written [UI tests](write_tests.md)
-and chosen [the lint pass](lint_passes.md) for the lint, we can begin the
-implementation of the lint logic so that we can emit it and gradually work
-towards a lint that behaves as expected.
+Once we have [defined a lint](define_lints.md), written [UI
+tests](write_tests.md) and chosen [the lint pass](lint_passes.md) for the lint,
+we can begin the implementation of the lint logic so that we can emit it and
+gradually work towards a lint that behaves as expected.
 
 Note that we will not go into concrete implementation of a lint logic in this
-chapter. We will go into details in later chapters as well as in two examples
-of real Clippy lints.
+chapter. We will go into details in later chapters as well as in two examples of
+real Clippy lints.
 
-To emit a lint, we must implement a pass (see [Lint Passes](lint_passes.md)) for the lint that we have
-declared. In this example we'll implement a "late" lint, so take a look at the [LateLintPass][late_lint_pass]
-documentation, which provides an abundance of methods that we can implement for our lint.
+To emit a lint, we must implement a pass (see [Lint Passes](lint_passes.md)) for
+the lint that we have declared. In this example we'll implement a "late" lint,
+so take a look at the [LateLintPass][late_lint_pass] documentation, which
+provides an abundance of methods that we can implement for our lint.
 
 ```rust
 pub trait LateLintPass<'tcx>: LintPass {
@@ -19,31 +20,32 @@ pub trait LateLintPass<'tcx>: LintPass {
 }
 ```
 
-By far the most common method used for Clippy lints is [`check_expr` method][late_check_expr],
-this is because Rust is an expression language and, more often than not,
-the lint we want to work on must examine expressions.
+By far the most common method used for Clippy lints is [`check_expr`
+method][late_check_expr], this is because Rust is an expression language and,
+more often than not, the lint we want to work on must examine expressions.
 
-> _Note:_ If you don't fully understand what expressions are in Rust,
-> take a look at the official documentation on [expressions][rust_expressions]
+> _Note:_ If you don't fully understand what expressions are in Rust, take a
+> look at the official documentation on [expressions][rust_expressions]
 
 Other common ones include the [`check_fn` method][late_check_fn] and the
 [`check_item` method][late_check_item].
 
 ### Emitting a lint
 
-Inside the trait method that we implement, we can write down the lint logic
-and emit the lint with suggestions.
+Inside the trait method that we implement, we can write down the lint logic and
+emit the lint with suggestions.
 
-Clippy's [diagnostics] provides quite a few diagnostic functions that we can
-use to emit lints. Take a look at the documentation to pick one that suits
-your lint's needs the best. Some common ones you will encounter in the Clippy
+Clippy's [diagnostics] provides quite a few diagnostic functions that we can use
+to emit lints. Take a look at the documentation to pick one that suits your
+lint's needs the best. Some common ones you will encounter in the Clippy
 repository includes:
 
 - [`span_lint`]: Emits a lint without providing any other information
 - [`span_lint_and_note`]: Emits a lint and adds a note
 - [`span_lint_and_help`]: Emits a lint and provides a helpful message
 - [`span_lint_and_sugg`]: Emits a lint and provides a suggestion to fix the code
-- [`span_lint_and_then`]: Like `span_lint`, but allows for a lot of output customization.
+- [`span_lint_and_then`]: Like `span_lint`, but allows for a lot of output
+  customization.
 
 ```rust
 impl<'tcx> LateLintPass<'tcx> for LintName {
@@ -63,16 +65,17 @@ impl<'tcx> LateLintPass<'tcx> for LintName {
 }
 ```
 
-> Note: The message should be matter of fact and avoid
-> capitalization and punctuation. If multiple sentences are needed, the messages should probably be split up into an
-> error + a help / note / suggestion message.
+> Note: The message should be matter of fact and avoid capitalization and
+> punctuation. If multiple sentences are needed, the messages should probably be
+> split up into an error + a help / note / suggestion message.
 
 ## Suggestions: Automatic fixes
 
 Some lints know what to change in order to fix the code. For example, the lint
-[`range_plus`][range_plus_one] warns for ranges where the user wrote `x..y + 1` instead of using an
-[inclusive range][inclusive_range] (`x..=1`). The fix to this code would be changing the `x..y + 1` expression
-to `x..=y`. **This is where suggestions come in**.
+[`range_plus_one`][range_plus_one] warns for ranges where the user wrote `x..y +
+1` instead of using an [inclusive range][inclusive_range] (`x..=y`). The fix to
+this code would be changing the `x..y + 1` expression to `x..=y`. **This is
+where suggestions come in**.
 
 A suggestion is a change that the lint provides to fix the issue it is linting.
 The output looks something like this (from the example earlier):
@@ -85,16 +88,17 @@ LL |     for _ in 1..1 + 1 {}
    |              ^^^^^^^^ help: use: `1..=1`
 ```
 
-**Not all suggestions are always right**, some of them require human supervision, that's why we have
-[Applicability][applicability].
+**Not all suggestions are always right**, some of them require human
+supervision, that's why we have [Applicability][applicability].
 
-Applicability indicates confidence in the correctness of the suggestion, some are always right
-(`Applicability::MachineApplicable`), but we use `Applicability::MaybeIncorrect` and others when talking about a lint
-that may be incorrect.
+Applicability indicates confidence in the correctness of the suggestion, some
+are always right (`Applicability::MachineApplicable`), but we use
+`Applicability::MaybeIncorrect` and others when talking about a suggestion that
+may be incorrect.
 
----
+### Example
 
-The same lint `LINT_NAME` but that emits a suggestion would be something like this:
+The same lint `LINT_NAME` but that emits a suggestion would look something like this:
 
 ```rust
 impl<'tcx> LateLintPass<'tcx> for LintName {
@@ -107,22 +111,27 @@ impl<'tcx> LateLintPass<'tcx> for LintName {
                 span,
                 "message on why the lint is emitted",
                 "use",
-                "suggestion (don't forget to integrate things from the source, like variable names)", // < Suggestion
-                Applicability::MachineApplicable
+                format!("foo + {} * bar", snippet(cx, expr.span, "<default>")), // < Suggestion
+                Applicability::MachineApplicable,
             );
         }
     }
 }
 ```
 
-Suggestions generally use the [`format!`](format_macro) macro to interpolate the old values with the new ones.
+Suggestions generally use the [`format!`](format_macro) macro to interpolate the
+old values with the new ones. To get code snippets, use one of the `snippet*`
+functions from `clippy_utils::source`.
 
 ## How to choose between notes, help messages and suggestions
 
-Notes are presented separately from the main lint message, they provide useful information that the user needs to
-understand why the lint was activated. They are the most helpful when attached to a span.
+Notes are presented separately from the main lint message, they provide useful
+information that the user needs to understand why the lint was activated. They
+are the most helpful when attached to a span.
 
-Example:
+Examples:
+
+### Notes
 
 ```text
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
@@ -139,10 +148,11 @@ note: argument has type &SomeStruct
    |            ^^^^^^^^^^^
 ```
 
----
+### Help Messages
 
-Help messages are specifically to help the user. These are used in situation where you can't provide a specific
-machine applicable suggestion. They can also be attached to a span.
+Help messages are specifically to help the user. These are used in situation
+where you can't provide a specific machine applicable suggestion. They can also
+be attached to a span.
 
 Example:
 
@@ -156,10 +166,11 @@ error: constant division of 0.0 with 0.0 will always result in NaN
    = help: consider using `f64::NAN` if you would like a constant representing NaN
 ```
 
----
+### Suggestions
 
-Suggestions are the most helpful, they are changes to the source code to fix the error. The magic
-in suggestions is that tools like `rustfix` can detect them and automatically fix your code.
+Suggestions are the most helpful, they are changes to the source code to fix the
+error. The magic in suggestions is that tools like `rustfix` can detect them and
+automatically fix your code.
 
 Example:
 
@@ -170,21 +181,20 @@ error: This `.fold` can be more succinctly expressed as `.any`
 390 |     let _ = (0..3).fold(false, |acc, x| acc || x > 2);
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)`
     |
-    = note: `-D fold-any` implied by `-D warnings`
 ```
 
 ### Snippets
 
-Snippets are pieces of the source code (as a string), they are extracted generally using the [`snippet`][snippet_fn]
-function.
+Snippets are pieces of the source code (as a string), they are extracted
+generally using the [`snippet`][snippet_fn] function.
 
-For example, if you want to know how an item looks (and you know the item's span), you could use
-`snippet(cx, span, "..")`.
+For example, if you want to know how an item looks (and you know the item's
+span), you could use `snippet(cx, span, "..")`.
 
 ## Final: Run UI Tests to Emit the Lint
 
-Now, if we run our [UI test](write_tests.md), we should see that the compiler now
-produce output that contains the lint message we designed.
+Now, if we run our [UI test](write_tests.md), we should see that Clippy now
+produces output that contains the lint message we designed.
 
 The next step is to implement the logic properly, which is a detail that we will
 cover in the next chapters.