Skip to content

8385834: Duplicate placeholders behavior of ListFormat#31377

Open
naotoj wants to merge 3 commits into
openjdk:masterfrom
naotoj:JDK-8385834-Duplicate-placeholders-behavior-of-ListFormat
Open

8385834: Duplicate placeholders behavior of ListFormat#31377
naotoj wants to merge 3 commits into
openjdk:masterfrom
naotoj:JDK-8385834-Duplicate-placeholders-behavior-of-ListFormat

Conversation

@naotoj
Copy link
Copy Markdown
Member

@naotoj naotoj commented Jun 3, 2026

Made changes to the invalid placeholder handling in ListFormat.getInstance(String[]), stemming from JDK-8385736.

This rejects duplicate placeholders and "{2}" outside the three pattern, with spec and test updates. Also includes minor Javadoc formatting cleanups. The invalid-long-pattern test added with JDK-8385736 has been repurposed to cover the newly specified invalid-placeholder cases, because the repeated-placeholder input is now rejected immediately by duplicate-placeholder validation.

Since this changes the behavior of the method, a corresponding CSR has been drafted.



Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Change requires CSR request JDK-8385841 to be approved
  • Commit message must refer to an issue

Issues

  • JDK-8385834: Duplicate placeholders behavior of ListFormat (Bug - P4)
  • JDK-8385841: Duplicate placeholders behavior of ListFormat (CSR)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/31377/head:pull/31377
$ git checkout pull/31377

Update a local copy of the PR:
$ git checkout pull/31377
$ git pull https://git.openjdk.org/jdk.git pull/31377/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 31377

View PR using the GUI difftool:
$ git pr show -t 31377

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/31377.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link
Copy Markdown

bridgekeeper Bot commented Jun 3, 2026

👋 Welcome back naoto! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link
Copy Markdown

openjdk Bot commented Jun 3, 2026

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk Bot added csr Pull request needs approved CSR before integration core-libs core-libs-dev@openjdk.org i18n i18n-dev@openjdk.org labels Jun 3, 2026
@openjdk
Copy link
Copy Markdown

openjdk Bot commented Jun 3, 2026

@naotoj The following labels will be automatically applied to this pull request:

  • core-libs
  • i18n

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@naotoj naotoj marked this pull request as ready for review June 4, 2026 00:00
@openjdk openjdk Bot added the rfr Pull request is ready for review label Jun 4, 2026
@mlbridge
Copy link
Copy Markdown

mlbridge Bot commented Jun 4, 2026

Webrevs

Copy link
Copy Markdown
Member

@justin-curtis-lu justin-curtis-lu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate placeholder checking looks good to me. New test cases look good and exhaustive. Some other comments below.

var patterns = new String[]{
"{0}, {1}",
"{0}, {1}",
"{0}, and {1}",
"{0} and {1}",
"{0} {1} {2}"
};
patterns[index] = "{0}".repeat(100_000);
patterns[index] = invalidPattern;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that the current implementation rejects this input immediately because it contains duplicate placeholders, but I think this 100_000 length case is still worth preserving as a regression test. I might retain it as a simple standalone test that preserves the long string input (and probably only needs to be checked against one pattern, not all). I say this because I don't think the test should be relying on an assumption of the current implementation.

var positions = new int[3];
for (int i = 0; i < positions.length; i++) {
positions[i] = pattern.indexOf("{" + i + "}");
var ph = "{" + i + "}";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ListFormat uses MessageFormat, which means that any patterns taken by the former get passed to the latter.

What would we expect to happen if {3} was passed as a pattern. Do we expect that to be printed out literally? Do we expect to reject it because it takes the form of a placeholder but exceeds the 0-2 value range?

In the current form, depending on the number of elements, it could either be printed out literally, or it could be interpreted as a MessageFormat pattern. For example,

String[] p = {
      "{3} {0}, {1}",
      "{0}, {1}",
      "{0}, and {1}",
      "",
      "" 
};
var lf = ListFormat.getInstance(p);
lf.format(List.of("a", "b", "c", "d")); // -> d a, b, c, and d
lf.format(List.of("a", "b", "c")); // -> {3} a, b, and c

I would not be opposed to rejecting any placeholders that are not in the form of only 0, 1, and 2. I am going to guess that no locales rely on {HARD_CODED_NUMBER} as being a part of their list patterns. What do you think?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think rejecting is fine. In fact, I made it stricter as any curly brace use other than 0/1/2 now throws an exception because MessageFormat has its own parsing, which prevents "{foo}" from working as a literal.

* can be created with {@link #getInstance(String[])}. The String array to the
* method specifies the delimiting patterns for the start/middle/end portion of
* the formatted string, as well as optional specialized patterns for two or three
* method specifies the delimiting patterns for the {@code start}/{@code middle}/{@code end}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "The string array passed to the method" reads better.

* If parsing of any pattern string for start, middle, end, two, or three fails,
* it throws an {@code IllegalArgumentException}.
* }
* If {@code two} or {@code three} pattern string is empty, it falls back to
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend: If the {@code two} ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core-libs core-libs-dev@openjdk.org csr Pull request needs approved CSR before integration i18n i18n-dev@openjdk.org rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

2 participants