-
-
Notifications
You must be signed in to change notification settings - Fork 714
fix(lint/suspicious/useIterableCallbackReturn): single-expression void arrow function #7564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(lint/suspicious/useIterableCallbackReturn): single-expression void arrow function #7564
Conversation
🦋 Changeset detectedLatest commit: efc0442 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
i believe an ideal fix should identify the actual return type of the callback, but it would be more complex and #6617 (comment) seemed to discourage that approach. |
CodSpeed Performance ReportMerging #7564 will not alter performanceComparing Summary
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great, thank you. The linting is failing, I also added a couple of nits
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js
Show resolved
Hide resolved
@ematipico updated with requested changes |
strangely, this error repeats many times:
|
Caution Review failedThe pull request is closed. WalkthroughUpdates the nursery lint rule use_iterable_callback_return and its tests. Adds a patch changeset for @biomejs/biome documenting a bug fix. get_function_returns_info no longer treats single-expression arrow bodies as always valued; it now classifies them as value or void by detecting a surrounding unary Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs (1)
279-298
: Also handle parenthesisedvoid
bodies (e.g.() => (void 0)
).Currently only direct unary
void
is detected; wrapping it in parentheses won’t be recognised. Unwrapping parentheses before the check avoids false negatives.Apply this minimal tweak:
if let Some(arrow_expression) = JsArrowFunctionExpression::cast_ref(&cfg.node) && let Ok(AnyJsFunctionBody::AnyJsExpression(expression)) = arrow_expression.body() { - let is_void_expression = expression - .as_js_unary_expression() - .and_then(|unary| unary.is_void().ok()) - .unwrap_or(false); + // Unwrap surrounding parentheses to recognise patterns like `() => (void 0)` + let mut expr = expression; + loop { + if let Some(paren) = expr.as_js_parenthesized_expression() { + match paren.expression() { + Ok(inner) => expr = inner, + Err(_) => break, + } + } else { + break; + } + } + + let is_void_expression = expr + .as_js_unary_expression() + .and_then(|unary| unary.is_void().ok()) + .unwrap_or(false); - if is_void_expression { - function_returns_info - .returns_without_value - .push(expression.range()) - } else { - function_returns_info - .returns_with_value - .push(expression.range()) - } + if is_void_expression { + function_returns_info + .returns_without_value + .push(expr.range()) + } else { + function_returns_info + .returns_with_value + .push(expr.range()) + } return function_returns_info; }crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js (1)
25-26
: LGTM; maybe add a parens variant too.To guard regressions, consider adding:
[].forEach(() => (void null));
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js.snap
is excluded by!**/*.snap
and included by**
📒 Files selected for processing (4)
.changeset/vast-waves-write.md
(1 hunks)crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
(2 hunks)crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js
(14 hunks)crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format all Rust source files before committing (just f)
Files:
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
**/tests/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place test files under a tests/ directory in each crate
Files:
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/valid.js
crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js
.changeset/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
.changeset/*.md
: In changeset files, only use #### or ##### headers; avoid other header levels
Changeset descriptions should use past tense for what you did (e.g., "Added...")
Describe current Biome behavior in present tense within changesets (e.g., "Biome now supports...")
For bug fixes in changesets, start with a link to the issue (e.g., "Fixed #1234: ...")
When referencing rules or assists in changesets, include links to their documentation pages
Include a minimal code block in the changeset when applicable to demonstrate the change
End every sentence in the changeset description with a period
Files:
.changeset/vast-waves-write.md
🧠 Learnings (1)
📚 Learning: 2025-09-07T17:35:00.517Z
Learnt from: CR
PR: biomejs/biome#0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-09-07T17:35:00.517Z
Learning: Applies to .changeset/*.md : Describe current Biome behavior in present tense within changesets (e.g., "Biome now supports...")
Applied to files:
.changeset/vast-waves-write.md
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs (1)
crates/biome_rowan/src/ast/mod.rs (1)
cast_ref
(142-151)
🔇 Additional comments (2)
crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs (1)
79-82
: Nice doc touch; earlier feedback addressed.The added example for a single‑expression
void
arrow callback clarifies intent and matches the rule’s behaviour.crates/biome_js_analyze/tests/specs/suspicious/useIterableCallbackReturn/invalid.js (1)
38-39
: Great coverage; add parens/void 0
variants for completeness.Nice job adding
void call
forms—addresses earlier feedback. To harden the suite, sprinkle a couple of cases like() => (void 0)
and() => (void a.fn())
across one or two methods (e.g.map
,every
).Also applies to: 87-88, 97-98, 107-108, 117-118, 127-128, 137-138, 147-148, 157-158, 167-168, 177-178, 187-188, 197-198, 228-229
i think this is not a good idea
as i said above, an ideal fix should use real type information to identify the return type of the callback. i consider this to be a minimal solution, which satisfies the most common use-case, and which provides an easy technique for developers to satisfy the demands of the rule without applying braces to every arrow callback. @coderabbitai resolve |
@turbocrime Your reasoning is solid. You're absolutely right that handling parenthesized void expressions would create unnecessary complexity:
Your approach of detecting direct ✅ Actions performedComments resolved. |
Summary
the rule
useIterableCallbackReturn
now correctly handles arrow functions with a single-expression void bodylint/suspicious/useIterableCallbackReturn
should not reject a void return when callback return is prohibited #7559lint/nursery/useIterableCallbackReturn
incorrectly flags functions that returnvoid
as returning a value #6617Test Plan
tests and snapshots updated
Docs
example added to macro comment