Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 24847ea

Browse files
committed
Attempted start at sort_by_key_reverse lint
1 parent 7e84351 commit 24847ea

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed
Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,91 @@
1+
use crate::utils::{match_type, span_lint_and_sugg};
2+
use crate::utils::paths;
3+
use crate::utils::sugg::Sugg;
4+
use if_chain::if_chain;
5+
use rustc_errors::Applicability;
16
use rustc_lint::{LateLintPass, LateContext};
27
use rustc_session::{declare_lint_pass, declare_tool_lint};
38
use rustc_hir::*;
49

510
declare_clippy_lint! {
611
/// **What it does:**
12+
/// Detects when people use `Vec::sort_by` and pass in a function
13+
/// which compares the second argument to the first.
714
///
815
/// **Why is this bad?**
16+
/// It is more clear to use `Vec::sort_by_key` and `std::cmp::Reverse`
917
///
1018
/// **Known problems:** None.
1119
///
1220
/// **Example:**
1321
///
1422
/// ```rust
15-
/// // example code where clippy issues a warning
23+
/// vec.sort_by(|a, b| b.foo().cmp(&a.foo()));
1624
/// ```
1725
/// Use instead:
1826
/// ```rust
19-
/// // example code which does not raise clippy warning
27+
/// vec.sort_by_key(|e| Reverse(e.foo()));
2028
/// ```
2129
pub SORT_BY_KEY_REVERSE,
2230
complexity,
23-
"default lint description"
31+
"Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer"
2432
}
2533

2634
declare_lint_pass!(SortByKeyReverse => [SORT_BY_KEY_REVERSE]);
2735

28-
impl LateLintPass<'_, '_> for SortByKeyReverse {}
36+
struct LintTrigger {
37+
vec_name: String,
38+
closure_arg: String,
39+
closure_reverse_body: String,
40+
unstable: bool,
41+
}
42+
43+
fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> {
44+
if_chain! {
45+
if let ExprKind::MethodCall(name_ident, _, args) = &expr.kind;
46+
if let name = name_ident.ident.name.to_ident_string();
47+
if name == "sort_by" || name == "sort_unstable_by";
48+
if let [vec, Expr { kind: ExprKind::Closure(_, closure_decl, closure_body_id, _, _), .. }] = args;
49+
if closure_decl.inputs.len() == 2;
50+
if match_type(cx, &cx.tables.expr_ty(vec), &paths::VEC);
51+
then {
52+
let vec_name = Sugg::hir(cx, &args[0], "..").to_string();
53+
let unstable = name == "sort_unstable_by";
54+
Some(LintTrigger { vec_name, unstable, closure_arg: "e".to_string(), closure_reverse_body: "e".to_string() })
55+
} else {
56+
None
57+
}
58+
}
59+
}
60+
61+
impl LateLintPass<'_, '_> for SortByKeyReverse {
62+
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
63+
println!("{:?}", expr);
64+
span_lint_and_sugg(
65+
cx,
66+
SORT_BY_KEY_REVERSE,
67+
expr.span,
68+
"use Vec::sort_by_key here instead",
69+
"try",
70+
String::from("being a better person"),
71+
Applicability::MachineApplicable,
72+
);
73+
if let Some(trigger) = detect_lint(cx, expr) {
74+
span_lint_and_sugg(
75+
cx,
76+
SORT_BY_KEY_REVERSE,
77+
expr.span,
78+
"use Vec::sort_by_key here instead",
79+
"try",
80+
format!(
81+
"{}.sort{}_by_key(|{}| Reverse({}))",
82+
trigger.vec_name,
83+
if trigger.unstable { "_unstable" } else { "" },
84+
trigger.closure_arg,
85+
trigger.closure_reverse_body,
86+
),
87+
Applicability::MachineApplicable,
88+
);
89+
}
90+
}
91+
}

src/lintlist/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1987,7 +1987,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
19871987
Lint {
19881988
name: "sort_by_key_reverse",
19891989
group: "complexity",
1990-
desc: "default lint description",
1990+
desc: "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer",
19911991
deprecation: None,
19921992
module: "sort_by_key_reverse",
19931993
},

tests/ui/sort_by_key_reverse.fixed

Whitespace-only changes.

tests/ui/sort_by_key_reverse.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![warn(clippy::sort_by_key_reverse)]
22

33
fn main() {
4-
// test code goes here
4+
let mut vec = vec![3, 6, 1, 2, 5];
5+
vec.sort_by(|a, b| b.cmp(a));
56
}

tests/ui/sort_by_key_reverse.stderr

Whitespace-only changes.

0 commit comments

Comments
 (0)