Documentation

whitehall why

Explain what the compiler decided about a file, and why.

Usage

whitehall why <file>[:line | #name] [--json]
whitehall why src/routes/feed/+screen.wh            # every decision in the file
whitehall why src/routes/feed/+screen.wh:12         # what is declared on line 12
whitehall why src/routes/feed/+screen.wh#shows      # one name
whitehall why src/routes/feed/+screen.wh --json     # for editors and tooling

Whitehall deduces a great deal. Where a $state is kept is decided from its type and the file it is in. A file under src/routes/ is a route, registered nowhere. $permission("camera") is the manifest entry. Each of those deletes a chore, and also deletes the line you would have read to find out what happened. why prints it back.

src/routes/button/+screen.wh:7
  pressCount — state, in `rememberSaveable`

  because  declared `$state`
  because  its type is one a `Bundle` holds, so it survives rotation
  because  read in 1 place

  becomes  var pressCount by rememberSaveable { mutableStateOf(0) }

  see      docs/LANGUAGE-REFERENCE.md#state

Each receipt is a subject, a verdict, the reasons (because), what it turns into (becomes), and where to read more.

What it explains

SubjectThe receipt says
the file's rolescreen, layout, component, and the route a screen serves — from the path, [param] folders and any layout override
where the file's $state is keptthe composition, rememberSaveable, or a ViewModel, and the one reason: a loader, $screen.params, a type a Bundle cannot hold, or none of those
each $state, $derived, plain var and valthe declaration, its type, whether anything assigns to it, how often and where it is read
each $effectwhat it becomes
each function and classsuspend and where it runs; a class's $state fields and who holds it
each lifecycle hookwhat it becomes, and what it promises
$permission(...)the <uses-permission> entries it derived
any linethe Kotlin it became, through the source map

Token classes

A color class that names a theme token — bg-primary, text-muted-foreground — gets a receipt saying which stylesheet line set the token, in the light scheme and in the dark one. The same lookup works from the stylesheet side: whitehall why theme.css:<line> lists the tokens that line sets and which classes read them.

whitehall why src/routes/+screen.wh:14      # bg-card on that line: where card is set, light and dark
whitehall why theme.css:9                   # the tokens line 9 sets, and what reads them

See Theming.

The navigation runtime

A routed app is generated with a small navigation runtime, written into MainActivity.kt. None of it is a library, and a stack trace through it names a file you never wrote. Point why at the generated file, or at one of the names, and it says what each piece is for and which .wh fact put it there:

whitehall why …/MainActivity.kt:120
whitehall why …/MainActivity.kt#NavRequests

The … is the path to the generated file, as the stack trace or build log printed it.

For example, NavRequests is the queue $navigate uses outside the composition: a $navigate(…) in a ViewModel function or $onMount has no composition to navigate in, so it sends the route there and MainActivity drains it, in order.

Receipts are read back, not re-derived

The rules come out of the same analyzer the build uses, so a receipt cannot drift from what the compiler does. why only claims what is computed: whether a var is ever assigned is tracked across function bodies, hooks, effect blocks and event handlers, not guessed.

In the editor, hovering a @prop, a var, a store or a store field shows the same receipt, for the buffer as it is, unsaved edits included. See Editor support.

Options

FlagWhat it does
--jsonOutput as JSON, for editors and tooling

See Also