Repository navigation
WW-5836 Bound integer digits in number tag and message arguments - #2095
Open
lukaszlenart wants to merge 1 commit into
Open
lukaszlenart wants to merge 1 commit into
lukaszlenart wants to merge 1 commit into
Conversation
…uments WW-5828 bounded the integer digits StringConverter emits for a BigDecimal and falls back to BigDecimal.toString() past 340. The number tag and MessageFormat arguments format a BigDecimal without StringConverter, so neither applied the bound. The bound moves to BigDecimalBounds and is shared by StringConverter, the number tag and message argument formatting. The number tag falls back to toString() past the bound. Its maximumIntegerDigits attribute is not a substitute: DecimalFormat applies it by dropping leading digits. For message arguments the argument itself cannot be replaced, because a typed element such as {0,number} rejects a String. When an argument is past the bound, BoundedMessageFormat formats through a clone whose elements delegate to their original formats and render the over-bound value with toString(). A ChoiceFormat element whose branch contains {n} is re-parsed by MessageFormat only when the element's format is a ChoiceFormat, so the wrapper repeats that step with the bound applied to the nested pattern. A call with no argument past the bound is formatted by MessageFormat unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lukaszlenart
marked this pull request as ready for review
November 3, 2026 18:48
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes WW-5836
WW-5828 bounded the integer digits
StringConverteremits for aBigDecimal, falling back toBigDecimal.toString()past 340. Two other paths format aBigDecimalwithout going throughStringConverter, and neither applied the bound:numbertag (Number.end()), which formats the value from the stack withNumberFormatdirectly;MessageFormatarguments:AbstractLocalizedTextProvider.formatWithNullDetection(reached fromgetText(key, args),<s:text>with<s:param>, and validatormessageParams) andDefaultTextProvider.getText(key, defaultValue, List).The bound and its check (
precision - scale, computed inlong) move toBigDecimalBounds, shared byStringConverter, the number tag and message formatting.Number tag. Past the bound the value renders with
toString(). The tag'smaximumIntegerDigitsattribute is not a substitute, becauseDecimalFormatapplies it by dropping leading digits.Message arguments. The argument itself cannot be replaced with a
String, because a typed element such as{0,number}throwsIllegalArgumentExceptionon a String. Instead, when an argument is past the bound,BoundedMessageFormatformats through a clone whose elements delegate to their original formats and render the over-bound value withtoString().MessageFormatre-parses a choice branch that contains{n}only when the element's format is an actualChoiceFormat. Wrapping a choice element would therefore print the nested{0}literally, and leaving it unwrapped would format the nested pattern without the bound. The wrapper repeats that step itself, with the bound applied to the nested pattern at every level. A call with no argument past the bound goes toMessageFormatunchanged.Tests pin both sides of the bound for:
type="currency";{0},{0,number}and{0,number,currency};null) next to an over-bound argument;{1}, and a branch with no nested argument.Below the bound, the output is compared byte for byte with plain
MessageFormat. Full core suite green (3633).Observable change: a value with more than 340 integer digits renders in
1E+340form in these paths, as it already does throughStringConverter. A{0,date}element given such a value prints that form too, instead of a date built fromlongValue().A 6.x backport follows in a separate PR.
🤖 Generated with Claude Code