Detect also when works

This commit is contained in:
JarredAllen 2020-05-24 20:05:58 -07:00
parent 059e8edd15
commit 07886a9764
3 changed files with 45 additions and 10 deletions

View File

@ -3,7 +3,7 @@ use crate::utils::paths;
use crate::utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, QPath};
use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Ident;
@ -16,7 +16,7 @@ declare_clippy_lint! {
/// **Why is this bad?**
/// It is more clear to use `Vec::sort_by_key` (or
/// `Vec::sort_by_key` and `std::cmp::Reverse` if necessary) than
/// using
/// using
///
/// **Known problems:** None.
///
@ -36,7 +36,17 @@ declare_clippy_lint! {
declare_lint_pass!(SortByKey => [SORT_BY_KEY]);
struct LintTrigger {
enum LintTrigger {
Sort(SortDetection),
SortByKey(SortByKeyDetection),
}
struct SortDetection {
vec_name: String,
unstable: bool,
}
struct SortByKeyDetection {
vec_name: String,
closure_arg: String,
closure_body: String,
@ -177,7 +187,18 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
};
let vec_name = Sugg::hir(cx, &args[0], "..").to_string();
let unstable = name == "sort_unstable_by";
Some(LintTrigger { vec_name, unstable, closure_arg, closure_body })
if_chain! {
if let ExprKind::Path(QPath::Resolved(_, Path {
segments: [PathSegment { ident: left_name, .. }], ..
})) = &left_expr.kind;
if left_name == left_ident;
then {
Some(LintTrigger::Sort(SortDetection { vec_name, unstable }))
}
else {
Some(LintTrigger::SortByKey(SortByKeyDetection { vec_name, unstable, closure_arg, closure_body }))
}
}
} else {
None
}
@ -186,8 +207,8 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
impl LateLintPass<'_, '_> for SortByKey {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if let Some(trigger) = detect_lint(cx, expr) {
utils::span_lint_and_sugg(
match detect_lint(cx, expr) {
Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg(
cx,
SORT_BY_KEY,
expr.span,
@ -201,7 +222,21 @@ impl LateLintPass<'_, '_> for SortByKey {
trigger.closure_body,
),
Applicability::MachineApplicable,
);
),
Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg(
cx,
SORT_BY_KEY,
expr.span,
"use Vec::sort here instead",
"try",
format!(
"{}.sort{}()",
trigger.vec_name,
if trigger.unstable { "_unstable" } else { "" },
),
Applicability::MachineApplicable,
),
None => {},
}
}
}

View File

@ -10,7 +10,7 @@ fn id(x: isize) -> isize {
fn main() {
let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5];
// Forward examples
vec.sort_by_key(|&a| a);
vec.sort();
vec.sort_by_key(|&a| (a + 5).abs());
vec.sort_by_key(|&a| id(-a));
// Reverse examples

View File

@ -1,8 +1,8 @@
error: use Vec::sort_by_key here instead
error: use Vec::sort here instead
--> $DIR/sort_by_key.rs:13:5
|
LL | vec.sort_by(|a, b| a.cmp(b));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| a)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()`
|
= note: `-D clippy::sort-by-key` implied by `-D warnings`