@@ -7,16 +7,25 @@ creating an example lint from scratch.
77To get started, we will create a lint that detects functions called ` foo ` ,
88because that's clearly a non-descriptive name.
99
10+ * [ Setup] ( #Setup )
1011* [ Testing] ( #Testing )
12+ * [ Rustfix tests] ( #Rustfix-tests )
1113* [ Lint declaration] ( #Lint-declaration )
1214* [ Lint passes] ( #Lint-passes )
1315* [ Emitting a lint] ( #Emitting-a-lint )
1416* [ Adding the lint logic] ( #Adding-the-lint-logic )
1517* [ Documentation] ( #Documentation )
18+ * [ Running rustfmt] ( #Running-rustfmt )
1619* [ Debugging] ( #Debugging )
1720* [ PR Checklist] ( #PR-Checklist )
1821* [ Cheatsheet] ( #Cheatsheet )
1922
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+
2029### Testing
2130
2231Let'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
7584Running ` TESTNAME=ui/foo_functions cargo uitest ` should pass then. When you
7685commit your lint, be sure to commit the ` *.stderr ` files, too.
7786
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.
79106
80107### Lint declaration
81108
@@ -278,7 +305,44 @@ impl LintPass for Pass { /* .. */ }
278305```
279306
280307That 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.
282346
283347### Documentation
284348
@@ -309,6 +373,19 @@ declare_clippy_lint! { /* ... */ }
309373Once your lint is merged, this documentation will show up in the [ lint
310374list] [ lint_list ] .
311375
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+
312389### Debugging
313390
314391If you want to debug parts of your lint implementation, you can use the ` dbg! `
@@ -317,7 +394,7 @@ output in the `stdout` part.
317394
318395### PR Checklist
319396
320- TODO: Prose
397+ Before submitting your PR make sure you followed all of the basic requirements:
321398
322399- [ ] Followed [ lint naming conventions] [ lint_naming ]
323400- [ ] Added passing UI tests (including committed ` .stderr ` file)
@@ -329,7 +406,7 @@ TODO: Prose
329406Here are some pointers to things you are likely going to need for every lint:
330407
331408* [ 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)
333410* [ Clippy diagnostics] [ diagnostics ]
334411* [ The ` if_chain ` macro] [ if_chain ]
335412* [ ` in_macro ` ] [ in_macro ] and [ ` in_external_macro ` ] [ in_external_macro ]
0 commit comments