feat(rome_js_analyze): consider unary expressions in `useSimplifiedLogicExpression`
MODIFY
crates/rome_js_analyze/src/analyzers/correctness/use_simplified_logic_expression.rs
crates/rome_js_analyze/src/analyzers/correctness/use_simplified_logic_expression.rs
@@ -2,11 +2,12 @@ use rome_analyze::{context::RuleContext, declare_rule, ActionCategory, Ast, Rule
use rome_console::markup;
use rome_diagnostics::Applicability;
use rome_js_factory::make;
+use rome_js_syntax::JsUnaryOperator::LogicalNot;
use rome_js_syntax::{
JsAnyExpression, JsAnyLiteralExpression, JsBooleanLiteralExpression, JsLogicalExpression,
JsUnaryExpression, JsUnaryOperator, T,
};
-use rome_rowan::{AstNode, AstNodeExt, BatchMutationExt};
+use rome_rowan::{declare_node_union, AstNode, AstNodeExt, BatchMutationExt};
use crate::JsRuleAction;
@@ -37,6 +38,11 @@ declare_rule! {
/// const boolExpr2 = false;
/// const r4 = !boolExpr1 || !boolExpr2;
/// ```
+ ///
+ /// ```js,expect_diagnostic
+ /// const boolExp2 = true;
+ /// const r2 = !!boolExp2;
+ /// ```
/// ### Valid
/// ```js
/// const boolExpr3 = true;
@@ -44,7 +50,6 @@ declare_rule! {
/// const r5 = !(boolExpr1 && boolExpr2);
/// const boolExpr5 = true;
/// const boolExpr6 = false;
- /// const r6 = !!boolExpr1 || !!boolExpr2;
/// ```
///
pub(crate) UseSimplifiedLogicExpression {
@@ -54,14 +59,20 @@ declare_rule! {
}
}
+declare_node_union! {
+ pub(crate) AnyLogicalLikeExpression = JsLogicalExpression | JsUnaryExpression
+}
+
impl Rule for UseSimplifiedLogicExpression {
- type Query = Ast<JsLogicalExpression>;
+ type Query = Ast<AnyLogicalLikeExpression>;
/// First element of tuple is if the expression is simplified by [De Morgan's Law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) rule, the second element is the expression to replace.
type State = (bool, JsAnyExpression);
type Signals = Option<Self::State>;
fn run(ctx: &RuleContext<Self>) -> Option<Self::State> {
let node = ctx.query();
+ match node {
+ AnyLogicalLikeExpression::JsLogicalExpression(node) => {
let left = node.left().ok()?;
let right = node.right().ok()?;
match node.operator().ok()? {
@@ -80,7 +91,8 @@ impl Rule for UseSimplifiedLogicExpression {
JsAnyLiteralExpression::JsBooleanLiteralExpression(literal),
) = left
{
- return simplify_or_expression(literal, right).map(|expr| (false, expr));
+ return simplify_or_expression(literal, right)
+ .map(|expr| (false, expr));
}
if let JsAnyExpression::JsAnyLiteralExpression(
@@ -100,14 +112,16 @@ impl Rule for UseSimplifiedLogicExpression {
JsAnyLiteralExpression::JsBooleanLiteralExpression(literal),
) = left
{
- return simplify_and_expression(literal, right).map(|expr| (false, expr));
+ return simplify_and_expression(literal, right)
+ .map(|expr| (false, expr));
}
if let JsAnyExpression::JsAnyLiteralExpression(
JsAnyLiteralExpression::JsBooleanLiteralExpression(literal),
) = right
{
- return simplify_and_expression(literal, left).map(|expr| (false, expr));
+ return simplify_and_expression(literal, left)
+ .map(|expr| (false, expr));
}
if could_apply_de_morgan(node).unwrap_or(false) {
@@ -117,6 +131,19 @@ impl Rule for UseSimplifiedLogicExpression {
}
_ => return None,
}
+ }
+ AnyLogicalLikeExpression::JsUnaryExpression(unary_expression) => {
+ if unary_expression.operator().ok()? == LogicalNot {
+ let nested_unary = unary_expression.argument().ok()?;
+ let nested_unary = nested_unary.as_js_unary_expression()?;
+ if nested_unary.operator().ok()? == LogicalNot {
+ let expression = nested_unary.argument().ok()?;
+ return Some((false, expression));
+ }
+ }
+ }
+ }
+
None
}
@@ -137,10 +164,19 @@ impl Rule for UseSimplifiedLogicExpression {
let mut mutation = ctx.root().begin();
let (is_simplified_by_de_morgan, expr) = state;
+ match node {
+ AnyLogicalLikeExpression::JsLogicalExpression(node) => {
mutation.replace_node(
JsAnyExpression::JsLogicalExpression(node.clone()),
expr.clone(),
);
+ }
+ AnyLogicalLikeExpression::JsUnaryExpression(unary) => mutation.replace_element(
+ unary.clone().into_syntax().into(),
+ expr.clone().into_syntax().into(),
+ ),
+ }
+
let message = if *is_simplified_by_de_morgan {
"Reduce the complexity of the logical expression."
} else {

MODIFY
crates/rome_js_analyze/tests/specs/correctness/useSimplifiedLogicExpression.js
crates/rome_js_analyze/tests/specs/correctness/useSimplifiedLogicExpression.js
@@ -15,3 +15,4 @@ const r3 = null ?? nonNullExp;
const boolExpr1 = true;
const boolExpr2 = false;
const r4 = !boolExpr1 || !boolExpr2;
+!!x

feat(rome_js_analyze): consider unary expressions in `useSimplifiedLogicExpression` (#3340)