Skip to content

[eradicate] Fix ERA001/RUF100 conflict when noqa is on commented-out code#25414

Merged
ntBre merged 3 commits into
astral-sh:mainfrom
Redslayer112:main
May 28, 2026
Merged

[eradicate] Fix ERA001/RUF100 conflict when noqa is on commented-out code#25414
ntBre merged 3 commits into
astral-sh:mainfrom
Redslayer112:main

Conversation

@Redslayer112
Copy link
Copy Markdown
Contributor

Summary

Fixes #25386.

For commented-out code with a trailing # noqa: ERA001, Ruff could report both
ERA001 on one line and RUF100 (unused ERA001) on the next — which is inconsistent.

ERA001 uses comment_contains_code() to decide if a comment is code. That function
was analyzing the full comment body, including trailing # noqa: ERA001. The allowlist
treats noqa as non-code, so lines like # ) # noqa: ERA001 were skipped by ERA001
while a nearby line without noqa still triggered ERA001. That made the noqa
look unused to RUF100.

The fix strips a trailing inline # noqa... before ERA001’s code detection, so the
comment is evaluated on its code portion only (e.g. )). Suppression and detection
then agree: noqa: ERA001 is used when it suppresses a real ERA001 match.

the repro now shows ERA001 diagnostics without incorrectly flagging the paired noqa: ERA001 as unused.

Test Plan

@astral-sh-bot astral-sh-bot Bot requested a review from ntBre May 27, 2026 11:51
@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented May 27, 2026

Thanks for looking into this. Could you please take a look at our AI Policy and confirm that you've followed it? I get the strong impression from the PR summary that this was written by an LLM.

I'm also a bit surprised by this approach. I see that you found existing tests in RUF100_5.py that test behavior similar to that reported in the issue. Is it possible to extend the approach used by those other noqa positions instead of adding a new strip_trailing_noqa function? It looks like this is done via POSITIVE_CASES, where the dictionary case allows trailing comments while the brackets case (and multiline assignment) does not:

// Partial dictionary
r#"^['"]\w+['"]\s*:.+[,{]\s*(#.*)?$"#,
// Multiline assignment
r"^(?:[(\[]\s*)?(?:\w+\s*,\s*)*\w+\s*([)\]]\s*)?=.*[(\[{]$",
// Brackets,
r"^[()\[\]{}\s]+$",

Looks like this is the PR that added that for dictionaries: #6822.

@ntBre ntBre added bug Something isn't working rule Implementing or modifying a lint rule labels May 27, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented May 27, 2026

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+2 -0 violations, +0 -0 fixes in 1 projects; 55 projects unchanged)

zulip/zulip (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --no-preview --select ALL

+ zproject/prod_settings_template.py:297:1: ERA001 Found commented-out code
+ zproject/prod_settings_template.py:298:1: ERA001 Found commented-out code

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
ERA001 2 2 0 0 0

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+2 -0 violations, +0 -0 fixes in 1 projects; 55 projects unchanged)

zulip/zulip (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview --select ALL

+ zproject/prod_settings_template.py:297:1: ERA001 Found commented-out code
+ zproject/prod_settings_template.py:298:1: ERA001 Found commented-out code

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
ERA001 2 2 0 0 0

@Redslayer112
Copy link
Copy Markdown
Contributor Author

Thanks for the feedback, yes I followed the AI policy. I confirm the generated code is generated by an LLM, me guiding it.

Changed the implementation to match the existing ERA001 pattern instead of using a dedicated strip_trailing_noqa helper.
Specifically, I removed strip_trailing_noqa and extended POSITIVE_CASES so the multiline-assignment and bracket patterns accept trailing inline comments, similar to the dictionary handling approach from #6822.

Reran:

@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented May 27, 2026

Thank you for looking at the AI policy. However, this is the section I was more curious about than the code itself:

AI should not be used to generate comments when communicating with maintainers. We expect comments on our projects to be written by humans. We may hide any comments that we believe are AI generated.

If you are opening an issue, we expect you to describe the problem in your own words.

If you are opening a pull request, we expect you to be able to explain the proposed changes in your own words. This includes the pull request body and responses to questions. Do not copy responses from the AI when replying to questions from maintainers.

My impression was that the PR summary, especially this list of overly-specific test commands in the test plan, was written by an LLM, which is against our policy. The fact that you've copied this test plan again into your latest comment very strongly suggests that you're violating our AI policy.

The code changes look reasonable here, so I'm okay with keeping the PR open, but please refrain from pasting LLM output into comments. The PR summary should also be updated to reflect the current state of the code rather than the first implementation.

Comment thread crates/ruff_linter/src/rules/eradicate/detection.rs
Comment thread crates/ruff_linter/src/rules/eradicate/detection.rs Outdated
@Redslayer112
Copy link
Copy Markdown
Contributor Author

Thanks for clarification, Im new to OSS so it made sense in my head to add the test cases which passed. apologies that it looked LLM generated comment. I confirm that I personally wrote the above comment. I updated the implementation as per your feedback of the regex style and test coverage...
thank you again for your guidance

@ntBre ntBre changed the title [eradicate] Fix ERA001/RUF100 conflict when noqa is on commented-out code [eradicate] Fix ERA001/RUF100 conflict when noqa is on commented-out code May 28, 2026
Copy link
Copy Markdown
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Nice work, thank you!

@ntBre ntBre merged commit b427926 into astral-sh:main May 28, 2026
45 checks passed
anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request May 28, 2026
…ted-out code (astral-sh#25414)

## Summary

Fixes astral-sh#25386.

For commented-out code with a trailing `# noqa: ERA001`, Ruff could
report both
`ERA001` on one line and `RUF100` (unused `ERA001`) on the next — which
is inconsistent.

`ERA001` uses `comment_contains_code()` to decide if a comment is code.
That function
was analyzing the full comment body, including trailing `# noqa:
ERA001`. The allowlist
treats `noqa` as non-code, so lines like `# ) # noqa: ERA001` were
skipped by `ERA001`
while a nearby line without `noqa` still triggered `ERA001`. That made
the `noqa`
look unused to `RUF100`.

The fix strips a trailing inline `# noqa...` before ERA001’s code
detection, so the
comment is evaluated on its code portion only (e.g. `)`). Suppression
and detection
then agree: `noqa: ERA001` is used when it suppresses a real `ERA001`
match.

the repro now shows ERA001 diagnostics without incorrectly flagging the
paired noqa: ERA001 as unused.

## Test Plan

- Added unit tests in `detection.rs` for `# ) # noqa: ERA001` and `# \t(
# noqa: ERA001`
- Extended `RUF100_5.py` with regression cases from astral-sh#25386
- Ran `cargo test -p ruff_linter ruf100_5` (snapshot updated)
- Ran `cargo test -p ruff_linter comment_contains_code_with_multiline`
- Ran `uvx prek run --files` on the three changed files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schrödinger's comment: it is both commented-out code and a comment that is not code (ERA001 vs RUF100)

2 participants