Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/add-check-for-each-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@biomejs/biome": patch
---

Added the `checkForEach` option to the `useIterableCallbackReturn` rule.

When `checkForEach` is `true`, the rule reports when `forEach` callbacks return a value. When `false` (the default), `forEach` callbacks are not checked.

This aligns with ESLint's `array-callback-return` rule behavior where `forEach` checking is opt-in.

**Breaking change:** Previously, `forEach` was always checked. Users who want the previous behavior should set `checkForEach: true` in their configuration.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@ declare_lint_rule! {
/// - `toSorted`
/// — `from` (when called on `Array`)
///
/// A return value is disallowed in the method `forEach`.
/// When `checkForEach` is enabled, a return value is disallowed in the method `forEach`.
///
/// ## Options
///
/// ### checkForEach
///
/// If `true`, also check that callbacks to `forEach` do not return a value.
///
/// Default: `false`
///
/// ## Examples
///
Expand All @@ -57,12 +65,6 @@ declare_lint_rule! {
/// });
/// ```
///
/// ```js,expect_diagnostic
/// [].forEach(() => {
/// return 1; // Should not return a value
/// });
/// ```
///
/// ### Valid
///
/// ```js
Expand All @@ -72,14 +74,11 @@ declare_lint_rule! {
/// ```
///
/// ```js
/// // By default, forEach callbacks may return a value
/// [].forEach(() => {
/// // No return value, which is correct
/// return 1;
/// });
/// ```
///
/// ```js
/// [].forEach(() => void null); // Void return value, which doesn't trigger the rule
/// ```
pub UseIterableCallbackReturn {
version: "2.0.0",
name: "useIterableCallbackReturn",
Expand Down Expand Up @@ -130,6 +129,11 @@ impl Rule for UseIterableCallbackReturn {

let method_config = ITERABLE_METHOD_INFOS.get(member_name.text_trimmed())?;

// Skip forEach checks if checkForEach option is false
if member_name.text_trimmed() == "forEach" && !ctx.options().check_for_each() {
return None;
}

let arg_position = argument_list
.elements()
.position(|arg| arg.node.is_ok() && arg.node.unwrap().syntax().eq(&cfg.node))?;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
[].forEach((a) => {
return a.fn();
});
[].forEach(function(a) {
return a.fn();
});
[].forEach((a) => {
if (a) {
return a.fn();
}
});
[].forEach((a) => {
if (a) {
return;
}
return a.fn();
});
[].forEach((a) => {
if (a) {
return;
}
return a.fn();
});
[].forEach((a) => {
if (a) {
throw new Error();
}
return a.fn();
});
Array.from([], () => {});
Array.from([], function() {});
Array.from([], () => {
Expand Down
Loading