# `Statifier.Validator.Checks.If`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.0.0/lib/statifier/validator/checks/if.ex#L1)

Spec 4.3.2: "In a conformant SCXML document, `<else>` MUST occur after all
`<elseif>` tags." `Statifier.Lowering.Builders.build_if/2` has already
partitioned an `<if>`'s children into `branches` by the time a
`%Statifier.Document.If{}` reaches the validator, so this check reads
branch order directly rather than re-parsing `<elseif>`/`<else>` element
names.

A branch's `cond` is `nil` only for the `<else>` branch. `cond` is
required on both `<if>` (4.3.1) and `<elseif>` (4.4.1), and
`Statifier.Lowering.Builders.build_if/2` and `build_elseif/2` report
`missing_attribute` and build no node at all when it is absent, so a
cond-less non-`<else>` branch never reaches the validator. This check
still keys off `cond: nil` rather than an explicit "is an `<else>`" flag,
because that is the shape `Statifier.Document.If.Branch` actually carries;
it just does not have a second case to distinguish. Once the first
`nil`-cond branch in document order is seen, every branch after it is
illegal:

- another `nil`-cond branch is a second `<else>`, reported
  `{:if_duplicate_else}` at *that* branch's own `location`
- a `cond`-carrying branch is an `<elseif>` after an `<else>`, reported
  `{:if_elseif_after_else}` at *that* branch's own `location`

Classifying by the *offending* branch's own shape (rather than, say,
flagging the first `nil`-cond branch for "not being last") is what keeps
the two-`<else>`s case reporting exactly once, at the second `<else>`,
instead of also flagging the first as "not last".

This check walks every state's own `onentry`/`onexit` blocks, every
state's own transitions (both plain and a `:history` state's default),
and every state's `<initial>` element's own transition - the same three
places `Statifier.Validator.Checks.Assign` walks - and recurses into every
`<if>` nested inside another `<if>`'s branch content (SCION's
`if_else/test0` nests two deep), since spec 4.3.2 explicitly allows
nested `<if>` as executable content. It recurses into a `<foreach>`'s own
content the same way, so an `<if>` written inside a loop body (`test153`)
is not invisible to this check either.

# `check`

```elixir
@spec check(
  document :: Statifier.Document.t(),
  context :: Statifier.Validator.Context.t()
) :: [
  Statifier.Validator.Error.t()
]
```

Walks every `<if>` reachable through a state's `onentry`/`onexit` blocks or
its own (and its `<initial>` element's) transitions, recursing into nested
`<if>`s, and returns an `:if_elseif_after_else` or `:if_duplicate_else`
error for each branch that follows the first `nil`-cond branch of its own
`<if>`. Returns `[]` when every `<if>` in the document keeps its `<else>`
(if any) last and singular.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
