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
| Subject | The receipt says |
|---|---|
| the file's role | screen, layout, component, and the route a screen serves — from the path, [param] folders and any layout override |
where the file's $state is kept | the 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 val | the declaration, its type, whether anything assigns to it, how often and where it is read |
each $effect | what it becomes |
| each function and class | suspend and where it runs; a class's $state fields and who holds it |
| each lifecycle hook | what it becomes, and what it promises |
$permission(...) | the <uses-permission> entries it derived |
| any line | the 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.
@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
| Flag | What it does |
|---|---|
--json | Output as JSON, for editors and tooling |
See Also
- whitehall check — what the compiler refuses
- whitehall trace — a crash's
Foo.kt:123back to a.whline - Editor support — receipts on hover
- All commands