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

Spec 5.4.2: "A conformant SCXML document MUST specify either 'expr' or
children of `<assign>`, but not both." Reports `{:assign_expr_and_text,
expr}` at the `<assign>`'s own element span.

`lib/statifier/document/assign.ex` makes both `expr` and `text`
representable at once precisely so this check can report the shape rather
than lowering refusing to build it - the same division of labour
`Checks.Content` has with `<content>` and `Checks.Data` has with `<data>`.

**Whitespace-only text is not text.** `Statifier.Parser.DOM.text/1`
concatenates `<assign>`'s direct text children verbatim and untrimmed, so
a pretty-printed `<assign expr="1">\n  </assign>` carries a `text` of
`"\n  "`. That is source formatting, not a payload, and firing on it
would reject documents the spec allows - the same rule
`Checks.Content.blank?/1` and `Checks.Data.blank?/1` already follow.

This check walks every state's own `onentry`/`onexit` blocks, every
state's own transitions (both plain and a `:history` state's default -
`Statifier.Document.State.transitions` covers both), and every state's
`<initial>` element's own transition - the three places
`Statifier.Document.Assign` can appear as executable content
(`Statifier.Document.Block.t()`'s and `Statifier.Document.Transition.t()`'s
own `content` fields).

# `check`

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

Walks every `<assign>` reachable through a state's `onentry`/`onexit`
blocks or its own (and its `<initial>` element's) transitions, and returns
an `:assign_expr_and_text` error for each one that carries both an `expr`
attribute and non-blank child text. Returns `[]` when no `<assign>` in the
document mixes the two forms.

---

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