Skip to content

Commit 09c5aa1

Browse files
committed
ICU-22893 Remove support for Unsupported, Private & Reserved constructs
- Matching PR unicode-org#883 in the message-format-wg repo. - Also removes some unused imports
1 parent 1b33f5e commit 09c5aa1

File tree

15 files changed

+30
-264
lines changed

15 files changed

+30
-264
lines changed

icu4j/main/core/src/main/java/com/ibm/icu/message2/MFDataModel.java

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public SelectMessage(
8787
*/
8888
@Deprecated
8989
public interface Declaration {
90-
// Provides a common type for InputDeclaration, LocalDeclaration, and UnsupportedStatement.
90+
// Provides a common type for InputDeclaration, and LocalDeclaration
9191
}
9292

9393
/**
@@ -130,28 +130,6 @@ public LocalDeclaration(String name, Expression value) {
130130
}
131131
}
132132

133-
/**
134-
* @internal ICU 72 technology preview
135-
* @deprecated This API is for technology preview only.
136-
*/
137-
@Deprecated
138-
public static class UnsupportedStatement implements Declaration {
139-
public final String keyword;
140-
public final String body;
141-
public final List<Expression> expressions;
142-
143-
/**
144-
* @internal ICU 72 technology preview
145-
* @deprecated This API is for technology preview only.
146-
*/
147-
@Deprecated
148-
public UnsupportedStatement(String keyword, String body, List<Expression> expressions) {
149-
this.keyword = keyword;
150-
this.body = body;
151-
this.expressions = expressions;
152-
}
153-
}
154-
155133
/**
156134
* @internal ICU 72 technology preview
157135
* @deprecated This API is for technology preview only.
@@ -312,26 +290,6 @@ public FunctionExpression(FunctionAnnotation annotation, List<Attribute> attribu
312290
}
313291
}
314292

315-
/**
316-
* @internal ICU 72 technology preview
317-
* @deprecated This API is for technology preview only.
318-
*/
319-
@Deprecated
320-
public static class UnsupportedExpression implements Expression {
321-
public final UnsupportedAnnotation annotation;
322-
public final List<Attribute> attributes;
323-
324-
/**
325-
* @internal ICU 72 technology preview
326-
* @deprecated This API is for technology preview only.
327-
*/
328-
@Deprecated
329-
public UnsupportedExpression(UnsupportedAnnotation annotation, List<Attribute> attributes) {
330-
this.annotation = annotation;
331-
this.attributes = attributes;
332-
}
333-
}
334-
335293
/**
336294
* @internal ICU 72 technology preview
337295
* @deprecated This API is for technology preview only.
@@ -441,24 +399,6 @@ public Option(String name, LiteralOrVariableRef value) {
441399
}
442400
}
443401

444-
/**
445-
* @internal ICU 72 technology preview
446-
* @deprecated This API is for technology preview only.
447-
*/
448-
@Deprecated
449-
public static class UnsupportedAnnotation implements Annotation {
450-
public final String source;
451-
452-
/**
453-
* @internal ICU 72 technology preview
454-
* @deprecated This API is for technology preview only.
455-
*/
456-
@Deprecated
457-
public UnsupportedAnnotation(String source) {
458-
this.source = source;
459-
}
460-
}
461-
462402
// Markup
463403

464404
/**

icu4j/main/core/src/main/java/com/ibm/icu/message2/MFDataModelFormatter.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
import com.ibm.icu.message2.MFDataModel.Pattern;
2929
import com.ibm.icu.message2.MFDataModel.SelectMessage;
3030
import com.ibm.icu.message2.MFDataModel.StringPart;
31-
import com.ibm.icu.message2.MFDataModel.UnsupportedAnnotation;
32-
import com.ibm.icu.message2.MFDataModel.UnsupportedExpression;
3331
import com.ibm.icu.message2.MFDataModel.VariableRef;
3432
import com.ibm.icu.message2.MFDataModel.Variant;
3533
import com.ibm.icu.util.Calendar;
@@ -104,7 +102,8 @@ String format(Map<String, Object> arguments) {
104102
variables = resolveDeclarations(sm.declarations, arguments);
105103
patternToRender = findBestMatchingPattern(sm, variables, arguments);
106104
} else {
107-
formattingError("");
105+
fatalFormattingError("Unknown message type.");
106+
// formattingError throws, so the return does not actually happen
108107
return "ERROR!";
109108
}
110109

@@ -123,10 +122,8 @@ String format(Map<String, Object> arguments) {
123122
result.append(formattedExpression.getFormattedValue().toString());
124123
} else if (part instanceof MFDataModel.Markup) {
125124
// Ignore
126-
} else if (part instanceof MFDataModel.UnsupportedExpression) {
127-
// Ignore
128125
} else {
129-
formattingError("Unknown part type: " + part);
126+
fatalFormattingError("Unknown part type: " + part);
130127
}
131128
}
132129
return result.toString();
@@ -217,7 +214,7 @@ private Pattern findBestMatchingPattern(
217214
// spec: Append `ks` as the last element of the list `keys`.
218215
keys.add(ks);
219216
} else {
220-
formattingError("Literal expected, but got " + key);
217+
fatalFormattingError("Literal expected, but got " + key);
221218
}
222219
}
223220
// spec: Let `rv` be the resolved value at index `i` of `res`.
@@ -249,7 +246,7 @@ private Pattern findBestMatchingPattern(
249246
}
250247
// spec: Assert that `key` is a _literal_.
251248
if (!(key instanceof Literal)) {
252-
formattingError("Literal expected");
249+
fatalFormattingError("Literal expected");
253250
}
254251
// spec: Let `ks` be the resolved value of `key`.
255252
String ks = ((Literal) key).value;
@@ -304,7 +301,7 @@ private Pattern findBestMatchingPattern(
304301
if (!(key instanceof CatchallKey)) {
305302
// spec: Assert that `key` is a _literal_.
306303
if (!(key instanceof Literal)) {
307-
formattingError("Literal expected");
304+
fatalFormattingError("Literal expected");
308305
}
309306
// spec: Let `ks` be the resolved value of `key`.
310307
String ks = ((Literal) key).value;
@@ -356,7 +353,7 @@ private static int sortVariants(IntVarTuple o1, IntVarTuple o2) {
356353
List<LiteralOrCatchallKey> v1 = o1.variant.keys;
357354
List<LiteralOrCatchallKey> v2 = o1.variant.keys;
358355
if (v1.size() != v2.size()) {
359-
formattingError("The number of keys is not equal.");
356+
fatalFormattingError("The number of keys is not equal.");
360357
}
361358
for (int i = 0; i < v1.size(); i++) {
362359
LiteralOrCatchallKey k1 = v1.get(i);
@@ -399,7 +396,7 @@ public ResolvedSelector(
399396
}
400397
}
401398

402-
private static void formattingError(String message) {
399+
private static void fatalFormattingError(String message) {
403400
throw new IllegalArgumentException(message);
404401
}
405402

@@ -512,24 +509,23 @@ private FormattedPlaceholder formatExpression(
512509
// No output on markup, for now (we only format to string)
513510
return new FormattedPlaceholder(expression, new PlainStringFormattedValue(""));
514511
} else {
515-
UnsupportedExpression ue = (UnsupportedExpression) expression;
516-
char sigil = ue.annotation.source.charAt(0);
517-
return new FormattedPlaceholder(
518-
expression, new PlainStringFormattedValue("{" + sigil + "}"));
512+
if (expression == null) {
513+
fatalFormattingError("unexpected null expression");
514+
} else {
515+
fatalFormattingError("unknown expression type "
516+
+ expression.getClass().getName());
517+
}
519518
}
520519

521520
if (annotation instanceof FunctionAnnotation) {
522521
FunctionAnnotation fa = (FunctionAnnotation) annotation;
523522
if (functionName != null && !functionName.equals(fa.name)) {
524-
formattingError(
523+
fatalFormattingError(
525524
"invalid function overrides, '" + functionName + "' <> '" + fa.name + "'");
526525
}
527526
functionName = fa.name;
528527
Map<String, Object> newOptions = convertOptions(fa.options, variables, arguments);
529528
options.putAll(newOptions);
530-
} else if (annotation instanceof UnsupportedAnnotation) {
531-
// We don't know how to format unsupported annotations
532-
return new FormattedPlaceholder(expression, new PlainStringFormattedValue(fallbackString));
533529
}
534530

535531
FormatterFactory funcFactory = getFormattingFunctionFactoryByName(toFormat, functionName);

icu4j/main/core/src/main/java/com/ibm/icu/message2/MFParser.java

Lines changed: 11 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@ private String getText() {
147147

148148
// abnf: placeholder = expression / markup
149149
// abnf: expression = literal-expression
150-
// abnf: / variable-expression
151-
// abnf: / annotation-expression
150+
// abnf: / variable-expression
151+
// abnf: / annotation-expression
152152
// abnf: literal-expression = "{" [s] literal [s annotation] *(s attribute) [s] "}"
153153
// abnf: variable-expression = "{" [s] variable [s annotation] *(s attribute) [s] "}"
154154
// abnf: annotation-expression = "{" [s] annotation *(s attribute) [s] "}"
155155
// abnf: markup = "{" [s] "#" identifier *(s option) *(s attribute) [s] ["/"] "}" ; open and standalone
156-
// abnf: / "{" [s] "/" identifier *(s option) *(s attribute) [s] "}" ; close
156+
// abnf: / "{" [s] "/" identifier *(s option) *(s attribute) [s] "}" ; close
157157
private MFDataModel.Expression getPlaceholder() throws MFParseException {
158158
int cp = input.peekChar();
159159
if (cp != '{') {
@@ -168,9 +168,7 @@ private MFDataModel.Expression getPlaceholder() throws MFParseException {
168168
result = getMarkup();
169169
} else if (cp == '$') {
170170
result = getVariableExpression();
171-
} else if (StringUtils.isFunctionSigil(cp)
172-
|| StringUtils.isPrivateAnnotationSigil(cp)
173-
|| StringUtils.isReservedAnnotationSigil(cp)) {
171+
} else if (StringUtils.isFunctionSigil(cp)) {
174172
result = getAnnotationExpression();
175173
} else {
176174
result = getLiteralExpression();
@@ -214,16 +212,8 @@ private MFDataModel.Annotation getAnnotation(boolean whitespaceRequired) throws
214212
checkCondition(identifier != null, "Annotation / function name missing");
215213
Map<String, MFDataModel.Option> options = getOptions();
216214
return new MFDataModel.FunctionAnnotation(identifier, options);
217-
default: // reserved && private
218-
if (StringUtils.isReservedAnnotationSigil(cp)
219-
|| StringUtils.isPrivateAnnotationSigil(cp)) {
220-
cp = input.readCodePoint();
221-
// The sigil is part of the body.
222-
// Safe to cast to char, the code point is in BMP
223-
identifier = (char) cp + getIdentifier();
224-
String body = getReservedBody();
225-
return new MFDataModel.UnsupportedAnnotation(identifier + body);
226-
}
215+
default:
216+
// OK to continue and return null, it is an error.
227217
}
228218
input.gotoPosition(position);
229219
return null;
@@ -246,7 +236,7 @@ private MFDataModel.Annotation getMarkupAnnotation() throws MFParseException {
246236
Map<String, MFDataModel.Option> options = getOptions();
247237
return new MFDataModel.FunctionAnnotation(identifier, options);
248238
default:
249-
// reserved, private, function, something else,
239+
// function or something else,
250240
return null;
251241
}
252242
}
@@ -290,17 +280,14 @@ private MFDataModel.Expression getAnnotationExpression() throws MFParseException
290280
if (annotation instanceof MFDataModel.FunctionAnnotation) {
291281
return new MFDataModel.FunctionExpression(
292282
(MFDataModel.FunctionAnnotation) annotation, attributes);
293-
} else if (annotation instanceof MFDataModel.UnsupportedAnnotation) {
294-
return new MFDataModel.UnsupportedExpression(
295-
(MFDataModel.UnsupportedAnnotation) annotation, attributes);
296283
} else {
297284
error("Unexpected annotation : " + annotation);
298285
}
299286
return null;
300287
}
301288

302289
// abnf: markup = "{" [s] "#" identifier *(s option) *(s attribute) [s] ["/"] "}" ; open and standalone
303-
// abnf: / "{" [s] "/" identifier *(s option) *(s attribute) [s] "}" ; close
290+
// abnf: / "{" [s] "/" identifier *(s option) *(s attribute) [s] "}" ; close
304291
private MFDataModel.Markup getMarkup() throws MFParseException {
305292
int cp = input.peekChar(); // consume the '{'
306293
checkCondition(cp == '#' || cp == '/', "Should not happen. Expecting a markup.");
@@ -370,39 +357,6 @@ private MFDataModel.Attribute getAttribute() throws MFParseException {
370357
return null;
371358
}
372359

373-
// abnf: reserved-body = *([s] 1*(reserved-char / reserved-escape / quoted))
374-
// abnf: reserved-escape = backslash ( backslash / "{" / "|" / "}" )
375-
private String getReservedBody() throws MFParseException {
376-
int spaceCount = skipWhitespaces();
377-
StringBuilder result = new StringBuilder();
378-
while (true) {
379-
int cp = input.readCodePoint();
380-
if (StringUtils.isReservedChar(cp)) {
381-
result.appendCodePoint(cp);
382-
} else if (cp == '\\') {
383-
cp = input.readCodePoint();
384-
checkCondition(
385-
cp == '{' || cp == '|' || cp == '}',
386-
"Invalid escape sequence. Only \\{, \\| and \\} are valid here.");
387-
result.append(cp);
388-
} else if (cp == '|') {
389-
input.backup(1);
390-
MFDataModel.Literal quoted = getQuotedLiteral();
391-
result.append(quoted.value);
392-
} else if (cp == EOF) {
393-
return result.toString();
394-
} else {
395-
if (result.length() == 0) {
396-
input.backup(spaceCount + 1);
397-
return "";
398-
} else {
399-
input.backup(1);
400-
return result.toString();
401-
}
402-
}
403-
}
404-
}
405-
406360
// abnf: identifier = [namespace ":"] name
407361
// abnf: namespace = name
408362
// abnf: name = name-start *name-char
@@ -650,7 +604,7 @@ private MFDataModel.SelectMessage getMatch(List<MFDataModel.Declaration> declara
650604
// abnf: key = literal / "*"
651605
private MFDataModel.Variant getVariant() throws MFParseException {
652606
List<MFDataModel.LiteralOrCatchallKey> keys = new ArrayList<>();
653-
// abnf variant = key *(s key) [s] quoted-pattern
607+
// abnf: variant = key *(s key) [s] quoted-pattern
654608
while (true) {
655609
// Space is required between keys
656610
MFDataModel.LiteralOrCatchallKey key = getKey(!keys.isEmpty());
@@ -705,8 +659,6 @@ private static class MatchDeclaration implements MFDataModel.Declaration {
705659

706660
// abnf: input-declaration = input [s] variable-expression
707661
// abnf: local-declaration = local s variable [s] "=" [s] expression
708-
// abnf: reserved-statement = reserved-keyword [s reserved-body] 1*([s] expression)
709-
// abnf: reserved-keyword = "." name
710662
private MFDataModel.Declaration getDeclaration() throws MFParseException {
711663
int position = input.getPosition();
712664
skipOptionalWhitespaces();
@@ -745,32 +697,8 @@ private MFDataModel.Declaration getDeclaration() throws MFParseException {
745697
break;
746698
case "match":
747699
return new MatchDeclaration();
748-
default: // abnf: reserved-statement = reserved-keyword [s reserved-body] 1*([s] expression)
749-
skipOptionalWhitespaces();
750-
String body = getReservedBody();
751-
List<MFDataModel.Expression> expressions = new ArrayList<>();
752-
while (true) {
753-
skipOptionalWhitespaces();
754-
// Look ahead to detect the end of the unsupported statement
755-
// (next token either begins a placeholder or begins a complex body)
756-
cp = input.readCodePoint();
757-
int cp1 = input.readCodePoint();
758-
if (cp == '{' && cp1 == '{') {
759-
// End of unsupported statement
760-
input.backup(2);
761-
break;
762-
} else {
763-
input.backup(2);
764-
}
765-
expression = getPlaceholder();
766-
// This also covers != null
767-
if (expression instanceof MFDataModel.VariableExpression) {
768-
expressions.add(expression);
769-
} else {
770-
break;
771-
}
772-
}
773-
return new MFDataModel.UnsupportedStatement(declName, body, expressions);
700+
default:
701+
// OK to continue and return null, it is an error.
774702
}
775703
return null;
776704
}

0 commit comments

Comments
 (0)