diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs b/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs index 5280db6b79a13..82686754b9d52 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs @@ -197,6 +197,13 @@ fn is_read(current_node_id: NodeId, semantic: &Semantic) -> bool { return true; } } + (AstKind::PrivateFieldExpression(_), AstKind::LogicalExpression(logical_expr)) => { + // Reading the left side of a logical expression can affect control flow + // (e.g. `this.#flag && sideEffect()`), even when used as a statement. + if logical_expr.left.span().contains_inclusive(curr.span()) { + return true; + } + } _ => { return false; } @@ -495,6 +502,7 @@ fn test() { r"class Foo { #x; method(val) { switch(val) { case (a ? this.#x : b): break; } } }", r"class Foo { #x; method() { throw a ? this.#x : new Error(); } }", r"class Foo { #x; method() { while (a ? this.#x : b) {} } }", + r"class Bug { #flag = false; foo() { this.#flag && console.log('spam'); } }", r"class Foo { #a; #b; #c; method() { return this.#a ? this.#b : this.#c; } }", // Issue #15548: Private member used in logical expression on RHS of assignment r"class ExampleFoo { #foo = 0; foo(foo) { foo = foo ?? this.#foo; return foo; } }",