Wado

Wado Formatter

wado format re-prints a source file in canonical form. This document is the rules it follows, and how those rules are held in place by tests.

One style, by design

The formatter has no configuration. There is no line-width setting, no brace or indent option, no directive that turns it off for a region, and no plan to add one. The only inputs besides the source are the [format] section of wado.toml and the built-in skips below, which decide which files are formatted at all, never how.

A single style is worth more than any option it forgoes. Every Wado file reads the same way, a diff shows what changed rather than who wrote it, layout never reaches code review, and one canonical output is a thing tests can pin exactly.

Contract

Four promises, each covered by a test in Tests.

Running it

wado format FILE prints the result. -w rewrites files in place and --check exits non-zero when a file would change; more than one input requires one of the two. mise run format formats the whole repository, Rust and Markdown included.

**/generated/** and **/build/** are skipped in every package, because nothing there is written by hand. [format] exclude in a wado.toml skips more paths, and [format] include carves any of them back in. wado-compiler excludes tests/**, because those fixtures have hand-authored layouts that are part of the test.

A directory argument is walked from the package that encloses it, so the globs match as authored whichever subdirectory you name. wado format -w wado-compiler/tests formats nothing and reports that directory as empty.

Naming a file bypasses the filters. The golden-fixture scripts rely on that to rewrite excluded fixtures, so never run wado format -w on a fixture file yourself.

Layout

A line is at most 120 columns.

A construct is rendered compact and wrapped only when it does not fit. The budget counts what will follow on the same line, such as the { after an if condition, so a construct never fits by ignoring what comes next.

Four things force the wrapped form whatever the width allows.

An array that does not fit packs as many elements per line as the budget allows, unless it holds a call, a nested container, or a comment. Every other wrapped list is one entry per line with a trailing comma. Declaration bodies, a match with more than one arm, and if / else chains are always multi-line.

Blank lines follow the source: none stays none, one stays one, and a larger gap collapses to two.

What it rewrites

Only what carries no meaning: redundant parentheses, an explicit -> () return type, repeated or missing statement semicolons, an impl block's type parameters (always written out), and a field name's quoting (bare when it is an identifier).

Everything else is kept as written, including the spelling of every literal (hex, octal, digit separators, float form, string and template escapes), &self receivers, compound assignments, comparison chains, struct shorthand, visibility keywords, and any parenthesis that changes how the code parses.

Comments

A comment can sit in any gap between two tokens, and most of those gaps belong to no node of the syntax tree. The rules below hold for all of them.

The rules are chosen so the result is a fixed point. A comment is moved to where the next parse will read it, which is why a second pass agrees with the first.

As a backstop, format compares the comments in its input and its output and refuses to emit a file that lost one. The rules above make that unreachable.

Tests

wado-compiler/tests/format.rs holds them all.

test_format_keeps_a_comment_wedged_in_any_token_gap is the one that makes the comment rules a guarantee rather than an intention. It wedges a line comment and a block comment into every gap between two tokens of every fixture, template interpolations included, and asserts that each variant formats, keeps the comment, re-parses, and is a fixed point. Comment loss is a class of defect rather than a list of sites, so it is enumerated mechanically: a construct that ignores comments is caught here, not by a user whose file stops formatting.

assert_format_preserves_ast is the per-case helper behind the first two promises. It formats the source, compares the parsed trees ignoring positions, and asserts the fixed point. Reach for it in any test that adds a syntax.

The golden tests pair a wado-compiler/tests/format.fixtures/*_dirty.wado input with its expected output under wado-compiler/tests/generated/format.fixtures/. They are where a layout rule is pinned exactly, which is what a single style buys. Add a fixture when a rule is added or changed, then regenerate with mise run update-golden-format-fixtures and read the diff.

test_format_idempotent_all_fixtures and test_no_dropped_comments_in_corpus run the whole fixture and standard-library corpus through the formatter, so a rule that only misbehaves at scale still has somewhere to fail.