]> git.lizzy.rs Git - rust.git/blobdiff - doc/adding_lints.md
Merge commit 'b40ea209e7f14c8193ddfc98143967b6a2f4f5c9' into clippyup
[rust.git] / doc / adding_lints.md
index fd2a7d171d020aff7b99eb2826f199a6bd591287..99b86953d51a6287ceccb8bcb9207d881b0f368e 100644 (file)
@@ -18,6 +18,7 @@ because that's clearly a non-descriptive name.
   - [Lint passes](#lint-passes)
   - [Emitting a lint](#emitting-a-lint)
   - [Adding the lint logic](#adding-the-lint-logic)
+  - [Specifying the lint's minimum supported Rust version (MSRV)](#specifying-the-lints-minimum-supported-rust-version-msrv)
   - [Author lint](#author-lint)
   - [Documentation](#documentation)
   - [Running rustfmt](#running-rustfmt)
@@ -108,6 +109,9 @@ should only commit files changed by `cargo dev bless` for the
 specific lint you are creating/editing. Note that if the generated files are
 empty, they should be removed.
 
+Note that you can run multiple test files by specifying a comma separated list:
+`TESTNAME=foo_functions,test2,test3`.
+
 ### Cargo lints
 
 For cargo lints, the process of testing differs in that we are interested in
@@ -289,7 +293,7 @@ the next section. Let's worry about the details later and emit our lint for
 
 Depending on how complex we want our lint message to be, we can choose from a
 variety of lint emission functions. They can all be found in
-[`clippy_lints/src/utils/diagnostics.rs`][diagnostics].
+[`clippy_utils/src/diagnostics.rs`][diagnostics].
 
 `span_lint_and_help` seems most appropriate in this case. It allows us to
 provide an extra help message and we can't really suggest a better name
@@ -318,7 +322,7 @@ When code or an identifier must appear in a message or label, it should be
 surrounded with single grave accents \`.
 
 [check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn
-[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/diagnostics.rs
+[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/diagnostics.rs
 [the rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/diagnostics.html
 
 ## Adding the lint logic
@@ -384,18 +388,19 @@ pass.
 [`FnKind::Fn`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html#variant.Fn
 [ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html
 
-## Specifying the lint's minimum supported Rust version (msrv)
+## Specifying the lint's minimum supported Rust version (MSRV)
 
-Projects supporting older versions of Rust would need to disable a lint if it targets features
-present in later versions. Support for this can be added by specifying an msrv in your lint like so,
+Projects supporting older versions of Rust would need to disable a lint if it
+targets features present in later versions. Support for this can be added by
+specifying an MSRV in your lint like so,
 
 ```rust
 const MANUAL_STRIP_MSRV: RustcVersion = RustcVersion::new(1, 45, 0);
 ```
 
-The project's msrv will also have to be an attribute in the lint so you'll have to add a struct
-and constructor for your lint. The project's msrv needs to be passed when the lint is registered
-in `lib.rs`
+The project's MSRV will also have to be an attribute in the lint so you'll have
+to add a struct and constructor for your lint. The project's MSRV needs to be
+passed when the lint is registered in `lib.rs`
 
 ```rust
 pub struct ManualStrip {
@@ -410,8 +415,8 @@ impl ManualStrip {
 }
 ```
 
-The project's msrv can then be matched against the lint's msrv in the LintPass using the `meets_msrv` utility
-function.
+The project's MSRV can then be matched against the lint's `msrv` in the LintPass
+using the `meets_msrv` utility function.
 
 ``` rust
 if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
@@ -419,9 +424,10 @@ if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
 }
 ```
 
-The project's msrv can also be specified as an inner attribute, which overrides the value from
-`clippy.toml`. This can be accounted for using the `extract_msrv_attr!(LintContext)` macro and passing
-LateContext/EarlyContext.
+The project's MSRV can also be specified as an inner attribute, which overrides
+the value from `clippy.toml`. This can be accounted for using the
+`extract_msrv_attr!(LintContext)` macro and passing
+`LateContext`/`EarlyContext`.
 
 ```rust
 impl<'tcx> LateLintPass<'tcx> for ManualStrip {
@@ -432,8 +438,20 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 }
 ```
 
-Once the msrv is added to the lint, a relevant test case should be added to `tests/ui/min_rust_version_attr.rs`
-which verifies that the lint isn't emitted if the project's msrv is lower.
+Once the `msrv` is added to the lint, a relevant test case should be added to
+`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted
+if the project's MSRV is lower.
+
+As a last step, the lint should be added to the lint documentation. This is done
+in `clippy_lints/src/utils/conf.rs`:
+
+```rust
+define_Conf! {
+    /// Lint: LIST, OF, LINTS, <THE_NEWLY_ADDED_LINT>. The minimum rust version that the project supports
+    (msrv, "msrv": Option<String>, None),
+    ...
+}
+```
 
 ## Author lint
 
@@ -529,21 +547,21 @@ Before submitting your PR make sure you followed all of the basic requirements:
 
 ## Adding configuration to a lint
 
-Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace 
+Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace
 directory. Adding a configuration to a lint can be useful for thresholds or to constrain some
-behavior that can be seen as a false positive for some users. Adding a configuration is done 
+behavior that can be seen as a false positive for some users. Adding a configuration is done
 in the following steps:
 
-1. Adding a new configuration entry to [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs)
+1. Adding a new configuration entry to [clippy_utils::conf](/clippy_utils/src/conf.rs)
     like this:
     ```rust
     /// Lint: LINT_NAME. <The configuration field doc comment>
     (configuration_ident, "configuration_value": Type, DefaultValue),
     ```
-    The configuration value and identifier should usually be the same. The doc comment will be 
+    The configuration value and identifier should usually be the same. The doc comment will be
     automatically added to the lint documentation.
 2. Adding the configuration value to the lint impl struct:
-    1. This first requires the definition of a lint impl struct. Lint impl structs are usually 
+    1. This first requires the definition of a lint impl struct. Lint impl structs are usually
         generated with the `declare_lint_pass!` macro. This struct needs to be defined manually
         to add some kind of metadata to it:
         ```rust
@@ -560,7 +578,7 @@ in the following steps:
             LINT_NAME
         ]);
         ```
-    
+
     2. Next add the configuration value and a corresponding creation method like this:
         ```rust
         #[derive(Copy, Clone)]
@@ -580,16 +598,16 @@ in the following steps:
         ```
 3. Passing the configuration value to the lint impl struct:
 
-    First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). 
-    Make sure that `clippy dev update_lints` added it beforehand. The configuration value is now 
-    cloned or copied into a local value that is then passed to the impl struct like this:
+    First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs).
+    The configuration value is now cloned or copied into a local value that is then passed to the
+    impl struct like this:
     ```rust
     // Default generated registration:
-    store.register_late_pass(|| box module::StructName);
+    store.register_*_pass(|| box module::StructName);
 
     // New registration with configuration value
     let configuration_ident = conf.configuration_ident.clone();
-    store.register_late_pass(move || box module::StructName::new(configuration_ident));
+    store.register_*_pass(move || box module::StructName::new(configuration_ident));
     ```
 
     Congratulations the work is almost done. The configuration value can now be accessed
@@ -597,9 +615,9 @@ in the following steps:
 
 4. Adding tests:
     1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui).
-    2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). 
-        Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file 
-        with the configuration value and a rust file that should be linted by clippy. The test can 
+    2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml).
+        Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file
+        with the configuration value and a rust file that should be linted by Clippy. The test can
         otherwise be written as usual.
 
 ## Cheatsheet
@@ -633,7 +651,7 @@ documentation currently. This is unfortunate, but in most cases you can probably
 get away with copying things from existing similar lints. If you are stuck,
 don't hesitate to ask on [Zulip] or in the issue/PR.
 
-[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/mod.rs
+[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs
 [if_chain]: https://docs.rs/if_chain/*/if_chain/
 [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion
 [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html