Skip to content

feat: check sequence expressions in for-direction#20701

Merged
fasttime merged 9 commits into
eslint:mainfrom
Kuldeep2822k:fix/for-direction-sequence-expression
May 10, 2026
Merged

feat: check sequence expressions in for-direction#20701
fasttime merged 9 commits into
eslint:mainfrom
Kuldeep2822k:fix/for-direction-sequence-expression

Conversation

@Kuldeep2822k

@Kuldeep2822k Kuldeep2822k commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Prerequisites checklist

AI acknowledgment

  • I did not use AI to generate this PR.
  • (If the above is not checked) I have reviewed the AI-generated content before submitting.

What is the purpose of this pull request? (put an "X" next to an item)

  • Documentation update
  • Bug fix (template)
  • New rule (template)
  • Changes an existing rule (template)
  • Add autofix to a rule
  • Add a CLI option
  • Add something to the core
  • Other, please explain:

Tell us about your environment (npx eslint --env-info):

  • Node version: v22.x
  • npm version: 10.x
  • Local ESLint version: latest (main)
  • Global ESLint version: N/A
  • Operating System: Windows 11

What parser are you using (place an "X" next to just one item)?

  • Default (Espree)
  • @typescript-eslint/parser
  • @babel/eslint-parser
  • vue-eslint-parser
  • @angular-eslint/template-parser
  • Other

Please show your full configuration:

Configuration
export default [
  {
    rules: {
      "for-direction": "error"
    }
  }
];

What did you do? Please include the actual source code causing the issue.

/* eslint for-direction: "error" */
for (let i = 10; i < 20; i--, j++) {}

The for-direction rule was silently ignoring the update clause when it was a SequenceExpression (comma operator). It returned 0 (no direction detected) for the entire update, causing a false negative — no error was reported even though one of the comma-separated expressions moved the counter in the wrong direction.

What did you expect to happen?

error  The update clause in this loop moves the variable in the wrong direction.  for-direction

What actually happened? Please include the actual, raw output from ESLint.

No output. The rule passed silently without reporting an error.


What changes did you make? (Give an overview)

  • Added a getDirectionFromExpression helper that dispatches to getUpdateDirection or getAssignmentDirection based on expression type.
  • Added a getModifyingExpressions helper that recursively collects all sub-expressions in a SequenceExpression that modify the counter variable (i.e., UpdateExpression or AssignmentExpression targeting the counter).
  • When node.update is a SequenceExpression, the rule collects all sub-expressions that modify the counter. If exactly one sub-expression modifies the counter and it moves in the wrong direction, the loop is reported. If multiple sub-expressions modify the counter, the rule skips reporting because the net direction is ambiguous.
  • Non-sequence updates continue through the existing single-expression path, preserving all prior behavior.

Is there anything you'd like reviewers to focus on?

The counterExpressions.length === 1 guard — the rule only reports when exactly one sub-expression in the sequence modifies the counter. When multiple sub-expressions modify the counter (e.g., (i--, i += 2)), the net direction is ambiguous, so the rule intentionally skips those cases.

@Kuldeep2822k
Kuldeep2822k requested a review from a team as a code owner March 30, 2026 18:19
@github-project-automation github-project-automation Bot moved this to Needs Triage in Triage Mar 30, 2026
@eslint-github-bot eslint-github-bot Bot added the bug ESLint is working incorrectly label Mar 30, 2026
@netlify

netlify Bot commented Mar 30, 2026

Copy link
Copy Markdown

Deploy Preview for docs-eslint canceled.

Name Link
🔨 Latest commit c6a5136
🔍 Latest deploy log https://app.netlify.com/projects/docs-eslint/deploys/69f8d7e37df76000088e5ce4

@github-actions github-actions Bot added the rule Relates to ESLint's core rules label Mar 30, 2026
@Kuldeep2822k
Kuldeep2822k force-pushed the fix/for-direction-sequence-expression branch from c42027a to 6c766be Compare March 30, 2026 18:31
@nzakas nzakas changed the title fix: detect wrong direction in or-direction when update uses Sequenc… fix: detect wrong direction in for-direction Apr 1, 2026
@nzakas

nzakas commented Apr 1, 2026

Copy link
Copy Markdown
Member

Thanks for the submission. Can you please update the description with the same fields we have in our bug report template? Thanks.

@nzakas nzakas moved this from Needs Triage to Triaging in Triage Apr 1, 2026
@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

Thanks for the submission. Can you please update the description with the same fields we have in our bug report template? Thanks.

Thanks for mentioning the template i have updated the pr description to include the templete please review it

@lumirlumir

Copy link
Copy Markdown
Member

I believe this fix addresses #20410, but it’s assigned to someone else.

And please double-check the PR template. It seems a malformed code block is still breaking the template.

@Kuldeep2822k

Kuldeep2822k commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

I believe this fix addresses #20410, but it’s assigned to someone else.

And please double-check the PR template. It seems a malformed code block is still breaking the template.

To clarify — PR #20701 addresses SequenceExpression support in the update clause, not the statically-false condition case described in the issue.

@amareshsm

amareshsm commented Apr 6, 2026

Copy link
Copy Markdown
Member

I believe this fix addresses #20410, but it’s assigned to someone else.

And please double-check the PR template. It seems a malformed code block is still breaking the template.

This pr is not related to #20410

This PR addresses a completely different scenario where the update clause is a SequenceExpression. Currently, we handle:

  1. UpdateExpressioni++, i--
  2. AssignmentExpressioni += 1, i -= 1

Please create a separate issue to track this case - SequenceExpression. Based on the team’s decision, you may proceed with the implementation.

There can be multiple cases
case 1: Mixed UpdateExpression + AssignmentExpression

case 2: Three values separated by comma

case 3: for(var i = 10; i < 20; i--, i++) {} - different directions

Scenario 1:
i-- → i = i - 1 and i++ → i = i + 1 the net effect No change to i

Condition: i < 20 → always true result in infinite loop.

Scenario 2:
i-- → i = i - 1 and i = i + 2 → increases i by 2 the effect i = i + 1

Condition: i < 20 → runs from 10 to 19 and stops when i becomes 20 Normal loop (not infinite)

Ideally if the counter appears more than once in the sequence, treat direction as unknown and we should skip i guess.

@SwetaTanwar SwetaTanwar added the accepted There is consensus among the team that this change meets the criteria for inclusion label Apr 13, 2026
@SwetaTanwar SwetaTanwar moved this from Triaging to Implementing in Triage Apr 13, 2026
Comment thread lib/rules/for-direction.js Outdated
Comment on lines +166 to +172
? update.expressions.some(
expr =>
getDirectionFromExpression(
expr,
counter,
) === wrongDirection,
)

@SwetaTanwar SwetaTanwar Apr 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kuldeep2822k The issue has been accepted, feel free to continue your work on this PR.

If the counter appears in more than one expression within the sequence, treat direction as unknown and skip. Only report when exactly one expression in the sequence modifies the counter in the wrong direction.

We need to make sure of this proposed behavior and add the corresponding test case.

When a SequenceExpression update has the counter modified in more than one sub-expression, treat direction as unknown and skip. Only report when exactly one expression in the sequence modifies the counter in the wrong direction.

Refs eslint#20726
@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

Did the changes as described in the issue

@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

Lines 164–182 in lib/rules/for-direction.js:

if (update.type === "SequenceExpression") {
    const counterExpressions = update.expressions.filter(
        expr => getDirectionFromExpression(expr, counter) !== 0,
    );

    if (
        counterExpressions.length === 1 &&
        getDirectionFromExpression(counterExpressions[0], counter) === wrongDirection
    ) {
        report(node);
    }
}

This uses .filter() to collect all expressions that modify the counter, then only reports if exactly one expression modifies the counter and it moves in the wrong direction. If the counter appears more than once (e.g., i--, i++ or i--, i += 2), counterExpressions.length will be > 1, so the rule treats the direction as unknown and skips — exactly as proposed in #20726.

The corresponding test cases are already in place:

Valid (counter modified multiple times → direction unknown, skip):

"for(var i = 10; i < 20; (i--, i++)){}"
"for(var i = 10; i < 20; (i--, i += 2)){}"
"for(var i = 0; i < 10; (i++, i--)){}"
"for(var i = 0; i < 10; (i-=1, i+=2)){}"

Invalid (exactly one expression moves counter in wrong direction):

"for(var i = 0; i < 10; (i--, j++)){}"
"for(var i = 10; i > 0; (i++, j--)){}"
"for(var i = 0; i < 10; (i-=1, j++)){}"
// ...and more

Let me know if any additional test cases or changes are needed!

Copilot AI review requested due to automatic review settings April 19, 2026 16:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes for-direction false negatives when the for loop update clause is a SequenceExpression (comma operator), ensuring the rule evaluates counter-direction changes inside comma-separated updates.

Changes:

  • Add getDirectionFromExpression() helper to unify direction detection for update vs assignment expressions.
  • Extend for-direction to handle SequenceExpression updates by analyzing its sub-expressions.
  • Add RuleTester coverage for SequenceExpression updates in both valid and invalid cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
lib/rules/for-direction.js Adds SequenceExpression handling and a shared direction helper to detect wrong-direction counter updates inside comma operator updates.
tests/lib/rules/for-direction.js Adds new valid/invalid cases covering comma operator updates in for loop update clauses.

Comment thread lib/rules/for-direction.js Outdated
Comment thread lib/rules/for-direction.js Outdated
Comment thread tests/lib/rules/for-direction.js Outdated
Comment thread tests/lib/rules/for-direction.js
@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

Before procceding with fixing all found issue i want a member confirmation to proceed

@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

I think this copilot review was trigger by me by mistake

@mdjermanovic mdjermanovic changed the title fix: detect wrong direction in for-direction feat: check sequence expressions in for-direction Apr 25, 2026
@eslint-github-bot eslint-github-bot Bot added the feature This change adds a new feature to ESLint label Apr 25, 2026
@Kuldeep2822k

Copy link
Copy Markdown
Contributor Author

In the SequenceExpression path, counterExpressions filters on getDirectionFromExpression(...) !== 0. For AssignmentExpression on the counter where the RHS isn't statically known (e.g. i += STEP_SIZE), getAssignmentDirection returns 0, so that expression is excluded even though it does modify the counter. This can lead to false reports when the sequence contains one known-direction update plus another counter update with unknown direction (overall direction should be treated as unknown and skipped). Consider separating (1) “does this expression modify the counter?” from (2) “what is its direction?”, and treat any additional/unknown counter modifications (including nested SequenceExpressions) as making the direction indeterminate.

Applied this change as requested by @mdjermanovic.

I've updated the implementation to introduce a getMutatingExpressions helper that safely extracts all expressions modifying the counter. This successfully separates the check for "does it modify the counter?" from "what is its direction?". It now perfectly handles indeterminate assignments (like i += STEP_SIZE) as well as flattened nested SequenceExpressions.

I also added tests to verify these edge cases are properly skipped without throwing false positive reports.

Comment thread lib/rules/for-direction.js Outdated
@Kuldeep2822k
Kuldeep2822k requested a review from mdjermanovic May 4, 2026 17:51

@mdjermanovic mdjermanovic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! Leaving open for a second review.

@mdjermanovic mdjermanovic moved this from Implementing to Second Review Needed in Triage May 8, 2026

@fasttime fasttime left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@fasttime
fasttime merged commit 1a45ec5 into eslint:main May 10, 2026
43 checks passed
@github-project-automation github-project-automation Bot moved this from Second Review Needed to Complete in Triage May 10, 2026
@Kuldeep2822k
Kuldeep2822k deleted the fix/for-direction-sequence-expression branch May 14, 2026 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted There is consensus among the team that this change meets the criteria for inclusion bug ESLint is working incorrectly contributor pool feature This change adds a new feature to ESLint rule Relates to ESLint's core rules

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

Bug: for-direction rule doesn't detect wrong direction when update clause uses SequenceExpression (comma operator)

8 participants