Skip to content

Formatter Bug: Silently Drops Trailing Tokens After Record Builder #9047

@lukewilliamboswell

Description

@lukewilliamboswell

Summary

When formatting code with an unmatched closing parenthesis after a record builder expression, the formatter silently drops the unmatched ) and any subsequent tokens without reporting an error. This can result in data loss when formatting files.

Minimal Reproduction

{x: 5, y: 6}.Foo).bar()

Expected Behavior

The formatter should report a parse error about the unmatched ) token and preserve the original source, or at minimum warn the user that tokens are being dropped.

Actual Behavior

The formatter outputs:

{ x: 5, y: 6 }.Foo

The ).bar() portion is silently dropped with no error or warning.

Analysis

Looking at the parse tree output:

(e-record-builder
	(mapper (e-tag (raw "Foo")))
	(field (field "x")
		(e-int (raw "5")))
	(field (field "y")
		(e-int (raw "6"))))

The parser only parses up to .Foo and stops. The tokens after (CloseRound, NoSpaceDotLowerIdent, etc.) are silently ignored.

Impact

This bug can cause silent data loss when:

  1. Users accidentally introduce unmatched parentheses while editing
  2. Running roc fmt on a file would permanently delete code
  3. CI/CD pipelines with format checks could pass while dropping code

Snapshot Test

A minimal reproduction is available here unmatched_close_paren_multifield.md

Metadata

Metadata

Assignees

Labels

formattingRelates to the roc formatter

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions