@@ -88,6 +88,8 @@ LL | for _ in 1..1 + 1 {}
8888 | ^^^^^^^^ help: use: `1..=1`
8989```
9090
91+ ### Applicability
92+
9193** Not all suggestions are always right** , some of them require human
9294supervision, that's why we have [ Applicability] [ applicability ] .
9395
@@ -105,23 +107,26 @@ impl<'tcx> LateLintPass<'tcx> for LintName {
105107 fn check_expr (& mut self , cx : & LateContext <'tcx >, expr : & 'tcx Expr <'_ >) {
106108 // Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
107109 if some_lint_expr_logic (expr ) {
108- span_lint_and_sugg ( // < Note this change
110+ span_lint_and_then ( // < Note this change
109111 cx ,
110112 LINT_NAME ,
111- span ,
113+ expr . span,
112114 " message on why the lint is emitted" ,
113- " use" ,
114- format! (" foo + {} * bar" , snippet (cx , expr . span, " <default>" )), // < Suggestion
115- Applicability :: MachineApplicable ,
115+ | diag | {
116+ // v Build and emit the suggestion
117+ let mut app = Applicability :: MachineApplicable ;
118+ let expr_snippet = snippet_with_applicability (cx , expr . span, " _" , & mut app );
119+ let sugg = format! (" foo + {expr_snippet} * bar" );
120+ diag . span_suggestion (expr . span, " use" , sugg , app );
121+ }
116122 );
117123 }
118124 }
119125}
120126```
121127
122128Suggestions generally use the [ ` format! ` ] [ format_macro ] macro to interpolate the
123- old values with the new ones. To get code snippets, use one of the ` snippet* `
124- functions from ` clippy_utils::source ` .
129+ old values with the new ones. For information on getting code snippets, see [ Snippets] ( emitting_lints.md#snippets ) .
125130
126131## How to choose between notes, help messages and suggestions
127132
@@ -183,13 +188,50 @@ error: This `.fold` can be more succinctly expressed as `.any`
183188 |
184189```
185190
186- ### Snippets
191+ ## Snippets
187192
188193Snippets are pieces of the source code (as a string), they are extracted
189- generally using the [ ` snippet ` ] [ snippet_fn ] function.
194+ generally using the various ` snippet_* ` functions from [ ` clippy_utils::source ` ] [ ] .
195+
196+ If you're using the snippets _ not_ to build a suggestion, it's usually
197+ enough to use [ ` snippet ` ] [ snippet_fn ] -- it accepts the span of the item, and
198+ also a fallback string (see [ Fallback string] ( emitting_lints.md#fallback-string ) ).
190199
191200For example, if you want to know how an item looks (and you know the item's
192- span), you could use ` snippet(cx, span, "..") ` .
201+ span), you could use ` snippet(cx, span, "_") ` .
202+
203+ If you do use the snippet for a suggestion, it's recommended to use
204+ [ ` snippet_with_applicability ` ] instead. This is so that Clippy can reduce the
205+ [ applicability] ( emitting_lints.md#applicability ) of the suggestion in case it couldn't extract
206+ the snippet "cleanly" -- see the function's documentation for more information.
207+
208+ It's often necessary to create multiple snippets to build a suggestion, in which
209+ case you'll have the following pattern:
210+
211+ ``` rust
212+ // inside `span_lint_and_then`
213+
214+ // 1. Create initial applicability.
215+ let mut app = Applicability :: MachineApplicable ;
216+
217+ // 2. Use it to create all the snippets
218+ let foo_snippet = snippet_with_applicability (cx , foo . span, " _" , & mut app );
219+ let bar_snippet = snippet_with_applicability (cx , bar . span, " _" , & mut app );
220+ let sugg = format! (" {foo_snippet} + {bar_snippet}" ); // or whatever
221+
222+ // 3. Use it to emit the final suggestion
223+ diag . span_suggestion (span , msg , sugg , app );
224+ ```
225+
226+ ### Fallback string
227+ This is the string that is used for the snippet when the source code that the
228+ span points to is unavailable. That mostly only happens when proc-macros
229+ mishandle spans -- see [ the section on proc-macros] [ proc-macro-spans ] .
230+
231+ Most of the time, the snippets in a suggestion come from a (span of a) single
232+ expression, and so ` "_" ` is an appropriate fallback string. If you instead
233+ find yourself suggesting to insert multiple statements, or a block--basically
234+ anything "big"--then consider using ` ".." ` instead.
193235
194236## Final: Run UI Tests to Emit the Lint
195237
@@ -210,8 +252,11 @@ cover in the next chapters.
210252[ `span_lint_and_help` ] : https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_help.html
211253[ `span_lint_and_sugg` ] : https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html
212254[ `span_lint_and_then` ] : https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_then.html
255+ [ `clippy_utils::source` ] : https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/index.html
213256[ range_plus_one ] : https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
214257[ inclusive_range ] : https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
215258[ applicability ] : https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/enum.Applicability.html
216259[ snippet_fn ] : https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet.html
260+ [ `snippet_with_applicability` ] : https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet_with_applicability.html
261+ [ proc-macro-spans ] : macro_expansions.html#the-is_from_proc_macro-function
217262[ format_macro ] : https://doc.rust-lang.org/std/macro.format.html
0 commit comments