Something went wrong. Try again.
Lints and suggestions for the Nix programming language
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596use crate::{Metadata, Report, Rule, Suggestion, make};
use macros::lint;use rnix::{ NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, ast::{AttrSet, Entry, HasEntry as _, Lambda, Param},};use rowan::ast::AstNode as _;
/// ## What it does/// Checks for an empty variadic pattern: `{...}`, in a function/// argument.////// ## Why is this bad?/// The intention with empty patterns is not instantly obvious. Prefer/// an underscore identifier instead, to indicate that the argument/// is being ignored.////// ## Example////// ```nix/// client = { ... }: {/// services.irmaseal-pkg.enable = true;/// };/// ```////// Replace the empty variadic pattern with `_` to indicate that you/// intend to ignore the argument:////// ```nix/// client = _: {/// services.irmaseal-pkg.enable = true;/// };/// ```#[lint( name = "empty_pattern", note = "Found empty pattern in function argument", code = 10, match_with = SyntaxKind::NODE_LAMBDA)]struct EmptyPattern;
impl Rule for EmptyPattern { fn validate(&self, node: &SyntaxElement) -> Option<Report> { let NodeOrToken::Node(node) = node else { return None; };
let lambda_expr = Lambda::cast(node.clone())?;
let Some(Param::Pattern(pattern)) = lambda_expr.param() else { return None; };
// no patterns within `{ }` if pattern.pat_entries().count() != 0 { return None; }
// pattern is not bound if pattern.pat_bind().is_some() { return None; }
if is_module(lambda_expr.body()?.syntax()) { return None; }
Some(self.report().suggest( pattern.syntax().text_range(), "This pattern is empty, use `_` instead", Suggestion::with_replacement( pattern.syntax().text_range(), make::ident("_").syntax().clone(), ), )) }}
fn is_module(body: &SyntaxNode) -> bool { let Some(attr_set) = AttrSet::cast(body.clone()) else { return false; };
attr_set .entries() .filter_map(|e| { let Entry::AttrpathValue(attrpath_value) = e else { return None; };
attrpath_value.attrpath() }) .any(|k| k.to_string() == "imports")}