oxc-project/oxc · warning · OxcDiagnostic
Do not call `{description}` multiple times.
Error message
Do not call `{description}` multiple times. What it means
This is the oxlint rule `unicorn/prefer-single-call` (category `pedantic`, supersedes `unicorn/no-array-push-push`). It reports consecutive expression statements calling the same variadic method on the same receiver — `Array#push`/`unshift`, `Element#classList.add`/`remove`, and `importScripts()` — and asks you to merge them into one call, which is more concise and marginally faster.
Source
Thrown at crates/oxc_linter/src/rules/unicorn/prefer_single_call.rs:20
AstKind,
ast::{CallExpression, Expression, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::identifier::is_identifier_part;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
AstNode,
context::LintContext,
fixer::Fix,
rule::{DefaultRuleConfig, Rule},
};
fn prefer_single_call_diagnostic(span: Span, description: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Do not call `{description}` multiple times."))
.with_help("Merge with the previous call.")
.with_label(span)
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct PreferSingleCallConfig {
/// Methods to ignore.
#[serde(default)]
ignore: Vec<String>,
}
#[derive(Debug, Default, Clone, Deserialize)]
pub struct PreferSingleCall(Box<PreferSingleCallConfig>);
declare_oxc_lint!(
/// ### What it does
///View on GitHub (pinned to e1e7af627c)
Solutions
- Merge the calls: `foo.push(1, 2);`, `el.classList.add('a', 'b');`, `importScripts('a.js', 'b.js');` (for `unshift`, reverse the argument order to preserve semantics: `foo.unshift(2, 1);`).
- Run `oxlint --fix` — the rule is auto-fixable and will merge the spans for you.
- Add method names to the rule's `ignore` config if merging hurts readability or a receiver is a proxy with call-count side effects: `{ "rules": { "unicorn/prefer-single-call": ["error", { "ignore": ["importScripts"] }] } }`.
- Disable the rule in `.oxlintrc.json` if your style guide prefers one call per line.
Example fix
// before
foo.push(1);
foo.push(2);
el.classList.add('a');
el.classList.add('b');
// after
foo.push(1, 2);
el.classList.add('a', 'b'); Defensive patterns
Strategy: validation
Validate before calling
// Write variadic calls merged from the start
foo.push(1, 2, 3);
el.classList.add('a', 'b');
// CI: npx oxlint --deny-warn unicorn/prefer-single-call src/ Prevention
- Batch arguments into one variadic call when pushing/adding in sequence.
- Use the `ignore` config for receivers with call-count side effects (proxies, analytics-instrumented objects).
- Note `unshift` argument order reverses when merging — review autofixes on unshift chains.
When it happens
Trigger: Two or more adjacent expression statements in the same statement list (block, program, function body, static block, or switch case) calling e.g. `foo.push(1); foo.push(2);`, `el.classList.add('a'); el.classList.add('b');`, or `importScripts('a.js'); importScripts('b.js');` with no intervening statements on that receiver. The `ignore` config option suppresses specific method names.
Common situations: Build scripts pushing into arrays line-by-line, DOM code adding classes one per line, worker bootstraps loading several scripts with repeated `importScripts`; teams enabling the whole `unicorn` preset during an ESLint-to-oxlint migration and hitting newly strict formatting of consecutive calls.
Related errors
- IIFE with parenthesized arrow function body is considered un
- Useless case in switch statement.
- Do not use useless `undefined`.
- Require `for-in` loops to include an `if` statement
- All `if` blocks contain the same code at the start
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/4d0448c18815e23d.
Report an issue: GitHub.