Skip to content

Commit 32f5ca3

Browse files
committed
Add single method to control error handling behavior
Add MessageFormatter::Builder::setErrorHandlingBehavior() method and a new enum type MessageFormatter::Builder::UMFErrorHandlingBehavior to denote strict or best-effort behavior. The reason for adding a single method that takes an enum is to allow for the possibility of more error handling modes in the future.
1 parent db75954 commit 32f5ca3

File tree

4 files changed

+66
-34
lines changed

4 files changed

+66
-34
lines changed

icu4c/source/i18n/messageformat2_formatter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ namespace message2 {
8181
return *this;
8282
}
8383

84+
MessageFormatter::Builder&
85+
MessageFormatter::Builder::setErrorHandlingBehavior(
86+
MessageFormatter::Builder::UMFErrorHandlingBehavior type) {
87+
switch (type) {
88+
case U_MF_STRICT: {
89+
signalErrors = true;
90+
break;
91+
}
92+
case U_MF_BEST_EFFORT: {
93+
signalErrors = false;
94+
break;
95+
}
96+
}
97+
return *this;
98+
}
99+
84100
/*
85101
This build() method is non-destructive, which entails the risk that
86102
its borrowed MFFunctionRegistry and (if the setDataModel() method was called)

icu4c/source/i18n/unicode/messageformat2.h

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,29 @@ namespace message2 {
171171

172172
void clearState();
173173
public:
174+
/*
175+
* Used in conjunction with the `setErrorHandlingBehavior()` method.
176+
*
177+
* @internal ICU 76 technology preview
178+
* @deprecated This API is for technology preview only.
179+
*/
180+
typedef enum UMFErrorHandlingBehavior {
181+
/*
182+
* Suppress errors and return best-effort output.
183+
*
184+
* @internal ICU 76 technology preview
185+
* @deprecated This API is for technology preview only.
186+
*/
187+
U_MF_BEST_EFFORT = 0,
188+
/*
189+
* Signal all MessageFormat errors using the UErrorCode
190+
* argument.
191+
*
192+
* @internal ICU 76 technology preview
193+
* @deprecated This API is for technology preview only.
194+
*/
195+
U_MF_STRICT
196+
} UMFErrorHandlingBehavior;
174197
/**
175198
* Sets the locale to use for formatting.
176199
*
@@ -222,42 +245,35 @@ namespace message2 {
222245
*/
223246
Builder& setDataModel(MFDataModel&& dataModel);
224247
/**
225-
* Set this formatter to handle errors "strictly",
226-
* meaning that formatting methods will set their
227-
* UErrorCode arguments to signal MessageFormat data model,
228-
* resolution, and runtime errors. Syntax errors are
229-
* always signaled.
230-
* This doesn't re-trigger parsing of an existing pattern,
231-
* so it has to be called before parsing the pattern
232-
* whose error behavior should be affected.
248+
* Set the error handling behavior for this formatter.
233249
*
234-
* The default is to suppress all MessageFormat errors
235-
* and return best-effort output.
236-
*
237-
* @return A reference to the builder.
250+
* "Strict" error behavior means that that formatting methods
251+
* will set their UErrorCode arguments to signal MessageFormat
252+
* data model, resolution, and runtime errors. Syntax errors are
253+
* always signaled.
238254
*
239-
* @internal ICU 75 technology preview
240-
* @deprecated This API is for technology preview only.
241-
*/
242-
Builder& setStrictErrors() { signalErrors = true; return *this; }
243-
/**
244-
* Set this formatter to suppress errors
245-
* meaning that formatting methods will _not_ set their
255+
* "Best effort" error behavior means that MessageFormat errors are
256+
* suppressed: formatting methods will _not_ set their
246257
* UErrorCode arguments to signal MessageFormat data model,
247258
* resolution, or runtime errors. Best-effort output
248259
* will be returned. Syntax errors are always signaled.
249260
* This is the default behavior.
250261
*
251-
* This doesn't re-trigger parsing of an existing pattern,
252-
* so it has to be called before parsing the pattern
253-
* whose error behavior should be affected.
262+
* @param type An enum with type `UMFErrorHandlingBehavior`;
263+
* if type == `U_MF_STRICT`, then
264+
* errors are handled strictly.
265+
* If type == `U_MF_BEST_EFFORT`, then
266+
* best-effort output is returned.
267+
*
268+
* The default is to suppress all MessageFormat errors
269+
* and return best-effort output.
254270
*
255271
* @return A reference to the builder.
256272
*
257-
* @internal ICU 75 technology preview
273+
* @internal ICU 76 technology preview
258274
* @deprecated This API is for technology preview only.
259275
*/
260-
Builder& setSuppressErrors() { signalErrors = false; return *this; }
276+
Builder& setErrorHandlingBehavior(UMFErrorHandlingBehavior type);
261277
/**
262278
* Constructs a new immutable MessageFormatter using the pattern or data model
263279
* that was previously set, and the locale (if it was previously set)

icu4c/source/test/intltest/messageformat2test.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ void TestMessageFormat2::testFormatterAPI() {
7575
// if there's a syntax error
7676
UnicodeString pattern = "{{}";
7777
MessageFormatter::Builder mfBuilder(errorCode);
78-
mfBuilder.setSuppressErrors(); // This shouldn't matter, since there's a syntax error
78+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_BEST_EFFORT); // This shouldn't matter, since there's a syntax error
7979
mfBuilder.setPattern(pattern, parseError, errorCode);
8080
MessageFormatter mf = mfBuilder.build(errorCode);
8181
U_ASSERT(errorCode == U_MF_SYNTAX_ERROR);
8282

8383
/*
8484
Parsing is done when setPattern() is called,
85-
so setStrictErrors() or setSuppressErrors must be called
85+
so setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT) or setSuppressErrors must be called
8686
_before_ setPattern() to get the right behavior,
8787
and if either method is called after setting a pattern,
8888
setPattern() has to be called again.
8989
*/
9090
// Should get the same behavior with strict errors
9191
errorCode.reset();
92-
mfBuilder.setStrictErrors();
92+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT);
9393
// Force re-parsing, as above comment
9494
mfBuilder.setPattern(pattern, parseError, errorCode);
9595
mf = mfBuilder.build(errorCode);
@@ -99,7 +99,7 @@ void TestMessageFormat2::testFormatterAPI() {
9999
pattern = "{{{$x}}}";
100100
errorCode.reset();
101101
// Check that a pattern with a resolution error gives fallback output
102-
mfBuilder.setSuppressErrors();
102+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_BEST_EFFORT);
103103
mfBuilder.setPattern(pattern, parseError, errorCode);
104104
mf = mfBuilder.build(errorCode);
105105
U_ASSERT(U_SUCCESS(errorCode));
@@ -108,7 +108,7 @@ void TestMessageFormat2::testFormatterAPI() {
108108
U_ASSERT(result == "{$x}");
109109

110110
// Check that we do get an error with strict errors
111-
mfBuilder.setStrictErrors();
111+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT);
112112
mf = mfBuilder.build(errorCode);
113113
U_ASSERT(U_SUCCESS(errorCode));
114114
result = mf.formatToString(MessageArguments(), errorCode);
@@ -118,15 +118,15 @@ void TestMessageFormat2::testFormatterAPI() {
118118
errorCode.reset();
119119
pattern = "hello";
120120
mfBuilder.setPattern(pattern, parseError, errorCode);
121-
mfBuilder.setSuppressErrors();
121+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_BEST_EFFORT);
122122
mf = mfBuilder.build(errorCode);
123123
U_ASSERT(U_SUCCESS(errorCode));
124124
result = mf.formatToString(MessageArguments(), errorCode);
125125
U_ASSERT(U_SUCCESS(errorCode));
126126
U_ASSERT(result == "hello");
127127

128128
// Check that behavior is the same with strict errors
129-
mfBuilder.setStrictErrors();
129+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT);
130130
mf = mfBuilder.build(errorCode);
131131
U_ASSERT(U_SUCCESS(errorCode));
132132
result = mf.formatToString(MessageArguments(), errorCode);
@@ -286,7 +286,7 @@ void TestMessageFormat2::testAPICustomFunctions() {
286286
MessageFormatter::Builder mfBuilder(errorCode);
287287
UnicodeString result;
288288
// This fails, because we did not provide a function registry:
289-
MessageFormatter mf = mfBuilder.setStrictErrors()
289+
MessageFormatter mf = mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT)
290290
.setPattern("Hello {$name :person formality=informal}",
291291
parseError, errorCode)
292292
.setLocale(locale)

icu4c/source/test/intltest/messageformat2test_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ class TestUtils {
230230
}
231231
// Initially, set error behavior to strict.
232232
// We'll re-run to check for errors.
233-
mfBuilder.setStrictErrors();
233+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_STRICT);
234234
MessageFormatter mf = mfBuilder.build(errorCode);
235235
UnicodeString result;
236236

@@ -279,7 +279,7 @@ class TestUtils {
279279
// Re-run the formatter if there was an error,
280280
// in order to get best-effort output
281281
errorCode.reset();
282-
mfBuilder.setSuppressErrors();
282+
mfBuilder.setErrorHandlingBehavior(MessageFormatter::Builder::U_MF_BEST_EFFORT);
283283
mf = mfBuilder.build(errorCode);
284284
if (U_SUCCESS(errorCode)) {
285285
result = mf.formatToString(MessageArguments(testCase.getArguments(), errorCode), errorCode);

0 commit comments

Comments
 (0)