Lints and suggestions for the Nix programming language
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(useless_has_attr): let-else and try-expression

+45 -39
+45 -39
lib/src/lints/useless_has_attr.rs
··· 33 33 34 34 impl Rule for UselessHasAttr { 35 35 fn validate(&self, node: &SyntaxElement, _sess: &SessionInfo) -> Option<Report> { 36 - if let NodeOrToken::Node(node) = node 37 - && let Some(if_else_expr) = IfElse::cast(node.clone()) 38 - && let Some(condition_expr) = if_else_expr.condition() 39 - && let Some(default_expr) = if_else_expr.else_body() 40 - && let Some(cond_bin_expr) = BinOp::cast(condition_expr) 41 - && let Some(BinOpKind::IsSet) = cond_bin_expr.operator() 36 + let NodeOrToken::Node(node) = node else { 37 + return None; 38 + }; 42 39 43 - // set ? attr_path 44 - // ^^^--------------- lhs 45 - // ^^^^^^^^^^--- rhs 46 - && let Some(set) = cond_bin_expr.lhs() 47 - && let Some(attr_path) = cond_bin_expr.rhs() 40 + let if_else_expr = IfElse::cast(node.clone())?; 41 + let condition_expr = if_else_expr.condition()?; 42 + let default_expr = if_else_expr.else_body()?; 43 + let cond_bin_expr = BinOp::cast(condition_expr)?; 44 + let Some(BinOpKind::IsSet) = cond_bin_expr.operator() else { 45 + return None; 46 + }; 48 47 49 - // check if body of the `if` expression is of the form `set.attr_path` 50 - && let Some(body_expr) = if_else_expr.body() 51 - && let Some(body_select_expr) = Select::cast(body_expr) 52 - &&let expected_body = make::select(&set, &attr_path) 48 + // set ? attr_path 49 + // ^^^--------------- lhs 50 + // ^^^^^^^^^^--- rhs 51 + let set = cond_bin_expr.lhs()?; 52 + let attr_path = cond_bin_expr.rhs()?; 53 53 54 - // text comparison will do for now 55 - && body_select_expr.node().text() == expected_body.node().text() 56 - { 57 - let at = node.text_range(); 58 - // `or` is tightly binding, we need to parenthesize non-literal exprs 59 - let default_with_parens = match default_expr.kind() { 60 - SyntaxKind::NODE_LIST 61 - | SyntaxKind::NODE_PAREN 62 - | SyntaxKind::NODE_STRING 63 - | SyntaxKind::NODE_ATTR_SET 64 - | SyntaxKind::NODE_IDENT 65 - | SyntaxKind::NODE_SELECT => default_expr, 66 - _ => make::parenthesize(&default_expr).node().clone(), 67 - }; 68 - let replacement = make::or_default(&set, &attr_path, &default_with_parens) 69 - .node() 70 - .clone(); 71 - let message = format!("Consider using `{replacement}` instead of this `if` expression"); 72 - Some( 73 - self.report() 74 - .suggest(at, message, Suggestion::new(at, replacement)), 75 - ) 76 - } else { 77 - None 54 + // check if body of the `if` expression is of the form `set.attr_path` 55 + let body_expr = if_else_expr.body()?; 56 + let body_select_expr = Select::cast(body_expr)?; 57 + let expected_body = make::select(&set, &attr_path); 58 + 59 + // text comparison will do for now 60 + if body_select_expr.node().text() != expected_body.node().text() { 61 + return None; 78 62 } 63 + 64 + let at = node.text_range(); 65 + 66 + // `or` is tightly binding, we need to parenthesize non-literal exprs 67 + let default_with_parens = match default_expr.kind() { 68 + SyntaxKind::NODE_LIST 69 + | SyntaxKind::NODE_PAREN 70 + | SyntaxKind::NODE_STRING 71 + | SyntaxKind::NODE_ATTR_SET 72 + | SyntaxKind::NODE_IDENT 73 + | SyntaxKind::NODE_SELECT => default_expr, 74 + _ => make::parenthesize(&default_expr).node().clone(), 75 + }; 76 + 77 + let replacement = make::or_default(&set, &attr_path, &default_with_parens) 78 + .node() 79 + .clone(); 80 + let message = format!("Consider using `{replacement}` instead of this `if` expression"); 81 + Some( 82 + self.report() 83 + .suggest(at, message, Suggestion::new(at, replacement)), 84 + ) 79 85 } 80 86 }