Statifier.Lowering.Error (Statifier v2.0.0)

Copy Markdown View Source

Lowering's own error shape: never raised, always collected into a list.

Mirrors Statifier.Parser.ParseError's shape (reason, message, location) but is a plain struct rather than a defexception - lowering never raises, and Statifier.Lowering.lower/1 returns errors in a list rather than as a single exception, so a builder that fails on its own account can still return a partial result, the walk keeps going, and every error found in one pass is reported rather than just the first.

The reason union below is declared as the complete, closed set of shapes lowering can report. missing_attribute/3 and foreign_element/3 extend it alongside the unsupported_element, stray_text, unexpected_root, and misplaced_element constructors, each added without reopening the type.

Summary

Functions

An element resolves to a namespace URI that is neither absent nor the SCXML namespace - a genuinely foreign element, since an unprefixed element or one declaring no xmlns still dispatches as SCXML's own vocabulary. name is the qualified name exactly as written, prefix included, so the message points at what the source actually said.

A known element built somewhere its parent has no slot for it.

A required attribute is absent, so the element's struct cannot be built at all - <raise> with no event is the first case (:event is @enforce_keys'd on Statifier.Document.Raise).

Non-whitespace text found where the element's content model has no room for it.

An element that takes no attributes at all (spec 4.5.2's <else>) was written with one anyway - unlike missing_attribute/3, this never blocks the element's own struct from being built (<else> needs no attribute to build its branch), so the caller reports this alongside the struct it still constructs, not instead of it.

The document's root element is not <scxml> (or does not resolve to it once namespace prefixes are resolved).

An element name with no entry in the dispatch map.

The spec defines attribute on element, but this engine does not implement it - deliberately distinct from unexpected_attribute/3, whose "does not accept attribute" message would be false here: the spec defines it, this engine simply refuses to act on it. <script src> is the first case (ADR-0026 decision 2: <script>'s src attribute is rejected at load, never fetched - the same unresolved external-fetch question <data src> leaves open, see ADR-0024). No struct is built when this fires; the caller reports this error alone rather than also attempting a build.

Types

reason()

@type reason() ::
  {:unsupported_element, name :: binary()}
  | {:misplaced_element, name :: binary(), parent :: binary()}
  | {:stray_text, text :: binary()}
  | {:unexpected_root, name :: binary()}
  | {:missing_attribute, element :: binary(), attribute :: binary()}
  | {:foreign_element, name :: binary(), uri :: binary()}
  | {:unexpected_attribute, element :: binary(), attribute :: binary()}
  | {:unsupported_attribute, element :: binary(), attribute :: binary()}

t()

@type t() :: %Statifier.Lowering.Error{
  location: Statifier.Parser.Location.t(),
  message: binary(),
  reason: reason()
}

Functions

foreign_element(name, uri, location)

@spec foreign_element(
  name :: binary(),
  uri :: binary(),
  location :: Statifier.Parser.Location.t()
) ::
  t()

An element resolves to a namespace URI that is neither absent nor the SCXML namespace - a genuinely foreign element, since an unprefixed element or one declaring no xmlns still dispatches as SCXML's own vocabulary. name is the qualified name exactly as written, prefix included, so the message points at what the source actually said.

misplaced(name, parent, location)

@spec misplaced(
  name :: binary(),
  parent :: binary(),
  location :: Statifier.Parser.Location.t()
) :: t()

A known element built somewhere its parent has no slot for it.

missing_attribute(element, attribute, location)

@spec missing_attribute(
  element :: binary(),
  attribute :: binary(),
  location :: Statifier.Parser.Location.t()
) :: t()

A required attribute is absent, so the element's struct cannot be built at all - <raise> with no event is the first case (:event is @enforce_keys'd on Statifier.Document.Raise).

stray_text(text, location)

@spec stray_text(text :: binary(), location :: Statifier.Parser.Location.t()) :: t()

Non-whitespace text found where the element's content model has no room for it.

text is the trimmed run, truncated to a readable prefix so the message does not embed a paragraph.

unexpected_attribute(element, attribute, location)

@spec unexpected_attribute(
  element :: binary(),
  attribute :: binary(),
  location :: Statifier.Parser.Location.t()
) :: t()

An element that takes no attributes at all (spec 4.5.2's <else>) was written with one anyway - unlike missing_attribute/3, this never blocks the element's own struct from being built (<else> needs no attribute to build its branch), so the caller reports this alongside the struct it still constructs, not instead of it.

unexpected_root(name, location)

@spec unexpected_root(name :: binary(), location :: Statifier.Parser.Location.t()) ::
  t()

The document's root element is not <scxml> (or does not resolve to it once namespace prefixes are resolved).

unsupported(name, location)

@spec unsupported(name :: binary(), location :: Statifier.Parser.Location.t()) :: t()

An element name with no entry in the dispatch map.

unsupported_attribute(element, attribute, location)

@spec unsupported_attribute(
  element :: binary(),
  attribute :: binary(),
  location :: Statifier.Parser.Location.t()
) :: t()

The spec defines attribute on element, but this engine does not implement it - deliberately distinct from unexpected_attribute/3, whose "does not accept attribute" message would be false here: the spec defines it, this engine simply refuses to act on it. <script src> is the first case (ADR-0026 decision 2: <script>'s src attribute is rejected at load, never fetched - the same unresolved external-fetch question <data src> leaves open, see ADR-0024). No struct is built when this fires; the caller reports this error alone rather than also attempting a build.