@@ -7,16 +7,25 @@ creating an example lint from scratch.
7
7
To get started, we will create a lint that detects functions called ` foo ` ,
8
8
because that's clearly a non-descriptive name.
9
9
10
+ * [ Setup] ( #Setup )
10
11
* [ Testing] ( #Testing )
12
+ * [ Rustfix tests] ( #Rustfix-tests )
11
13
* [ Lint declaration] ( #Lint-declaration )
12
14
* [ Lint passes] ( #Lint-passes )
13
15
* [ Emitting a lint] ( #Emitting-a-lint )
14
16
* [ Adding the lint logic] ( #Adding-the-lint-logic )
15
17
* [ Documentation] ( #Documentation )
18
+ * [ Running rustfmt] ( #Running-rustfmt )
16
19
* [ Debugging] ( #Debugging )
17
20
* [ PR Checklist] ( #PR-Checklist )
18
21
* [ Cheatsheet] ( #Cheatsheet )
19
22
23
+ ### Setup
24
+
25
+ Clippy depends on the current git master version of rustc, which can change rapidly. Make sure you're
26
+ working near rust-clippy's master, and use the ` setup-toolchain.sh ` script to configure the appropriate
27
+ toolchain for this directory.
28
+
20
29
### Testing
21
30
22
31
Let's write some tests first that we can execute while we iterate on our lint.
@@ -75,7 +84,25 @@ Once you are satisfied with the output, you need to run
75
84
Running ` TESTNAME=ui/foo_functions cargo uitest ` should pass then. When you
76
85
commit your lint, be sure to commit the ` *.stderr ` files, too.
77
86
78
- Let's have a look at implementing our lint now.
87
+ ### Rustfix tests
88
+
89
+ If the lint you are working on is making use of structured suggestions, the
90
+ test file should include a ` // run-rustfix ` comment at the top. This will
91
+ additionally run [ rustfix] ( https://github.com/rust-lang-nursery/rustfix ) for
92
+ that test. Rustfix will apply the suggestions from the lint to the code of the
93
+ test file and compare that to the contents of a ` .fixed ` file.
94
+
95
+ Use ` tests/ui/update-all-references.sh ` to automatically generate the
96
+ ` .fixed ` file after running ` cargo test ` .
97
+
98
+ With tests in place, let's have a look at implementing our lint now.
99
+
100
+ ### Testing manually
101
+
102
+ Manually testing against an example file is useful if you have added some
103
+ ` println! ` s and test suite output becomes unreadable. To try Clippy with your
104
+ local modifications, run ` env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs `
105
+ from the working copy root.
79
106
80
107
### Lint declaration
81
108
@@ -278,7 +305,44 @@ impl LintPass for Pass { /* .. */ }
278
305
```
279
306
280
307
That should be it for the lint implementation. Running ` cargo test ` should now
281
- pass and we can finish up our work by adding some documentation.
308
+ pass.
309
+
310
+ ### Author lint
311
+
312
+ If you have trouble implementing your lint, there is also the internal ` author `
313
+ lint to generate Clippy code that detects the offending pattern. It does not
314
+ work for all of the Rust syntax, but can give a good starting point.
315
+
316
+ First, create a new UI test file in the ` tests/ui/ ` directory with the pattern
317
+ you want to match:
318
+
319
+ ``` rust
320
+ // ./tests/ui/my_lint.rs
321
+ fn main () {
322
+ #[clippy:: author]
323
+ let arr : [i32 ; 1 ] = [7 ]; // Replace line with the code you want to match
324
+ }
325
+ ```
326
+
327
+ Now you run ` TESTNAME=ui/my_lint cargo uitest ` to produce a ` .stdout ` file with
328
+ the generated code:
329
+
330
+ ``` rust
331
+ // ./tests/ui/my_lint.stdout
332
+
333
+ if_chain! {
334
+ if let ExprKind :: Array (ref elements ) = stmt . node;
335
+ if elements . len () == 1 ;
336
+ if let ExprKind :: Lit (ref lit ) = elements [0 ]. node;
337
+ if let LitKind :: Int (7 , _ ) = lit . node;
338
+ then {
339
+ // report your lint here
340
+ }
341
+ }
342
+ ```
343
+
344
+ If the command was executed successfully, you can copy the code over to where
345
+ you are implementing your lint.
282
346
283
347
### Documentation
284
348
@@ -309,6 +373,19 @@ declare_clippy_lint! { /* ... */ }
309
373
Once your lint is merged, this documentation will show up in the [ lint
310
374
list] [ lint_list ] .
311
375
376
+ ### Running rustfmt
377
+
378
+ [ Rustfmt] ( https://github.com/rust-lang/rustfmt ) is a tool for formatting Rust code according
379
+ to style guidelines. Your code has to be formatted by ` rustfmt ` before a PR can be merged.
380
+
381
+ It can be installed via ` rustup ` :
382
+
383
+ ``` bash
384
+ rustup component add rustfmt
385
+ ```
386
+
387
+ Use ` cargo fmt --all ` to format the whole codebase.
388
+
312
389
### Debugging
313
390
314
391
If you want to debug parts of your lint implementation, you can use the ` dbg! `
@@ -317,7 +394,7 @@ output in the `stdout` part.
317
394
318
395
### PR Checklist
319
396
320
- TODO: Prose
397
+ Before submitting your PR make sure you followed all of the basic requirements:
321
398
322
399
- [ ] Followed [ lint naming conventions] [ lint_naming ]
323
400
- [ ] Added passing UI tests (including committed ` .stderr ` file)
@@ -329,7 +406,7 @@ TODO: Prose
329
406
Here are some pointers to things you are likely going to need for every lint:
330
407
331
408
* [ Clippy utils] [ utils ] - Various helper functions. Maybe the function you need
332
- is already in here. (` implements_trait ` , ` match_path ` , ` snippet ` , etc)
409
+ is already in here (` implements_trait ` , ` match_path ` , ` snippet ` , etc)
333
410
* [ Clippy diagnostics] [ diagnostics ]
334
411
* [ The ` if_chain ` macro] [ if_chain ]
335
412
* [ ` in_macro ` ] [ in_macro ] and [ ` in_external_macro ` ] [ in_external_macro ]
0 commit comments