diff --git a/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs b/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs index 579a27b60..13330a9e6 100644 --- a/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs +++ b/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs @@ -348,6 +348,8 @@ fn test() { // need getStaticValue // ("const A_NUMBER = 2; const x = foo.length || A_NUMBER", None), ("class A { a(){ if(this.length); while(!this.size || foo);}}", None), + // Use of .size but not in conditional "test" position + ("const totalCount = tests.reduce((count, test) => count + (test.enabled ? test.maxSize : test.size), 0)", None), ]; let fail = vec![ @@ -361,7 +363,10 @@ fn test() { ("const x = foo.length || bar()", None), ("() => foo.length && bar()", None), ("alert(foo.length && bar())", None), + // Use of .size in conditional "test" position + ("let foo = arr.length ? 'non-empty' : 'empty'", None), ]; + let fixes = vec![ ( r"if ( !!!( !foo.length && foo.length == 0 && foo.length < 1 && 0 === foo.length && 0 == foo.length && 1 > foo.length ) || diff --git a/crates/oxc_linter/src/snapshots/explicit_length_check.snap b/crates/oxc_linter/src/snapshots/explicit_length_check.snap index 90ab7ede4..85e3ed668 100644 --- a/crates/oxc_linter/src/snapshots/explicit_length_check.snap +++ b/crates/oxc_linter/src/snapshots/explicit_length_check.snap @@ -64,4 +64,10 @@ expression: explicit_length_check ╰──── help: Replace `.length` with `.length > 0`. + ⚠ eslint-plugin-unicorn(explicit-length-check): Use `.length > 0` when checking length is not zero. + ╭─[explicit_length_check.tsx:1:1] + 1 │ let foo = arr.length ? 'non-empty' : 'empty' + · ────────── + ╰──── + diff --git a/crates/oxc_linter/src/utils/unicorn/boolean.rs b/crates/oxc_linter/src/utils/unicorn/boolean.rs index 8be12be9d..2bba43022 100644 --- a/crates/oxc_linter/src/utils/unicorn/boolean.rs +++ b/crates/oxc_linter/src/utils/unicorn/boolean.rs @@ -1,8 +1,9 @@ use oxc_ast::{ - ast::{CallExpression, Expression}, + ast::{CallExpression, ConditionalExpression, Expression}, AstKind, }; use oxc_semantic::AstNode; +use oxc_span::GetSpan; use oxc_syntax::operator::UnaryOperator; use crate::{ast_util::outermost_paren_parent, LintContext}; @@ -48,7 +49,6 @@ pub fn is_boolean_node<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) if matches!( parent.kind(), AstKind::IfStatement(_) - | AstKind::ConditionalExpression(_) | AstKind::WhileStatement(_) | AstKind::DoWhileStatement(_) | AstKind::ForStatement(_) @@ -56,6 +56,14 @@ pub fn is_boolean_node<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) return true; } + if let AstKind::ConditionalExpression(ConditionalExpression { + test: conditional_test, .. + }) = parent.kind() + { + let expr_span = conditional_test.get_inner_expression().without_parenthesized().span(); + return expr_span == node.kind().span(); + } + if is_logical_expression(parent) { return is_boolean_node(parent, ctx); }