Skip to content

Commit 97d31c8

Browse files
blyxyasnahuakang
authored andcommitted
New chapter: Defining Lints
Co-authored-by: Nahua <[email protected]>
1 parent 710db18 commit 97d31c8

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Development](development/README.md)
1414
- [Basics](development/basics.md)
1515
- [Adding Lints](development/adding_lints.md)
16+
- [Defining Lints](development/defining_lints.md)
1617
- [Lint Passes](development/lint_passes.md)
1718
- [Type Checking](development/type_checking.md)
1819
- [Macro Expansions](development/macro_expansions.md)
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Define New Lints
2+
3+
The first step in the journey of a new lint is the definition
4+
and registration of the lint in Clippy's codebase.
5+
We can use the Clippy dev tools to handle this step since setting up the
6+
lint involves some boilerplate code.
7+
8+
In our example, we're going to create a lint to detect functions named `foo` because it is a highly non-descriptive name for a function, so we want to trigger this and fix it early in the development process.
9+
10+
## Lint name
11+
12+
A good lint name is important, it is usually given by the issue you're fixing (in the **Lint name** field). If you're unsure if the name you chose fits the lint, you can check the [lint naming guidelines][lint_naming]. Don't worry, if the lint name doesn't fit, a Clippy team member will alert you in the PR process.
13+
14+
If you're still unsure, you can ask on the [Zulip] or on the Github issue / PR.
15+
16+
---
17+
18+
We'll name our example lint that detects functions named "foo" `foo_functions`. Check the [lint naming guidelines][lint_naming] to see why this name makes sense.
19+
20+
## Add and Register the Lint
21+
22+
Now that a name is chosen, we shall register `foo_functions` as a lint to the codebase.
23+
There are two ways to register a lint.
24+
25+
### Standalone
26+
27+
If you believe that this new lint is a standalone lint (that doesn't belong to any specific [type](#lint-types) like `functions` or `loops`), you can run the following
28+
command in your Clippy project:
29+
30+
```sh
31+
$ cargo dev new_lint --name=foo_functions --pass=late --category=pedantic
32+
```
33+
34+
There are two things to note here:
35+
36+
1. We set `--pass=late` in this command to do a late lint pass. The alternative
37+
is an `early` lint pass. We will discuss this difference in a later chapter.
38+
<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
39+
2. If not provided, the `category` of this new lint will default to `nursery`.
40+
See Clippy's [lint types](../lints.md) for more information on categories.
41+
42+
The `cargo dev new_lint` command will create a new file: `clippy_lints/src/foo_functions.rs`
43+
as well as [register the lint](#lint-registration).
44+
45+
Overall, you should notice that the following files are modified or created:
46+
47+
```sh
48+
$ git status
49+
On branch foo_functions
50+
Changes not staged for commit:
51+
(use "git add <file>..." to update what will be committed)
52+
(use "git restore <file>..." to discard changes in working directory)
53+
modified: CHANGELOG.md
54+
modified: clippy_lints/src/lib.register_lints.rs
55+
modified: clippy_lints/src/lib.register_pedantic.rs
56+
modified: clippy_lints/src/lib.rs
57+
58+
Untracked files:
59+
(use "git add <file>..." to include in what will be committed)
60+
clippy_lints/src/foo_functions.rs
61+
tests/ui/foo_functions.rs
62+
```
63+
64+
### Specific Type
65+
66+
If you believe that this new lint belongs to a specific type of lints,
67+
you can run `cargo dev new_lint` with a `--type` option.
68+
69+
Since our `foo_functions` lint is related to function calls, one could
70+
argue that we should put it into a group of lints that detect some behaviors
71+
of functions, we can put it in the `functions` group.
72+
73+
Let's run the following command in your Clippy project:
74+
75+
```sh
76+
$ cargo dev new_lint --name=foo_functions --type=functions --category=pedantic
77+
```
78+
79+
This command will create, among other things, a new file:
80+
`clippy_lints/src/{type}/foo_functions.rs`.
81+
In our case, the path will be `clippy_lints/src/functions/foo_functions.rs`.
82+
83+
Notice how this command has a `--type` flag instead of `--pass`. Unlike a standalone
84+
definition, this lint won't be registered in the traditional sense. Instead, you will
85+
call your lint from within the type's lint pass, found in `clippy_lints/src/{type}/mod.rs`.
86+
87+
A _type_ is just the name of a directory in `clippy_lints/src`, like `functions` in
88+
the example command. Clippy groups together some lints that share common behaviors,
89+
so if your lint falls into one, it would be best to add it to that type.
90+
Read more about [lint types](#lint-types) below.
91+
92+
Overall, you should notice that the following files are modified or created:
93+
94+
```sh
95+
$ git status
96+
On branch foo_functions
97+
Changes not staged for commit:
98+
(use "git add <file>..." to update what will be committed)
99+
(use "git restore <file>..." to discard changes in working directory)
100+
modified: CHANGELOG.md
101+
modified: clippy_lints/src/declared_lints.rs
102+
modified: clippy_lints/src/functions/mod.rs
103+
104+
Untracked files:
105+
(use "git add <file>..." to include in what will be committed)
106+
clippy_lints/src/functions/foo_functions.rs
107+
tests/ui/foo_functions.rs
108+
```
109+
110+
## Lint registration
111+
112+
If we run the `cargo dev new_lint` command for a new lint,
113+
the lint will be automatically registered and there is nothing more to do.
114+
115+
However, sometimes we might want to declare a new lint by hand.
116+
In this case, we'd use `cargo dev update_lints` command afterwards.
117+
118+
When a lint is manually declared, we might need to register the lint pass
119+
manually in the `register_plugins` function in `clippy_lints/src/lib.rs`:
120+
121+
```rust
122+
store.register_late_pass(|| Box::new(foo_functions::FooFunctions));
123+
```
124+
125+
As you might have guessed, where there's something late, there is something early:
126+
in Clippy there is a `register_early_pass` method as well.
127+
More on early vs. late passes in a later chapter.
128+
129+
Without a call to one of `register_early_pass` or `register_late_pass`,
130+
the lint pass in question will not be run.
131+
132+
## Lint types
133+
134+
As of the writing of this documentation update, there are 12 categories (a.k.a. _types_)
135+
of lints besides the numerous standalone lints living under `clippy_lints/src/`:
136+
137+
- `cargo`
138+
- `casts`
139+
- `functions`
140+
- `loops`
141+
- `matches`
142+
- `methods`
143+
- `misc_early`
144+
- `operators`
145+
- `transmute`
146+
- `types`
147+
- `unit_types`
148+
- `utils / internal` (Clippy internal lints)
149+
150+
These categories group together lints that share some common behaviors.
151+
For instance, as we have mentioned earlier, `functions` groups together lints
152+
that deal with some aspects of function calls in Rust.
153+
154+
For more information, feel free to compare the lint files under any category
155+
with [All Clippy lints][all_lints] or
156+
ask one of the maintainers.
157+
158+
[all_lints]: https://rust-lang.github.io/rust-clippy/master/
159+
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
160+
[clippy_team_members]: https://www.rust-lang.org/governance/teams/dev-tools#Clippy%20team
161+
[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy

0 commit comments

Comments
 (0)