about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-16 12:37:22 +0000
committerbors <bors@rust-lang.org>2023-08-16 12:37:22 +0000
commit87d148759a9f02f880076d6fe7d67bf759a8a3fa (patch)
tree933dd702ee39edaa117d855ee415167a58af8f08
parent710db18ccd03b7dd13dd1a937890cca45581a494 (diff)
parent783c119768c14e1349c49c599410b7e0e60e0c4e (diff)
downloadrust-87d148759a9f02f880076d6fe7d67bf759a8a3fa.tar.gz
rust-87d148759a9f02f880076d6fe7d67bf759a8a3fa.zip
Auto merge of #10595 - blyxyas:book-define_lints, r=flip1995
Clippy Book Chapter Updates Reborn: Defining Lints

Revival of #9659, I've made a few changes (mainly ones from reviews from #9426, like removing mid-section storytelling) and some re-writes. The goal of the project would be to slowly re-write the Clippy book (only chapters that need it) to more up-to-date style.

## Notes

- Things like `git status` commands have changed, we need to make sure that they're correct.
- As this is a team-wide effort, I would please ask anyone and everyone to read it and give your opinion.
- To talk about the whole project, please use the tracking issue for the project #10597  (It also contains a timeline, discussions and more information)

---

changelog: Add a new "Defining lints" chapter to the book

r? `@flip1995`
-rw-r--r--book/src/SUMMARY.md1
-rw-r--r--book/src/development/defining_lints.md205
2 files changed, 206 insertions, 0 deletions
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 22fbdce75e8..f6378b1fb90 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -13,6 +13,7 @@
 - [Development](development/README.md)
     - [Basics](development/basics.md)
     - [Adding Lints](development/adding_lints.md)
+    - [Defining Lints](development/defining_lints.md)
     - [Lint Passes](development/lint_passes.md)
     - [Type Checking](development/type_checking.md)
     - [Macro Expansions](development/macro_expansions.md)
diff --git a/book/src/development/defining_lints.md b/book/src/development/defining_lints.md
new file mode 100644
index 00000000000..7c4aa5d4523
--- /dev/null
+++ b/book/src/development/defining_lints.md
@@ -0,0 +1,205 @@
+# Define New Lints
+
+The first step in the journey of a new lint is the definition
+and registration of the lint in Clippy's codebase.
+We can use the Clippy dev tools to handle this step since setting up the
+lint involves some boilerplate code.
+
+#### Lint types
+
+A lint type is the category of items and expressions in which your lint focuses on.
+
+As of the writing of this documentation update, there are 12 _types_ of lints
+besides the numerous standalone lints living under `clippy_lints/src/`:
+
+- `cargo`
+- `casts`
+- `functions`
+- `loops`
+- `matches`
+- `methods`
+- `misc_early`
+- `operators`
+- `transmute`
+- `types`
+- `unit_types`
+- `utils / internal` (Clippy internal lints)
+
+These types group together lints that share some common behaviors. For instance,
+`functions` groups together lints that deal with some aspects of functions in
+Rust, like definitions, signatures and attributes.
+
+For more information, feel free to compare the lint files under any category
+with [All Clippy lints][all_lints] or ask one of the maintainers.
+
+## Lint name
+
+A good lint name is important, make sure to 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.
+
+---
+
+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.
+
+## Add and Register the Lint
+
+Now that a name is chosen, we shall register `foo_functions` as a lint to the
+codebase. There are two ways to register a lint.
+
+### Standalone
+
+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 command in your Clippy project:
+
+```sh
+$ cargo dev new_lint --name=lint_name --pass=late --category=pedantic
+```
+
+There are two things to note here:
+
+1. `--pass`: We set `--pass=late` in this command to do a late lint pass. The
+   alternative is an `early` lint pass. We will discuss this difference in a
+   later chapter.
+   <!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
+2. `--category`: If not provided, the `category` of this new lint will default
+   to `nursery`.
+
+The `cargo dev new_lint` command will create a new file:
+`clippy_lints/src/foo_functions.rs` as well as [register the
+lint](#lint-registration).
+
+Overall, you should notice that the following files are modified or created:
+
+```sh
+$ git status
+On branch foo_functions
+Changes not staged for commit:
+  (use "git add <file>..." to update what will be committed)
+  (use "git restore <file>..." to discard changes in working directory)
+	modified:   CHANGELOG.md
+	modified:   clippy_lints/src/lib.register_lints.rs
+	modified:   clippy_lints/src/lib.register_pedantic.rs
+	modified:   clippy_lints/src/lib.rs
+
+Untracked files:
+  (use "git add <file>..." to include in what will be committed)
+	clippy_lints/src/foo_functions.rs
+	tests/ui/foo_functions.rs
+```
+
+
+### Specific Type
+
+> **Note**: Lint types are listed in the ["Lint types"](#lint-types) section
+
+If you believe that this new lint belongs to a specific type of lints,
+you can run `cargo dev new_lint` with a `--type` option.
+
+Since our `foo_functions` lint is related to function calls, one could
+argue that we should put it into a group of lints that detect some behaviors
+of functions, we can put it in the `functions` group.
+
+Let's run the following command in your Clippy project:
+
+```sh
+$ cargo dev new_lint --name=foo_functions --type=functions --category=pedantic
+```
+
+This command will create, among other things, a new file:
+`clippy_lints/src/{type}/foo_functions.rs`.
+In our case, the path will be `clippy_lints/src/functions/foo_functions.rs`.
+
+Notice how this command has a `--type` flag instead of `--pass`. Unlike a standalone
+definition, this lint won't be registered in the traditional sense. Instead, you will
+call your lint from within the type's lint pass, found in `clippy_lints/src/{type}/mod.rs`.
+
+A _type_ is just the name of a directory in `clippy_lints/src`, like `functions` in
+the example command. Clippy groups together some lints that share common behaviors,
+so if your lint falls into one, it would be best to add it to that type.
+
+Overall, you should notice that the following files are modified or created:
+
+```sh
+$ git status
+On branch foo_functions
+Changes not staged for commit:
+  (use "git add <file>..." to update what will be committed)
+  (use "git restore <file>..." to discard changes in working directory)
+	modified:   CHANGELOG.md
+	modified:   clippy_lints/src/declared_lints.rs
+	modified:   clippy_lints/src/functions/mod.rs
+
+Untracked files:
+  (use "git add <file>..." to include in what will be committed)
+	clippy_lints/src/functions/foo_functions.rs
+	tests/ui/foo_functions.rs
+```
+
+
+## The `define_clippy_lints` macro
+
+After `cargo dev new_lint`, you should see a macro with the name
+`define_clippy_lints`. It will be in the same file if you defined a standalone
+lint, and it will be in `mod.rs` if you defined a type-specific lint.
+
+The macro looks something like this:
+
+```rust
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// // Describe here what does the lint do.
+    ///
+    /// Triggers when detects...
+    ///
+    /// ### Why is this bad?
+    ///
+    /// // Describe why this pattern would be bad
+    ///
+    /// It can lead to...
+    ///
+    /// ### Example
+    /// ```rust
+    /// // example code where clippy issues a warning
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// // example code which does not raise clippy warning
+    /// ```
+    #[clippy::version = "1.70.0"] // <- In which version was this implemented, keep it up to date!
+    pub LINT_NAME, // <- The lint name IN_ALL_CAPS
+    pedantic, // <- The lint group
+    "default lint description" // <- A lint description, e.g. "A function has an unit return type."
+}
+```
+
+## Lint registration
+
+If we run the `cargo dev new_lint` command for a new lint, the lint will be
+automatically registered and there is nothing more to do.
+
+However, sometimes we might want to declare a new lint by hand. In this case,
+we'd use `cargo dev update_lints` command afterwards.
+
+When a lint is manually declared, we might need to register the lint pass
+manually in the `register_plugins` function in `clippy_lints/src/lib.rs`:
+
+```rust
+store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
+```
+
+As you might have guessed, where there's something late, there is something
+early: in Clippy there is a `register_early_pass` method as well. More on early
+vs. late passes in a later chapter.
+<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
+
+Without a call to one of `register_early_pass` or `register_late_pass`, the lint
+pass in question will not be run.
+
+
+[all_lints]: https://rust-lang.github.io/rust-clippy/master/
+[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints