Auto merge of #7928 - xFrednet:rust-90354-deploy-clippy-docs, r=flip1995
Reference `clippy_utils` docs on nightly-rustc and some other documentation updates The `clippy_utils` crate is now part of the nightly-rustc documentation. See [**very beautiful documentation**](https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/). This PR references them in our documentation and updates some other documentation. changelog: none
This commit is contained in:
commit
84a4ab7f3f
@ -155,14 +155,22 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
/// Converts a span to a code snippet if available, otherwise use default.
|
||||
/// Converts a span to a code snippet if available, otherwise returns the default.
|
||||
///
|
||||
/// This is useful if you want to provide suggestions for your lint or more generally, if you want
|
||||
/// to convert a given `Span` to a `str`.
|
||||
/// to convert a given `Span` to a `str`. To create suggestions consider using
|
||||
/// [`snippet_with_applicability`] to ensure that the applicability stays correct.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust,ignore
|
||||
/// snippet(cx, expr.span, "..")
|
||||
/// // Given two spans one for `value` and one for the `init` expression.
|
||||
/// let value = Vec::new();
|
||||
/// // ^^^^^ ^^^^^^^^^^
|
||||
/// // span1 span2
|
||||
///
|
||||
/// // The snipped call would return the corresponding code snippet
|
||||
/// snippet(cx, span1, "..") // -> "value"
|
||||
/// snippet(cx, span2, "..") // -> "Vec::new()"
|
||||
/// ```
|
||||
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
|
||||
|
@ -114,7 +114,12 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<
|
||||
|
||||
/// Checks whether a type implements a trait.
|
||||
/// The function returns false in case the type contains an inference variable.
|
||||
/// See also [`get_trait_def_id`](super::get_trait_def_id).
|
||||
///
|
||||
/// See:
|
||||
/// * [`get_trait_def_id`](super::get_trait_def_id) to get a trait [`DefId`].
|
||||
/// * [Common tools for writing lints] for an example how to use this function and other options.
|
||||
///
|
||||
/// [Common tools for writing lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md#checking-if-a-type-implements-a-specific-trait
|
||||
pub fn implements_trait<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
@ -254,9 +259,17 @@ pub fn is_type_ref_to_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_ite
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the type is equal to a diagnostic item
|
||||
/// Checks if the type is equal to a diagnostic item. To check if a type implements a
|
||||
/// trait marked with a diagnostic item use [`implements_trait`].
|
||||
///
|
||||
/// For a further exploitation what diagnostic items are see [diagnostic items] in
|
||||
/// rustc-dev-guide.
|
||||
///
|
||||
/// ---
|
||||
///
|
||||
/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
|
||||
///
|
||||
/// [Diagnostic Items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
|
||||
pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
|
||||
|
@ -634,7 +634,7 @@ in the following steps:
|
||||
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
|
||||
is already in here (`implements_trait`, `match_def_path`, `snippet`, etc)
|
||||
is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc)
|
||||
* [Clippy diagnostics][diagnostics]
|
||||
* [The `if_chain` macro][if_chain]
|
||||
* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro]
|
||||
@ -660,7 +660,10 @@ 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_utils/src/lib.rs
|
||||
[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.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
|
||||
[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html
|
||||
[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
|
||||
|
@ -4,7 +4,8 @@ You may need following tooltips to catch up with common operations.
|
||||
|
||||
- [Common tools for writing lints](#common-tools-for-writing-lints)
|
||||
- [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
|
||||
- [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
|
||||
- [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
|
||||
- [Checking for a specific type](#checking-for-a-specific-type)
|
||||
- [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
|
||||
- [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
|
||||
- [Dealing with macros](#dealing-with-macros)
|
||||
@ -15,7 +16,7 @@ Useful Rustc dev guide links:
|
||||
- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
|
||||
- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
|
||||
|
||||
# Retrieving the type of an expression
|
||||
## Retrieving the type of an expression
|
||||
|
||||
Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions:
|
||||
|
||||
@ -54,7 +55,7 @@ Two noticeable items here:
|
||||
created by type checking step, it includes useful information such as types
|
||||
of expressions, ways to resolve methods and so on.
|
||||
|
||||
# Checking if an expr is calling a specific method
|
||||
## Checking if an expr is calling a specific method
|
||||
|
||||
Starting with an `expr`, you can check whether it is calling a specific method `some_method`:
|
||||
|
||||
@ -63,9 +64,11 @@ impl LateLintPass<'_> for MyStructLint {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
if_chain! {
|
||||
// Check our expr is calling a method
|
||||
if let hir::ExprKind::MethodCall(path, _, _args, _) = &expr.kind;
|
||||
if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..], _) = &expr.kind;
|
||||
// Check the name of this method is `some_method`
|
||||
if path.ident.name == sym!(some_method);
|
||||
// Optionally, check the type of the self argument.
|
||||
// - See "Checking for a specific type"
|
||||
then {
|
||||
// ...
|
||||
}
|
||||
@ -74,7 +77,45 @@ impl LateLintPass<'_> for MyStructLint {
|
||||
}
|
||||
```
|
||||
|
||||
# Checking if a type implements a specific trait
|
||||
## Checking for a specific type
|
||||
|
||||
There are three ways to check if an expression type is a specific type we want to check for.
|
||||
All of these methods only check for the base type, generic arguments have to be checked separately.
|
||||
|
||||
```rust
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
||||
use clippy_utils::{paths, match_def_path};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_hir::LangItem;
|
||||
|
||||
impl LateLintPass<'_> for MyStructLint {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
// Getting the expression type
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
|
||||
// 1. Using diagnostic items
|
||||
// The last argument is the diagnostic item to check for
|
||||
if is_type_diagnostic_item(cx, ty, sym::Option) {
|
||||
// The type is an `Option`
|
||||
}
|
||||
|
||||
// 2. Using lang items
|
||||
if is_type_lang_item(cx, ty, LangItem::RangeFull) {
|
||||
// The type is a full range like `.drain(..)`
|
||||
}
|
||||
|
||||
// 3. Using the type path
|
||||
// This method should be avoided if possible
|
||||
if match_def_path(cx, def_id, &paths::RESULT) {
|
||||
// The type is a `core::result::Result`
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Prefer using diagnostic items and lang items where possible.
|
||||
|
||||
## Checking if a type implements a specific trait
|
||||
|
||||
There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
|
||||
|
||||
@ -102,6 +143,7 @@ impl LateLintPass<'_> for MyStructLint {
|
||||
|
||||
// 3. Using the type path with the expression
|
||||
// we use `match_trait_method` function from Clippy's utils
|
||||
// (This method should be avoided if possible)
|
||||
if match_trait_method(cx, expr, &paths::INTO) {
|
||||
// `expr` implements `Into` trait
|
||||
}
|
||||
@ -114,7 +156,7 @@ impl LateLintPass<'_> for MyStructLint {
|
||||
We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
|
||||
A list of defined paths for Clippy can be found in [paths.rs][paths]
|
||||
|
||||
# Checking if a type defines a specific method
|
||||
## Checking if a type defines a specific method
|
||||
|
||||
To check if our type defines a method called `some_method`:
|
||||
|
||||
@ -140,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
|
||||
}
|
||||
```
|
||||
|
||||
# Dealing with macros
|
||||
## Dealing with macros
|
||||
|
||||
There are several helpers in [`clippy_utils`][utils] to deal with macros:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user