Skip to content

Commit 7ee489b

Browse files
eemeliaphillips
andauthored
Add error handling (#320)
* Address review comments from @zbraniecki and @aphillips * Apply suggestions from code review * Add Data Model errors & apply suggestions from code review * Add examples * Add Unknown Function + Syntax/Data Model error priority + separate Fallback String Representations section * Specify Declaration vs Placeholder Expression for fallback string * Add paragraph on validation & field=$field example Co-authored-by: Addison Phillips <[email protected]>
1 parent 38fa6f1 commit 7ee489b

File tree

1 file changed

+245
-0
lines changed

1 file changed

+245
-0
lines changed

spec/formatting.md

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,248 @@ the local variable takes precedence.
1818

1919
It is an error for a local variable definition to
2020
refer to a local variable that's defined after it in the message.
21+
22+
## Error Handling
23+
24+
Errors in messages and their formatting may occur and be detected
25+
at multiple different stages of their processing.
26+
Where available,
27+
the use of validation tools is recommended,
28+
as early detection of errors makes their correction easier.
29+
30+
During the formatting of a message,
31+
various errors may be encountered.
32+
These are divided into the following categories:
33+
34+
- **Syntax errors** occur when the syntax representation of a message is not well-formed.
35+
36+
Example invalid messages resulting in a Syntax error:
37+
38+
```
39+
{Missing end brace
40+
```
41+
42+
```
43+
{Unknown {#placeholder#}}
44+
```
45+
46+
```
47+
let $var = {(no message body)}
48+
```
49+
50+
- **Data Model errors** occur when a message is invalid due to
51+
violating one of the semantic requirements on its structure:
52+
53+
- **Variant Key Mismatch errors** occur when the number of keys on a Variant
54+
does not equal the number of Selectors.
55+
56+
Example invalid messages resulting in a Variant Key Mismatch error:
57+
58+
```
59+
match {$one}
60+
when 1 2 {Too many}
61+
when * {Otherwise}
62+
```
63+
64+
```
65+
match {$one} {$two}
66+
when 1 2 {Two keys}
67+
when * {Missing a key}
68+
when * * {Otherwise}
69+
```
70+
71+
- **Missing Fallback Variant errors** occur when the message
72+
does not include a Variant with only catch-all keys.
73+
74+
Example invalid messages resulting in a Missing Fallback Variant error:
75+
76+
```
77+
match {$one}
78+
when 1 {Value is one}
79+
when 2 {Value is two}
80+
```
81+
82+
```
83+
match {$one} {$two}
84+
when 1 * {First is one}
85+
when * 1 {Second is one}
86+
```
87+
88+
- **Resolution errors** occur when the runtime value of a part of a message
89+
cannot be determined.
90+
91+
- **Unresolved Variable errors** occur when a variable reference cannot be resolved.
92+
93+
For example, attempting to format either of the following messages
94+
must result in an Unresolved Variable error if done within a context that
95+
does not provide for the variable reference `$var` to be successfully resolved:
96+
97+
```
98+
{The value is {$var}.}
99+
```
100+
101+
```
102+
match {$var}
103+
when 1 {The value is one.}
104+
when * {The value is not one.}
105+
```
106+
107+
- **Unknown Function errors** occur when an Expression includes
108+
a reference to a function which cannot be resolved.
109+
110+
For example, attempting to format either of the following messages
111+
must result in an Unknown Function error if done within a context that
112+
does not provide for the function `:func` to be successfully resolved:
113+
114+
```
115+
{The value is {(horse) :func}.}
116+
```
117+
118+
```
119+
match {(horse) :func}
120+
when 1 {The value is one.}
121+
when * {The value is not one.}
122+
```
123+
124+
- **Selection errors** occur when message selection fails.
125+
126+
- **Selector errors** are failures in the matching of a key to a specific selector.
127+
128+
For example, attempting to format either of the following messages
129+
might result in a Selector error if done within a context that
130+
uses a `:plural` selector function which requires its input to be numeric:
131+
132+
```
133+
match {(horse) :plural}
134+
when 1 {The value is one.}
135+
when * {The value is not one.}
136+
```
137+
138+
```
139+
let $sel = {(horse) :plural}
140+
match {$sel}
141+
when 1 {The value is one.}
142+
when * {The value is not one.}
143+
```
144+
145+
- **Formatting errors** occur during the formatting of a resolved value,
146+
for example when encountering a value with an unsupported type
147+
or an internally inconsistent set of options.
148+
149+
For example, attempting to format any of the following messages
150+
might result in a Formatting error if done within a context that
151+
152+
1. provides for the variable reference `$user` to resolve to
153+
an object `{ name: 'Kat', id: 1234 }`,
154+
2. provides for the variable reference `$field` to resolve to
155+
a string `'address'`, and
156+
3. uses a `:get` formatting function which requires its argument to be an object and
157+
an option `field` to be provided with a string value,
158+
159+
```
160+
{Hello, {(horse) :get field=name}!}
161+
```
162+
163+
```
164+
{Hello, {$user :get}!}
165+
```
166+
167+
```
168+
let $id = {$user :get field=id}
169+
{Hello, {$id :get field=name}!}
170+
```
171+
172+
```
173+
{Your {$field} is {$id :get field=$field}}
174+
```
175+
176+
Syntax and Data Model errors must be emitted as soon as possible.
177+
178+
During selection, an Expression handler must only emit Resolution and Selection errors.
179+
During formatting, an Expression handler must only emit Resolution and Formatting errors.
180+
181+
In all cases, when encountering an error,
182+
a message formatter must provide some representation of the message.
183+
An informative error or errors must also be separately provided.
184+
When a message contains more than one error,
185+
or contains some error which leads to further errors,
186+
an implementation which does not emit all of the errors
187+
should prioritise Syntax and Data Model errors over others.
188+
189+
When an error occurs in the resolution of an Expression or Markup Option,
190+
the Expression or Markup in question is processed as if the option were not defined.
191+
This may allow for the fallback handling described below to be avoided,
192+
though an error must still be emitted.
193+
194+
When an error occurs within a Selector,
195+
the selector must not match any VariantKey other than the catch-all `*`
196+
and a Resolution or Selector error is emitted.
197+
198+
## Fallback String Representations
199+
200+
The formatted string representation of a message with a Syntax or Data Model error
201+
is the concatenation of U+007B LEFT CURLY BRACKET `{`,
202+
a fallback string,
203+
and U+007D RIGHT CURLY BRACKET `}`.
204+
If a fallback string is not defined,
205+
the U+FFFD REPLACEMENT CHARACTER `�` character is used,
206+
resulting in the string `{�}`.
207+
208+
When an error occurs in a Placeholder that is being formatted,
209+
the fallback string representation of the Placeholder
210+
always starts with U+007B LEFT CURLY BRACKET `{`
211+
and ends with U+007D RIGHT CURLY BRACKET `}`.
212+
Between the brackets, the following contents are used:
213+
214+
- Expression with Literal Operand: U+0028 LEFT PARENTHESIS `(`
215+
followed by the value of the Literal,
216+
and then by U+0029 RIGHT PARENTHESIS `)`
217+
218+
Examples: `{(horse)}`, `{(42)}`
219+
220+
- Expression with Variable Operand: U+0024 DOLLAR SIGN `$`
221+
followed by the Variable Name of the Operand
222+
223+
Example: `{$user}`
224+
225+
- Expression with no Operand: U+003A COLON `:` followed by the Expression Name
226+
227+
Example: `{:platform}`
228+
229+
- Markup start: U+002B PLUS SIGN `+` followed by the MarkupStart Name
230+
231+
Example: `{+tag}`
232+
233+
- Markup end: U+002D HYPHEN-MINUS `-` followed by the MarkupEnd Name
234+
235+
Example: `{-tag}`
236+
237+
- Otherwise: The U+FFFD REPLACEMENT CHARACTER `�` character
238+
239+
Example: `{�}`
240+
241+
Option names and values are not included in the fallback string representations.
242+
243+
When an error occurs in an Expression with a Variable Operand
244+
and the Variable refers to a local variable Declaration,
245+
the fallback string is formatted based on the Expression of the Declaration,
246+
rather than the Expression of the Placeholder.
247+
248+
For example, attempting to format either of the following messages within a context that
249+
does not provide for the function `:func` to be successfully resolved:
250+
251+
```
252+
let $var = {(horse) :func}
253+
{The value is {$var}.}
254+
```
255+
256+
```
257+
let $var = {(horse)}
258+
{The value is {$var :func}.}
259+
```
260+
261+
would result in both cases with this formatted string representation:
262+
263+
```
264+
The value is {(horse)}.
265+
```

0 commit comments

Comments
 (0)