StatifierBlocks.SlotValidation (StatifierBlocks v0.31.0)

Copy Markdown View Source

ADR-0002 decision 6's two properties, checked over a whole document against a palette: declared slots are the complete set a block may carry (:undeclared_slot), and a slot's child count must satisfy the arity its type declares for it (:slot_arity_violated).

One implementation, consulted by both the editor and the compiler (sb-iwz), the same way StatifierBlocks.Assignability is - both are passed the same palette and the same document, and neither owns a private copy of either rule.

Ordering

validate/2 walks Document.blocks/1 (pre-order, root first) and concatenates each block's findings, so the result is already in the order a caller wants to report them. Within one block, arity findings come first, in slots/1's own declaration order; undeclared-slot findings come after, in UTF-8-sorted slot-name order (matching Document.blocks/1's own sorted slot traversal).

Degradation

A block whose type fails Palette.resolve/2 contributes no findings of either kind - the same permissive default Assignability.produces/4 uses, because unresolvability is ADR-0002 decision 3's own finding, reported by the walk that owns it, not this one.

Totality, and where the slots/1 precondition holds

module.slots(resolved.config) is called with no rescue, exactly as Assignability.valid_targets/4 calls module.slots/1: this package's rule is that nothing is rescued to a default. ADR-0002 decision 6 guarantees slots/1 returns without raising only for a config validate_config/1 accepts, so validate/2 is total over any document and palette whose block types honour that guarantee for the configs they are handed. In the compiler this precondition holds by construction - the Config stage runs validate_config/1 over every block and stops the pipeline before Structure runs - but a caller outside the compiler (an editor, mid-edit) wanting the same guarantee runs validate_config/1 first.

Summary

Functions

Whether count children satisfies arity, per ADR-0002 decision 6's four-row table: :any admits any count; :at_least_one needs count >= 1; :exactly_one needs count == 1; :zero_or_one needs count <= 1.

Every slot-arity and undeclared-slot finding in document against palette, in Document.blocks/1 pre-order. :ok when the list is empty.

Types

Functions

arity_satisfied?(atom, count)

Whether count children satisfies arity, per ADR-0002 decision 6's four-row table: :any admits any count; :at_least_one needs count >= 1; :exactly_one needs count == 1; :zero_or_one needs count <= 1.

validate(palette, document)

@spec validate(StatifierBlocks.Palette.t(), StatifierBlocks.Document.t()) ::
  :ok | {:error, [finding()]}

Every slot-arity and undeclared-slot finding in document against palette, in Document.blocks/1 pre-order. :ok when the list is empty.

Per block: Palette.resolve(palette, block). On {:error, _} the block contributes nothing. On {:ok, module, resolved}, module.slots(resolved.config) is the declaration list checked - resolved.config, not block.config, because the migrated config is what the type's own declarations are read against (ADR-0002 decision 8), and it is what the compiler's Resolve stage already uses.