@@ -22,6 +22,9 @@ predicate inVoidContext(Expr e) {
2222 )
2323 )
2424 or
25+ // propagate void context through parenthesized expressions
26+ inVoidContext ( e .getParent ( ) .( ParExpr ) )
27+ or
2528 exists ( SeqExpr seq , int i , int n |
2629 e = seq .getOperand ( i ) and
2730 n = seq .getNumOperands ( )
@@ -129,6 +132,19 @@ predicate noSideEffects(Expr e) {
129132 )
130133}
131134
135+ /**
136+ * Holds if `e` is a compound expression that may contain sub-expressions with side effects.
137+ * We should not flag these directly as useless since we want to flag only the innermost
138+ * expressions that actually have no effect.
139+ */
140+ predicate isCompoundExpression ( Expr e ) {
141+ e instanceof LogicalBinaryExpr
142+ or
143+ e instanceof SeqExpr
144+ or
145+ e instanceof ParExpr
146+ }
147+
132148/**
133149 * Holds if the expression `e` should be reported as having no effect.
134150 */
@@ -145,6 +161,7 @@ predicate hasNoEffect(Expr e) {
145161 not isDeclaration ( e ) and
146162 // exclude DOM properties, which sometimes have magical auto-update properties
147163 not isDomProperty ( e .( PropAccess ) .getPropertyName ( ) ) and
164+ not isCompoundExpression ( e ) and
148165 // exclude xUnit.js annotations
149166 not e instanceof XUnitAnnotation and
150167 // exclude common patterns that are most likely intentional
@@ -157,7 +174,17 @@ predicate hasNoEffect(Expr e) {
157174 not exists ( fe .getName ( ) )
158175 ) and
159176 // exclude block-level flow type annotations. For example: `(name: empty)`.
160- not e .( ParExpr ) .getExpression ( ) .getLastToken ( ) .getNextToken ( ) .getValue ( ) = ":" and
177+ not exists ( ParExpr parent |
178+ e .getParent ( ) = parent and
179+ e .getLastToken ( ) .getNextToken ( ) .getValue ( ) = ":"
180+ ) and
181+ // exclude expressions that are part of a conditional expression
182+ not exists ( ConditionalExpr cond | e = cond .getABranch ( ) |
183+ e instanceof NullLiteral or
184+ e .( GlobalVarAccess ) .getName ( ) = "undefined" or
185+ e .( NumberLiteral ) .getIntValue ( ) = 0 or
186+ e instanceof VoidExpr
187+ ) and
161188 // exclude the first statement of a try block
162189 not e = any ( TryStmt stmt ) .getBody ( ) .getStmt ( 0 ) .( ExprStmt ) .getExpr ( ) and
163190 // exclude expressions that are alone in a file, and file doesn't contain a function.
0 commit comments