1
Fork 0

Recommend let chains over if_chain in docs

This commit is contained in:
Alex Macleod 2022-05-09 14:23:16 +01:00
parent 5e4f092291
commit c9d88ef962
3 changed files with 17 additions and 21 deletions

View file

@ -69,7 +69,7 @@ and resolved paths.
To figure out how this syntax structure is encoded in the AST, it is recommended to run To figure out how this syntax structure is encoded in the AST, it is recommended to run
`rustc -Z unpretty=ast-tree` on an example of the structure and compare with the [nodes in the AST docs]. `rustc -Z unpretty=ast-tree` on an example of the structure and compare with the [nodes in the AST docs].
Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting]. Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting].
But we can make it nest-less by using [if_chain] macro, [like this][nest-less]. But we can make it nest-less by using [let chains], [like this][nest-less].
[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good-first-issue`] [`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good-first-issue`]
first. Sometimes they are only somewhat involved code wise, but not difficult per-se. first. Sometimes they are only somewhat involved code wise, but not difficult per-se.
@ -87,9 +87,9 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us
[`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium [`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium
[`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty [`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty
[nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/
[deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43 [deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/5e4f0922911536f80d9591180fa604229ac13939/clippy_lints/src/mem_forget.rs#L31-L45
[if_chain]: https://docs.rs/if_chain/*/if_chain [let chains]: https://github.com/rust-lang/rust/pull/94927
[nest-less]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/bit_mask.rs#L124-L150 [nest-less]: https://github.com/rust-lang/rust-clippy/blob/5e4f0922911536f80d9591180fa604229ac13939/clippy_lints/src/bit_mask.rs#L133-L159
## Writing code ## Writing code

View file

@ -656,7 +656,7 @@ Here are some pointers to things you are likely going to need for every lint:
* [Clippy utils][utils] - Various helper functions. Maybe the function you need * [Clippy utils][utils] - Various helper functions. Maybe the function you need
is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc) is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc)
* [Clippy diagnostics][diagnostics] * [Clippy diagnostics][diagnostics]
* [The `if_chain` macro][if_chain] * [Let chains][let-chains]
* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro]
* [`Span`][span] * [`Span`][span]
* [`Applicability`][applicability] * [`Applicability`][applicability]
@ -684,7 +684,7 @@ don't hesitate to ask on [Zulip] or in the issue/PR.
[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html [`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html
[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html [`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html
[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html [`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html
[if_chain]: https://docs.rs/if_chain/*/if_chain/ [let-chains]: https://github.com/rust-lang/rust/pull/94927
[from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [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 [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html
[span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html

View file

@ -62,16 +62,14 @@ Starting with an `expr`, you can check whether it is calling a specific method `
```rust ```rust
impl<'tcx> LateLintPass<'tcx> for MyStructLint { impl<'tcx> LateLintPass<'tcx> for MyStructLint {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if_chain! { // Check our expr is calling a method
// Check our expr is calling a method if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind
if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind;
// Check the name of this method is `some_method` // Check the name of this method is `some_method`
if path.ident.name == sym!(some_method); && path.ident.name == sym!(some_method)
// Optionally, check the type of the self argument. // Optionally, check the type of the self argument.
// - See "Checking for a specific type" // - See "Checking for a specific type"
then { {
// ... // ...
}
} }
} }
} }
@ -165,18 +163,16 @@ use clippy_utils::{is_type_diagnostic_item, return_ty};
impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
if_chain! { // Check if item is a method/function
// Check if item is a method/function if let ImplItemKind::Fn(ref signature, _) = impl_item.kind
if let ImplItemKind::Fn(ref signature, _) = impl_item.kind;
// Check the method is named `some_method` // Check the method is named `some_method`
if impl_item.ident.name == sym!(some_method); && impl_item.ident.name == sym!(some_method)
// We can also check it has a parameter `self` // We can also check it has a parameter `self`
if signature.decl.implicit_self.has_implicit_self(); && signature.decl.implicit_self.has_implicit_self()
// We can go further and even check if its return type is `String` // We can go further and even check if its return type is `String`
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)); && is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type))
then { {
// ... // ...
}
} }
} }
} }