59 lines
1.5 KiB
Rust
59 lines
1.5 KiB
Rust
use crate::{ast, rules::NodeRule};
|
|
|
|
pub struct ListToAttrsMap;
|
|
|
|
impl NodeRule for ListToAttrsMap {
|
|
type Node = ast::Binding;
|
|
|
|
const ID: &'static str = "list_to_attrs_map";
|
|
|
|
fn select(data: &ast::NodeData) -> Option<&Self::Node> {
|
|
let ast::NodeData::Binding(binding) = data;
|
|
|
|
Some(binding)
|
|
}
|
|
|
|
fn check(node: &Self::Node) -> Option<&'static str> {
|
|
matches_list_to_attrs_map(&node.value)
|
|
.then_some("Use `lib.genAttrs'` instead of `lib.listToAttrs` after `map`")
|
|
}
|
|
}
|
|
|
|
fn matches_list_to_attrs_map(expr: &ast::Expr) -> bool {
|
|
let ast::Expr::Apply(application) = unwrap_expr(expr) else {
|
|
return false;
|
|
};
|
|
|
|
is_lib_list_to_attrs(&application.lambda) && is_map_application(&application.argument)
|
|
}
|
|
|
|
fn unwrap_expr(expr: &ast::Expr) -> &ast::Expr {
|
|
match expr {
|
|
ast::Expr::Other(expressions) if expressions.len() == 1 => unwrap_expr(&expressions[0]),
|
|
_ => expr,
|
|
}
|
|
}
|
|
|
|
fn is_lib_list_to_attrs(expr: &ast::Expr) -> bool {
|
|
matches!(
|
|
unwrap_expr(expr),
|
|
ast::Expr::Select(select) if select.receiver == "lib" && select.attr.name == "listToAttrs"
|
|
)
|
|
}
|
|
|
|
fn is_map_application(expr: &ast::Expr) -> bool {
|
|
let ast::Expr::Apply(application) = unwrap_expr(expr) else {
|
|
return false;
|
|
};
|
|
|
|
is_map(&application.lambda)
|
|
}
|
|
|
|
fn is_map(expr: &ast::Expr) -> bool {
|
|
match unwrap_expr(expr) {
|
|
ast::Expr::Ident(ident) => ident.name == "map",
|
|
ast::Expr::Apply(application) => is_map(&application.lambda),
|
|
_ => false,
|
|
}
|
|
}
|