Skip to content

formatter: sequence expression in arrow function body collapses onto one line (differs from Prettier) #21171

@jsmecham

Description

@jsmecham

Input

const requestedReports = reportQueue.reduce(
  (obj, pcpReport) => (
    (obj[pcpReport.participant.id] = pcpReport.selectedReports),
    obj
  ),
  {}
);

Config

{
  "arrowParens": "avoid",
  "trailingComma": "es5",
  "printWidth": 80
}

Oxfmt output

const requestedReports = reportQueue.reduce(
  (obj, pcpReport) => (
    (obj[pcpReport.participant.id] = pcpReport.selectedReports), obj
  ),
  {}
);

Oxfmt playground link

https://playground.oxc.rs/?t=formatter&formatterPanels=output,prettier&code=const%20requestedReports%20%3D%20reportQueue.reduce(%0A%20%20(obj%2C%20pcpReport)%20%3D%3E%20(%0A%20%20%20%20(obj%5BpcpReport.participant.id%5D%20%3D%20pcpReport.selectedReports)%2C%0A%20%20%20%20obj%0A%20%20)%2C%0A%20%20%7B%7D%0A)%3B

(Note: set arrowParens to avoid in the playground's Configure Options panel to reproduce)

Prettier output

const requestedReports = reportQueue.reduce(
  (obj, pcpReport) => (
    (obj[pcpReport.participant.id] = pcpReport.selectedReports),
    obj
  ),
  {}
);

Additional notes

When a parenthesized sequence expression (comma operator) is used as an arrow function body, oxfmt collapses the expressions onto a single line even when the result would exceed printWidth. Prettier keeps each expression on its own line in that case.

The collapsed form (obj[pcpReport.participant.id] = pcpReport.selectedReports), obj is 67 characters, which together with the 4-space indent and surrounding parens puts the line at 73 characters — within printWidth: 80. However, Prettier still keeps the expressions on separate lines here, preserving the multi-line structure of the original arrow function body.

This pattern commonly appears in Array.prototype.reduce callbacks that use the comma operator to mutate an accumulator and return it. The same issue occurs when the first expression is a conditional:

sections?.reduce<PickedSections<P>>(
  (acc, { key, ...section }) => (
    isKey(key) ? (acc[key] = { key, ...section }) : undefined,
    acc
  ),
  {}
);

oxfmt collapses this to:

sections?.reduce<PickedSections<P>>(
  (acc, { key, ...section }) => (
    isKey(key) ? (acc[key] = { key, ...section }) : undefined, acc
  ),
  {}
);

Related prior work on sequence expression formatting: #18972

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions