Skip to content

Commit 237a01d

Browse files
committed
Update documentation for adding new lints
- Add instructions for adding new lints with the new automation
1 parent ea82cbe commit 237a01d

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed

doc/adding_lints.md

+48-28
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ because that's clearly a non-descriptive name.
99

1010
- [Adding a new lint](#adding-a-new-lint)
1111
- [Setup](#setup)
12+
- [Getting Started](#getting-started)
1213
- [Testing](#testing)
1314
- [Rustfix tests](#rustfix-tests)
1415
- [Edition 2018 tests](#edition-2018-tests)
@@ -31,6 +32,19 @@ which can change rapidly. Make sure you're working near rust-clippy's master,
3132
and use the `setup-toolchain.sh` script to configure the appropriate toolchain
3233
for the Clippy directory.
3334

35+
### Getting Started
36+
37+
There is a bit of boilerplate code that needs to be set up when creating a new
38+
lint. Fortunately, you can use the clippy dev tools to handle this for you. We
39+
are naming our new lint `foo_functions` (lints are generally written in snake
40+
case), and we don't need type information so it will have an early pass type
41+
(more on this later on). To get started on this lint you can run
42+
`./util/dev new_lint --name=foo_functions --pass=early --category=pedantic`
43+
(category will default to nursery if not provided). This command will create
44+
two files: `tests/ui/foo_functions.rs` and `clippy_lints/src/foo_functions.rs`,
45+
as well as run `./util/dev update_lints` to register the new lint. Next, we'll
46+
open up these files and add our lint!
47+
3448
### Testing
3549

3650
Let's write some tests first that we can execute while we iterate on our lint.
@@ -41,11 +55,9 @@ we want to check. The output of Clippy is compared against a `.stderr` file.
4155
Note that you don't have to create this file yourself, we'll get to
4256
generating the `.stderr` files further down.
4357

44-
We start by creating the test file at `tests/ui/foo_functions.rs`. It doesn't
45-
really matter what the file is called, but it's a good convention to name it
46-
after the lint it is testing, so `foo_functions.rs` it is.
58+
We start by opening the test file created at `tests/ui/foo_functions.rs`.
4759

48-
Inside the file we put some examples to get started:
60+
Update the file with some examples to get started:
4961

5062
```rust
5163
#![warn(clippy::foo_functions)]
@@ -90,8 +102,8 @@ Once we are satisfied with the output, we need to run
90102
`tests/ui/update-all-references.sh` to update the `.stderr` file for our lint.
91103
Please note that, we should run `TESTNAME=foo_functions cargo uitest`
92104
every time before running `tests/ui/update-all-references.sh`.
93-
Running `TESTNAME=foo_functions cargo uitest` should pass then. When we
94-
commit our lint, we need to commit the generated `.stderr` files, too.
105+
Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit
106+
our lint, we need to commit the generated `.stderr` files, too.
95107

96108
### Rustfix tests
97109

@@ -121,26 +133,42 @@ With tests in place, let's have a look at implementing our lint now.
121133

122134
### Lint declaration
123135

124-
We start by creating a new file in the `clippy_lints` crate. That's the crate
125-
where all the lint code is. We are going to call the file
126-
`clippy_lints/src/foo_functions.rs` and import some initial things we need:
136+
Let's start by opening the new file created in the `clippy_lints` crate
137+
at `clippy_lints/src/foo_functions.rs`. That's the crate where all the
138+
lint code is. This file has already imported some initial things we will need:
127139

128140
```rust
129-
use rustc::lint::{LintArray, LintPass, EarlyLintPass};
141+
use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
130142
use rustc_session::{declare_lint_pass, declare_tool_lint};
143+
use syntax::ast::*;
131144
```
132145

133-
The next step is to provide a lint declaration. Lints are declared using the
134-
[`declare_clippy_lint!`][declare_clippy_lint] macro:
146+
The next step is to update the lint declaration. Lints are declared using the
147+
[`declare_clippy_lint!`][declare_clippy_lint] macro, and we just need to update
148+
the auto-generated lint declaration to have a real description, something like this:
135149

136150
```rust
137151
declare_clippy_lint! {
152+
/// **What it does:**
153+
///
154+
/// **Why is this bad?**
155+
///
156+
/// **Known problems:** None.
157+
///
158+
/// **Example:**
159+
///
160+
/// ```rust
161+
/// // example code
162+
/// ```
138163
pub FOO_FUNCTIONS,
139164
pedantic,
140165
"function named `foo`, which is not a descriptive name"
141166
}
142167
```
143168

169+
* The section of lines prefixed with `///` constitutes the lint documentation
170+
section. This is the default documentation style and will be displayed at
171+
https://rust-lang.github.io/rust-clippy/master/index.html.
144172
* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming
145173
guidelines][lint_naming] here when naming your lint. In short, the name should
146174
state the thing that is being checked for and read well when used with
@@ -150,8 +178,8 @@ state the thing that is being checked for and read well when used with
150178
* The last part should be a text that explains what exactly is wrong with the
151179
code
152180

153-
With our lint declaration done, we will now make sure that it is assigned to a
154-
lint pass:
181+
The rest of this file contains an empty implementation for our lint pass,
182+
which in this case is `EarlyLintPass` and should look like this:
155183

156184
```rust
157185
// clippy_lints/src/foo_functions.rs
@@ -166,12 +194,9 @@ impl EarlyLintPass for FooFunctions {}
166194
Don't worry about the `name` method here. As long as it includes the name of the
167195
lint pass it should be fine.
168196

169-
Next we need to run `util/dev update_lints` to register the lint in various
170-
places, mainly in `clippy_lints/src/lib.rs`.
171-
172-
While `update_lints` automates some things, it doesn't automate everything. We
173-
will have to register our lint pass manually in the `register_plugins` function
174-
in `clippy_lints/src/lib.rs`:
197+
The new lint automation runs `update_lints`, which automates some things, but it
198+
doesn't automate everything. We will have to register our lint pass manually in
199+
the `register_plugins` function in `clippy_lints/src/lib.rs`:
175200

176201
```rust
177202
reg.register_early_lint_pass(box foo_functions::FooFunctions);
@@ -195,14 +220,9 @@ In short, the `LateLintPass` has access to type information while the
195220
`EarlyLintPass`. The `EarlyLintPass` is also faster. However linting speed
196221
hasn't really been a concern with Clippy so far.
197222

198-
Since we don't need type information for checking the function name, we are
199-
going to use the `EarlyLintPass`. It has to be imported as well, changing our
200-
imports to:
201-
202-
```rust
203-
use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
204-
use rustc::{declare_tool_lint, lint_array};
205-
```
223+
Since we don't need type information for checking the function name, we used
224+
`--pass=early` when running the new lint automation and all the imports were
225+
added accordingly.
206226

207227
### Emitting a lint
208228

0 commit comments

Comments
 (0)