StatifierUI.Trace.Diagnostic (StatifierUI v0.4.0)

Copy Markdown View Source

The wire error object for an expression failure: what docs/wire-format.md documents as an event object's error key.

This is the only caller of Statifier.Parser.Location.resolve_span/4 in this repo (ADR-0002 - never reimplement the engine's span composition locally). Every span this module emits, and every location it composes from one, follows that helper's convention: both the predicator span's end and the returned location's end are exclusive.

resolve_span/4 degrades rather than raising - a position past the end of the value clamps to the value location's end, and a raw/expanded desync returns the value location whole - so this module never rescues it. Per project convention (CLAUDE.md, "errors are values / never rescue-to-default at a leaf"), a call that could fail is not the shape the failure takes here: the helper's own degraded return already is the fallback.

A nil value location or a nil span means there is nothing to resolve. anchor/3 never calls resolve_span/4 in either case - it returns {:node, _} instead, so object/4 falls back to the owning node's own span. That branch is this module deciding not to call the helper, which is a different thing from catching what it raises.

location_kind reports what the producer did, not what the helper decided

"resolved" means resolve_span/4 was called with a value location and a span. "node" means it was not (no span, or no value location) and the owning node's own span was emitted instead. This module never inspects the result to guess which happened - resolve_span/4's own degraded return (falling back to the value location whole) is indistinguishable from a genuine resolution by looking at the location alone, and modeling that distinction here would be exactly the ADR-0002 failure this module exists to prevent. So "resolved" may still span the whole attribute value when the helper degraded internally.

Summary

Functions

Where to anchor error's span for origin: the value location of the failing expression ({:value, _}, resolved against error.span by the caller), the owning node's own span with nothing further to resolve ({:node, _}), or nothing at all (:none).

The wire error object for error, raised with cause origin.

Functions

anchor(arg1, machine, error)

Where to anchor error's span for origin: the value location of the failing expression ({:value, _}, resolved against error.span by the caller), the owning node's own span with nothing further to resolve ({:node, _}), or nothing at all (:none).

Dispatches on origin and, for content, on the content struct itself - never on a generic Map.get(node, :location) || Map.get(node, :node_location) reflection, the same posture StatifierUI.Trace.Manifest.content_location/1 takes and for the same reason: that fallback is silently wrong for Statifier.Machine.Content.Assign, whose :location is a path-expression string, not a span.

A candidate value location is only ever returned as {:value, _} when error.span is non-nil - a nil span means resolve_span/4 would not be called, so the caller must not be handed a location that invites it.

object(error, origin, machine, source)

The wire error object for error, raised with cause origin.

"kind" and "expression" are always present. "span" is present only when error.span is non-nil. "location"/"location_kind" are present only when both machine and source are supplied and anchor/3 finds a location to anchor on - origin of nil, machine/source of nil, or an origin anchor/3 cannot resolve at all all omit both keys, key absence being the ADR-0005 discipline for "nothing here" rather than a null or a sentinel.