aboutsummaryrefslogtreecommitdiff
path: root/lib/src/lints/faster_zipattrswith.rs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src/lints/faster_zipattrswith.rs')
-rw-r--r--lib/src/lints/faster_zipattrswith.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/src/lints/faster_zipattrswith.rs b/lib/src/lints/faster_zipattrswith.rs
new file mode 100644
index 0000000..139d499
--- /dev/null
+++ b/lib/src/lints/faster_zipattrswith.rs
@@ -0,0 +1,72 @@
1use crate::{
2 make,
3 session::{SessionInfo, Version},
4 Metadata, Report, Rule, Suggestion,
5};
6
7use if_chain::if_chain;
8use macros::lint;
9use rnix::{
10 types::{Select, TypedNode},
11 NodeOrToken, SyntaxElement, SyntaxKind,
12};
13
14/// ## What it does
15/// Checks for `lib.zipAttrsWith`.
16///
17/// ## Why is this bad?
18/// Nix 2.6 introduces `builtins.zipAttrsWith` which is faster and does
19/// not require a lib import.
20///
21/// ## Example
22///
23/// ```nix
24/// lib.zipAttrsWith (name: values: values) [ {a = "x";} {a = "y"; b = "z";} ]
25/// # { a = ["x" "y"]; b = ["z"] }
26/// ```
27///
28/// Replace `lib.zipAttrsWith` with `builtins.zipAttrsWith`:
29///
30/// ```nix
31/// builtins.zipAttrsWith (name: values: values) [ {a = "x";} {a = "y"; b = "z";} ]
32/// ```
33#[lint(
34 name = "faster_zipattrswith",
35 note = "Found lib.zipAttrsWith",
36 code = 16,
37 match_with = SyntaxKind::NODE_SELECT
38)]
39struct FasterZipAttrsWith;
40
41impl Rule for FasterZipAttrsWith {
42 fn validate(&self, node: &SyntaxElement, sess: &SessionInfo) -> Option<Report> {
43 let lint_version = "2.6".parse::<Version>().unwrap();
44 if_chain! {
45 if sess.version() >= &lint_version;
46 if let NodeOrToken::Node(node) = node;
47 if let Some(select_expr) = Select::cast(node.clone());
48 if let Some(select_from) = select_expr.set();
49 if let Some(zip_attrs_with) = select_expr.index();
50
51 // a heuristic to lint on nixpkgs.lib.zipAttrsWith
52 // and lib.zipAttrsWith and its variants
53 if select_from.text().to_string() != "builtins";
54 if zip_attrs_with.text().to_string() == "zipAttrsWith";
55
56 then {
57 let at = node.text_range();
58 let replacement = {
59 let builtins = make::ident("builtins");
60 make::select(builtins.node(), &zip_attrs_with).node().clone()
61 };
62 let message = format!("Prefer `builtins.zipAttrsWith` over `{}.zipAttrsWith`", select_from);
63 Some(
64 self.report()
65 .suggest(at, message, Suggestion::new(at, replacement)),
66 )
67 } else {
68 None
69 }
70 }
71 }
72}