Skip to content

Commit 9a37566

Browse files
authored
Merge pull request #2687 from phansch/explain_how_lints_work
Explain how Clippy and lints work
2 parents faefb4f + 3623378 commit 9a37566

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

CONTRIBUTING.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,56 @@ enabled as a plugin:
147147
#![plugin(clippy)]
148148
```
149149

150+
### How Clippy works
151+
152+
Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate.
153+
154+
[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them with the rustc plugin registry. For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this:
155+
156+
```rust
157+
// ./clippy_lints/src/lib.rs
158+
159+
// ...
160+
pub mod else_if_without_else;
161+
// ...
162+
163+
pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
164+
// ...
165+
reg.register_early_lint_pass(box else_if_without_else::ElseIfWithoutElse);
166+
// ...
167+
168+
reg.register_lint_group("clippy_restriction", vec![
169+
// ...
170+
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
171+
// ...
172+
]);
173+
}
174+
```
175+
176+
The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass].
177+
Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint.
178+
It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/update_lints.py` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time.
179+
180+
```rust
181+
// ./clippy_lints/src/else_if_without_else.rs
182+
183+
use rustc::lint::*;
184+
185+
// ...
186+
187+
pub struct ElseIfWithoutElse;
188+
189+
// ...
190+
191+
impl EarlyLintPass for ElseIfWithoutElse {
192+
// ... the functions needed, to make the lint work
193+
}
194+
```
195+
196+
The difference between `EarlyLintPass` and `LateLintPass` is that the methods of the `EarlyLintPass` trait only provide AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information via the `LateContext` parameter.
197+
198+
That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information.
199+
150200
## Contributions
151201

152202
Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will
@@ -156,3 +206,14 @@ main tree or given feedback for changes that would be required.
156206
All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/)
157207

158208
<!-- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md -->
209+
210+
[main_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/src/lib.rs#L14
211+
[lint_crate]: https://github.com/rust-lang-nursery/rust-clippy/tree/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src
212+
[lint_crate_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/lib.rs
213+
[else_if_without_else]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/else_if_without_else.rs
214+
[compiler_plugin]: https://doc.rust-lang.org/unstable-book/language-features/plugin.html#lint-plugins
215+
[plugin_registry]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html
216+
[reg_early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_early_lint_pass
217+
[reg_late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_late_lint_pass
218+
[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html
219+
[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html

0 commit comments

Comments
 (0)