Skip to content

6. Constraints and findings

Contents of DESL 0.2

Constraints say what makes a document valid. They are written in CEL, evaluated by the runtime and by headless validators, and reported to the user as findings. A document with findings is still opened, shown and saved.

6.1 Overview

Property Type Description
rules Constraint[] The constraints, in order.
defaults {severity, timing} Defaults for every rule: a severity, and when rules are evaluated, from "live" (after every transaction), "save" (before a document is written) and "explicit" (when the user asks). Default severity "error", timing ["live", "save"].
blockSaveOn "never", "error" Whether a document with errors may not be saved. Default "never".
doc Doc

6.2 Constraint object

Property Type Description
id identifier Required, unique.
code qualified identifier The code every finding of the rule reports (knowledge.no-title).
label, doc Its name and explanation, shown with every finding.
scope "document" or TypeRefs What the rule is evaluated for: once for the document, or once per element of the types, with self bound to it. Default "document".
when Expression The rule is evaluated only where this holds.
rule Expression → bool Required. The condition that must hold.
severity "error", "warning", "info", "hint", or {cel} Default from defaults.
message Message The finding's text.
target Expression The element or elements the finding is attached to. Default self, or the document for scope: "document".
enforcement "report", "prevent", "prevent-and-report" prevent: a transaction that would make the rule false for an element it held for is rolled back, with the message as its refusal. Default "report".
enabled bool Default true.
{ "id": "severalTitles", "code": "knowledge.several-titles", "scope": ["Property"], "severity": "error",
  "rule": "self.positionIn(document.elementsOfType('Property').filter(p, p.title)) == 0",
  "message": "Only one property can be the title; this one is not used as the title." }

The rule holds for the first title property only, so every later one is a finding.

6.3 Findings

Evaluating constraints, and reading a document, produce findings. A finding carries:

Property Type Description
constraint constraint id or built-in id The rule that raised it. Required.
code qualified identifier The rule's code, when it has one.
severity "error", "warning", "info", "hint" Required.
message string The rule's Message, evaluated. Required.
target element or elements What the finding is about; the document for a rule scoped to it.
location SourceLocation Where in the file it is.
subject string A display string naming something that is not an element, such as an unreadable entry.

Every finding MUST carry at least one of target, location and subject. A runtime MUST show findings in a list, where choosing one reveals its element or goes to its location, and beside the element they target.

A SourceLocation is {file, line?, column?, length?}: file relative to the document's own folder with / separators, line and column 1-based, and column and length counted in Unicode code points. When a finding targets an element, its location is where the reader recorded that element.

Order. Findings MUST be listed: first those the reader raised (std.unparseable, std.unreadableEntry, std.missingId, std.duplicateId) in reading order; then the other built-ins, in the order of the table in 6.5; then declared constraints in the order of rules, each by its scope elements in document order.

Parse failure. A reader that cannot parse a body MUST report exactly one std.unparseable finding, at the parser's line and column when it has them, and no other finding located in that body; no constraint is evaluated over it. Whether the document then opens empty or read-only is FBL's (FBL section 9).

6.4 Gesture refusals

A constraint with enforcement prevent or prevent-and-report MUST refuse a transaction that would make it false for an element it held for, before anything is written, and MUST show its message, evaluated in the working state, as the refusal. A refused transaction changes nothing.

6.5 Built-in constraints

The metamodel and the reader raise these by themselves. They behave as declared constraints; their texts are worded by the runtime.

Id Raised for Severity
std.required an attribute with required: true that has no value, or (DESL 0.2) the empty value of its type error
std.facets a value outside min, max, minLength, maxLength or pattern, or an enumeration value no value of the enumeration has error
std.references a reference that names no element error
std.containment a child whose type its parent's children, or its slot, does not allow, or (DESL 0.2) an element without a parent whose type metamodel.document.children does not allow error
std.unparseable the reader, once per body that cannot be parsed (6.3) error
std.unreadableEntry the reader, per entry of a parsed body that cannot become an element: an unknown key, a value that does not convert, an entry in no known form; the entry is kept as written warning
std.missingId the reader or runtime, per element without a usable id, or whose derived id cannot be computed (5.3.4) warning
std.duplicateId the reader or runtime, per element whose id equals that of an element earlier in reading order (5.3.4) warning
std.mentions (DESL 0.2) a mention that names no element of the types its mentions facet lists (4.3) warning

A reader MUST report the reader's four as they occur, and MUST NOT fail to open a document because of any of them.

Referenced from