One reason something was refused.
A finding is the unit every refusal in this package reports: a template that names a construct outside the template subset, and later a document whose vocabulary is not admitted. Refusals return a list of findings rather than the first one, so that an author fixing what they wrote learns everything wrong with it in a single pass.
The fields stay few, and one is added only where a host would otherwise have
to read the :message to get at something it needs:
:code- a stable, machine-readable reason. Hosts switch on it; it does not change when the wording does.:message- the human sentence, naming what was refused and, where the refusal has a place in some source text, where it appeared.:field- what the finding is about: the name of the refused construct for a template, the offending field for a document.nilwhen the refusal is about the input as a whole.:node_key- the key of the document node the finding belongs to, and always a string ornil. It isnilwherever there is no key a host can look a node up by: a template finding, because a template is compiled on its own without the document that carries it; a finding about the envelope, which is the document's and not any one node's; and a node whose key is absent or is not a string. A key of the wrong form is named in themessagerather than carried here, because a host reads this field to find the node the author has to fix and a key that is not a string is not a name it can find one by.:position- where in some source text the refusal is, as%{line: line, column: column}, both one-based. The column counts in the unit of the parser that located the refusal, and this package converts neither: a column the template parser gave counts bytes, and a column the condition compiler or the evaluator gave counts characters. The two differ wherever a multi-byte character stands before the place on its line, so a host that maps a column onto an editor offset reads the finding's code to know which it holds. Five places in this package set it: the two template refusal clauses inRiddler.Template, thedocument.invalid_templatefinding that re-reports a template refusal against the template a document node writes, which carries the position of the refusal it wraps, thedocument.invalid_conditionfinding, which carries the place the condition compiler gave for a condition that does not parse and nothing for a condition that never reached the parser, and theresponse.undecidablefinding, which carries the place the condition compiler or the evaluator gave for the condition it is about and nothing where neither gave one. The first three give bytes and the last two give characters. Every other finding leaves itnil- the document checks, a field refused for not being template source at all (which carries that same code, so the code alone does not say whether a span is there), and the otherresponse.*findings.document.invalid_patternis one of those by decision rather than by defect: the regular expression compiler answers a byte count into the expression this package compiles rather than a line and a column, and across the refusals run that count lands at the defect for some and at the end of the input for others, and is moved, or its reason replaced, by the anchors this package adds. A place derived from it would be right for some refusals under that code and wrong for others, which is worse for a host than none; the comment abovecompile_pattern/1in the internal Riddler.Screens.Compilers module records what was run. Where there is a position the:messagenames it too and goes on naming it, so that a person reading a finding reads one sentence; this field is the same fact in the form an editor can act on without parsing that sentence.
Examples
iex> finding = %Riddler.Finding{
...> code: "template.tag_not_allowed",
...> message: ~s[the tag "include" is not in the template subset (line 1, column 3)],
...> field: "include",
...> position: %{line: 1, column: 3}
...> }
iex> {finding.node_key, finding.position}
{nil, %{line: 1, column: 3}}
Summary
Types
A place in some source text: a one-based line and a one-based column. The
column counts bytes where the template parser located the place and
characters where the condition compiler or the evaluator did; the
:position field in the moduledoc says which finding gives which.
Types
@type position() :: %{line: pos_integer(), column: pos_integer()}
A place in some source text: a one-based line and a one-based column. The
column counts bytes where the template parser located the place and
characters where the condition compiler or the evaluator did; the
:position field in the moduledoc says which finding gives which.