Further simplify `NumberFormat` initialization; make fields that can be final, final.
PiperOrigin-RevId: 328333657
diff --git a/lib/src/intl/compact_number_format.dart b/lib/src/intl/compact_number_format.dart
index ceb13d1..fd53814 100644
--- a/lib/src/intl/compact_number_format.dart
+++ b/lib/src/intl/compact_number_format.dart
@@ -130,91 +130,17 @@
_CompactStyle styleForSign(number) => this;
List<_CompactStyle> get allStyles => [this];
-}
-/// Enumerates the different formats supported.
-enum _CompactFormatType {
- COMPACT_DECIMAL_SHORT_PATTERN,
- COMPACT_DECIMAL_LONG_PATTERN,
- COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN
-}
+ static final _regex = RegExp('([^0]*)(0+)(.*)');
-class _CompactNumberFormat extends NumberFormat {
- /// A default, using the decimal pattern, for the `getPattern` constructor parameter.
- static String _forDecimal(NumberSymbols symbols) => symbols.DECIMAL_PATTERN;
-
- List<_CompactStyleBase> _styles = [];
-
- _CompactNumberFormat(
- {String locale,
- _CompactFormatType formatType,
- String name,
- String currencySymbol,
- String Function(NumberSymbols) getPattern = _forDecimal,
- int decimalDigits,
- bool lookupSimpleCurrencySymbol = false,
- bool isForCurrency = false})
- : super._forPattern(locale, getPattern,
- name: name,
- currencySymbol: currencySymbol,
- decimalDigits: decimalDigits,
- lookupSimpleCurrencySymbol: lookupSimpleCurrencySymbol,
- isForCurrency: isForCurrency) {
- significantDigits = 3;
- turnOffGrouping();
-
- /// Map from magnitude to formatting pattern for that magnitude.
- ///
- /// The magnitude is the exponent when using the normalized scientific
- /// notation (so numbers from 1000 to 9999 correspond to magnitude 3).
- ///
- /// These patterns are taken from the appropriate CompactNumberSymbols
- /// instance's COMPACT_DECIMAL_SHORT_PATTERN, COMPACT_DECIMAL_LONG_PATTERN,
- /// or COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN members.
- Map<int, String> _patterns;
-
- switch (formatType) {
- case _CompactFormatType.COMPACT_DECIMAL_SHORT_PATTERN:
- _patterns = _compactSymbols.COMPACT_DECIMAL_SHORT_PATTERN;
- break;
- // TODO(alanknight): Long formats may have different forms for different
- // plural cases (e.g. million/millions).
- case _CompactFormatType.COMPACT_DECIMAL_LONG_PATTERN:
- _patterns = _compactSymbols.COMPACT_DECIMAL_LONG_PATTERN ??
- _compactSymbols.COMPACT_DECIMAL_SHORT_PATTERN;
- break;
- case _CompactFormatType.COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN:
- _patterns = _compactSymbols.COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN;
- break;
- default:
- throw ArgumentError.notNull('formatType');
- }
- _patterns.forEach((int exponent, String pattern) {
- if (pattern.contains(';')) {
- var patterns = pattern.split(';');
- _styles.add(_CompactStyleWithNegative(
- _createStyle(patterns.first, exponent),
- _createStyle(patterns.last, exponent)));
- } else {
- _styles.add(_createStyle(pattern, exponent));
- }
- });
-
- // Reverse the styles so that we look through them from largest to smallest.
- _styles = _styles.reversed.toList();
- // Add a fallback style that just prints the number.
- _styles.add(_CompactStyle());
- }
-
- final _regex = RegExp('([^0]*)(0+)(.*)');
-
- final _justZeros = RegExp(r'^0*$');
+ static final _justZeros = RegExp(r'^0*$');
/// Does pattern have any additional characters or is it just zeros.
- bool _hasNonZeroContent(String pattern) => !_justZeros.hasMatch(pattern);
+ static bool _hasNonZeroContent(String pattern) =>
+ !_justZeros.hasMatch(pattern);
/// Creates a [_CompactStyle] instance for pattern with [normalizedExponent].
- _CompactStyle _createStyle(String pattern, int normalizedExponent) {
+ static _CompactStyle createStyle(String pattern, int normalizedExponent) {
var match = _regex.firstMatch(pattern);
var integerDigits = match.group(2).length;
var prefix = match.group(1);
@@ -237,6 +163,121 @@
suffix: suffix,
divisor: divisor);
}
+}
+
+/// Enumerates the different formats supported.
+enum _CompactFormatType {
+ COMPACT_DECIMAL_SHORT_PATTERN,
+ COMPACT_DECIMAL_LONG_PATTERN,
+ COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN
+}
+
+class _CompactNumberFormat extends NumberFormat {
+ /// A default, using the decimal pattern, for the `getPattern` constructor parameter.
+ static String _forDecimal(NumberSymbols symbols) => symbols.DECIMAL_PATTERN;
+
+ final List<_CompactStyleBase> _styles;
+
+ factory _CompactNumberFormat(
+ {String locale,
+ _CompactFormatType formatType,
+ String name,
+ String currencySymbol,
+ String Function(NumberSymbols) getPattern = _forDecimal,
+ int decimalDigits,
+ bool lookupSimpleCurrencySymbol = false,
+ bool isForCurrency = false}) {
+ // Initialization copied from `NumberFormat` constructor.
+ // TODO(davidmorgan): deduplicate.
+ locale = Intl.verifiedLocale(locale, NumberFormat.localeExists);
+ var symbols = numberFormatSymbols[locale];
+ var localeZero = symbols.ZERO_DIGIT.codeUnitAt(0);
+ var zeroOffset = localeZero - NumberFormat._zero;
+ name ??= symbols.DEF_CURRENCY_CODE;
+ if (currencySymbol == null && lookupSimpleCurrencySymbol) {
+ currencySymbol = NumberFormat._simpleCurrencySymbols[name];
+ }
+ currencySymbol ??= name;
+ var pattern = getPattern(symbols);
+
+ // CompactNumberFormat initialization.
+
+ /// Map from magnitude to formatting pattern for that magnitude.
+ ///
+ /// The magnitude is the exponent when using the normalized scientific
+ /// notation (so numbers from 1000 to 9999 correspond to magnitude 3).
+ ///
+ /// These patterns are taken from the appropriate CompactNumberSymbols
+ /// instance's COMPACT_DECIMAL_SHORT_PATTERN, COMPACT_DECIMAL_LONG_PATTERN,
+ /// or COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN members.
+ Map<int, String> patterns;
+
+ var compactSymbols = compactNumberSymbols[locale];
+
+ var styles = <_CompactStyleBase>[];
+ switch (formatType) {
+ case _CompactFormatType.COMPACT_DECIMAL_SHORT_PATTERN:
+ patterns = compactSymbols.COMPACT_DECIMAL_SHORT_PATTERN;
+ break;
+ // TODO(alanknight): Long formats may have different forms for different
+ // plural cases (e.g. million/millions).
+ case _CompactFormatType.COMPACT_DECIMAL_LONG_PATTERN:
+ patterns = compactSymbols.COMPACT_DECIMAL_LONG_PATTERN ??
+ compactSymbols.COMPACT_DECIMAL_SHORT_PATTERN;
+ break;
+ case _CompactFormatType.COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN:
+ patterns = compactSymbols.COMPACT_DECIMAL_SHORT_CURRENCY_PATTERN;
+ break;
+ default:
+ throw ArgumentError.notNull('formatType');
+ }
+ patterns.forEach((int exponent, String pattern) {
+ if (pattern.contains(';')) {
+ var patterns = pattern.split(';');
+ styles.add(_CompactStyleWithNegative(
+ _CompactStyle.createStyle(patterns.first, exponent),
+ _CompactStyle.createStyle(patterns.last, exponent)));
+ } else {
+ styles.add(_CompactStyle.createStyle(pattern, exponent));
+ }
+ });
+
+ // Reverse the styles so that we look through them from largest to smallest.
+ styles = styles.reversed.toList();
+ // Add a fallback style that just prints the number.
+ styles.add(_CompactStyle());
+
+ return _CompactNumberFormat._(
+ name,
+ currencySymbol,
+ isForCurrency,
+ locale,
+ localeZero,
+ pattern,
+ symbols,
+ zeroOffset,
+ _NumberFormatParser.parse(symbols, pattern, isForCurrency,
+ currencySymbol, name, decimalDigits),
+ styles);
+ }
+
+ _CompactNumberFormat._(
+ String currencyName,
+ String currencySymbol,
+ bool isForCurrency,
+ String locale,
+ int localeZero,
+ String pattern,
+ NumberSymbols symbols,
+ int zeroOffset,
+ _NumberFormatParseResult result,
+ // Fields introduced in this class.
+ this._styles)
+ : super._(currencyName, currencySymbol, isForCurrency, locale, localeZero,
+ pattern, symbols, zeroOffset, result) {
+ significantDigits = 3;
+ turnOffGrouping();
+ }
/// The style in which we will format a particular number.
///
@@ -367,8 +408,4 @@
return null;
}
}
-
- /// The [CompactNumberSymbols] instance that corresponds to the [_locale] this
- /// [NumberFormat] instance was configured for.
- CompactNumberSymbols get _compactSymbols => compactNumberSymbols[_locale];
}
diff --git a/lib/src/intl/number_format.dart b/lib/src/intl/number_format.dart
index bfa4237..be92ab8 100644
--- a/lib/src/intl/number_format.dart
+++ b/lib/src/intl/number_format.dart
@@ -60,10 +60,10 @@
/// equivalent to "#E0" and does not take into account significant digits.
class NumberFormat {
/// Variables to determine how number printing behaves.
- String _negativePrefix;
- String _positivePrefix;
- String _negativeSuffix;
- String _positiveSuffix;
+ final String _negativePrefix;
+ final String _positivePrefix;
+ final String _negativeSuffix;
+ final String _positiveSuffix;
/// How many numbers in a group when using punctuation to group digits in
/// large numbers. e.g. in en_US: "1,000,000" has a grouping size of 3 digits
@@ -75,15 +75,15 @@
int _finalGroupingSize;
/// Set to true if the format has explicitly set the grouping size.
- bool _decimalSeparatorAlwaysShown;
- bool _useSignForPositiveExponent;
- bool _useExponentialNotation;
+ final bool _decimalSeparatorAlwaysShown;
+ final bool _useSignForPositiveExponent;
+ final bool _useExponentialNotation;
/// Explicitly store if we are a currency format, and so should use the
/// appropriate number of decimal digits for a currency.
// TODO(alanknight): Handle currency formats which are specified in a raw
/// pattern, not using one of the currency constructors.
- bool _isForCurrency;
+ final bool _isForCurrency;
int maximumIntegerDigits;
int minimumIntegerDigits;
@@ -106,20 +106,20 @@
/// For percent and permille, what are we multiplying by in order to
/// get the printed value, e.g. 100 for percent.
- int _multiplier;
+ final int _multiplier;
/// How many digits are there in the [_multiplier].
- int _multiplierDigits;
+ final int _multiplierDigits;
/// Stores the pattern used to create this format. This isn't used, but
/// is helpful in debugging.
- String _pattern;
+ final String _pattern;
/// The locale in which we print numbers.
final String _locale;
/// Caches the symbols used for our locale.
- NumberSymbols _symbols;
+ final NumberSymbols _symbols;
/// The name of the currency to print, in ISO 4217 form.
String currencyName;
@@ -127,12 +127,7 @@
/// The symbol to be used when formatting this as currency.
///
/// For example, "$", "US$", or "€".
- String _currencySymbol;
-
- /// The symbol to be used when formatting this as currency.
- ///
- /// For example, "$", "US$", or "€".
- String get currencySymbol => _currencySymbol;
+ final String currencySymbol;
/// The number of decimal places to use when formatting.
///
@@ -149,9 +144,7 @@
/// NumberFormat.currency(locale: 'en_US')
/// will format with two, which is the default for that locale.
///
- int get decimalDigits => _decimalDigits;
-
- int _decimalDigits;
+ final int decimalDigits;
/// Transient internal state in which to build up the result of the format
/// operation. We can have this be just an instance variable because Dart is
@@ -166,21 +159,22 @@
NumberFormat._forPattern(locale, (x) => newPattern);
/// Create a number format that prints as DECIMAL_PATTERN.
- NumberFormat.decimalPattern([String locale])
- : this._forPattern(locale, (x) => x.DECIMAL_PATTERN);
+ factory NumberFormat.decimalPattern([String locale]) =>
+ NumberFormat._forPattern(locale, (x) => x.DECIMAL_PATTERN);
/// Create a number format that prints as PERCENT_PATTERN.
- NumberFormat.percentPattern([String locale])
- : this._forPattern(locale, (x) => x.PERCENT_PATTERN);
+ factory NumberFormat.percentPattern([String locale]) =>
+ NumberFormat._forPattern(locale, (x) => x.PERCENT_PATTERN);
/// Create a number format that prints as PERCENT_PATTERN.
- NumberFormat.decimalPercentPattern({String locale, int decimalDigits})
- : this._forPattern(locale, (x) => x.PERCENT_PATTERN,
- decimalDigits: decimalDigits);
+ factory NumberFormat.decimalPercentPattern(
+ {String locale, int decimalDigits}) =>
+ NumberFormat._forPattern(locale, (x) => x.PERCENT_PATTERN,
+ decimalDigits: decimalDigits);
/// Create a number format that prints as SCIENTIFIC_PATTERN.
- NumberFormat.scientificPattern([String locale])
- : this._forPattern(locale, (x) => x.SCIENTIFIC_PATTERN);
+ factory NumberFormat.scientificPattern([String locale]) =>
+ NumberFormat._forPattern(locale, (x) => x.SCIENTIFIC_PATTERN);
/// A regular expression to validate currency names are exactly three
/// alphabetic characters.
@@ -242,17 +236,18 @@
/// format. This is useful if you have your own locale data which includes
/// unsupported formats (e.g. accounting format for currencies.)
// TODO(alanknight): Should we allow decimalDigits on other numbers.
- NumberFormat.currency(
- {String locale,
- String name,
- String symbol,
- int decimalDigits,
- String customPattern})
- : this._forPattern(locale, (x) => customPattern ?? x.CURRENCY_PATTERN,
- name: name,
- currencySymbol: symbol,
- decimalDigits: decimalDigits,
- isForCurrency: true);
+ factory NumberFormat.currency(
+ {String locale,
+ String name,
+ String symbol,
+ int decimalDigits,
+ String customPattern}) =>
+ NumberFormat._forPattern(
+ locale, (x) => customPattern ?? x.CURRENCY_PATTERN,
+ name: name,
+ currencySymbol: symbol,
+ decimalDigits: decimalDigits,
+ isForCurrency: true);
/// Creates a [NumberFormat] for currencies, using the simple symbol for the
/// currency if one is available (e.g. $, €), so it should only be used if the
@@ -483,58 +478,65 @@
/// The [currencySymbol] can either be specified directly, or we can pass a
/// function [computeCurrencySymbol] that will compute it later, given other
/// information, typically the verified locale.
- NumberFormat._forPattern(String locale, _PatternGetter getPattern,
+ factory NumberFormat._forPattern(String locale, _PatternGetter getPattern,
{String name,
String currencySymbol,
int decimalDigits,
bool lookupSimpleCurrencySymbol = false,
- bool isForCurrency = false})
- : _locale = Intl.verifiedLocale(locale, localeExists),
- _isForCurrency = isForCurrency {
- _symbols = numberFormatSymbols[_locale];
- _localeZero = _symbols.ZERO_DIGIT.codeUnitAt(0);
- _zeroOffset = _localeZero - _zero;
- currencyName = name ?? _symbols.DEF_CURRENCY_CODE;
-
- _currencySymbol = currencySymbol;
- if (_currencySymbol == null && lookupSimpleCurrencySymbol) {
- _currencySymbol = _simpleCurrencySymbols[currencyName];
+ bool isForCurrency = false}) {
+ locale = Intl.verifiedLocale(locale, localeExists);
+ var symbols = numberFormatSymbols[locale];
+ var localeZero = symbols.ZERO_DIGIT.codeUnitAt(0);
+ var zeroOffset = localeZero - _zero;
+ name ??= symbols.DEF_CURRENCY_CODE;
+ if (currencySymbol == null && lookupSimpleCurrencySymbol) {
+ currencySymbol = _simpleCurrencySymbols[name];
}
- _currencySymbol ??= currencyName;
+ currencySymbol ??= name;
var pattern = getPattern(symbols);
- // Save pattern with spaces converted to hard spaces, just for debugging.
- _pattern = pattern?.replaceAll(' ', '\u00a0');
-
- var result = _NumberFormatParser.parse(symbols, pattern, _isForCurrency,
- _currencySymbol, currencyName, decimalDigits);
-
- _positivePrefix = result.positivePrefix;
- _negativePrefix = result.negativePrefix;
- _positiveSuffix = result.positiveSuffix;
- _negativeSuffix = result.negativeSuffix;
-
- _multiplier = result.multiplier;
- _multiplierDigits = result.multiplierDigits;
-
- _useExponentialNotation = result.useExponentialNotation;
- minimumExponentDigits = result.minimumExponentDigits;
-
- maximumIntegerDigits = result.maximumIntegerDigits;
- minimumIntegerDigits = result.minimumIntegerDigits;
- maximumFractionDigits = result.maximumFractionDigits;
- minimumFractionDigits = result.minimumFractionDigits;
-
- _groupingSize = result.groupingSize;
- _finalGroupingSize = result.finalGroupingSize;
-
- _useSignForPositiveExponent = result.useSignForPositiveExponent;
- _decimalSeparatorAlwaysShown = result.decimalSeparatorAlwaysShown;
-
- _decimalDigits = result.decimalDigits;
+ return NumberFormat._(
+ name,
+ currencySymbol,
+ isForCurrency,
+ locale,
+ localeZero,
+ pattern,
+ symbols,
+ zeroOffset,
+ _NumberFormatParser.parse(symbols, pattern, isForCurrency,
+ currencySymbol, name, decimalDigits));
}
+ NumberFormat._(
+ this.currencyName,
+ this.currencySymbol,
+ this._isForCurrency,
+ this._locale,
+ this._localeZero,
+ this._pattern,
+ this._symbols,
+ this._zeroOffset,
+ _NumberFormatParseResult result)
+ : _positivePrefix = result.positivePrefix,
+ _negativePrefix = result.negativePrefix,
+ _positiveSuffix = result.positiveSuffix,
+ _negativeSuffix = result.negativeSuffix,
+ _multiplier = result.multiplier,
+ _multiplierDigits = result.multiplierDigits,
+ _useExponentialNotation = result.useExponentialNotation,
+ minimumExponentDigits = result.minimumExponentDigits,
+ maximumIntegerDigits = result.maximumIntegerDigits,
+ minimumIntegerDigits = result.minimumIntegerDigits,
+ maximumFractionDigits = result.maximumFractionDigits,
+ minimumFractionDigits = result.minimumFractionDigits,
+ _groupingSize = result.groupingSize,
+ _finalGroupingSize = result.finalGroupingSize,
+ _useSignForPositiveExponent = result.useSignForPositiveExponent,
+ _decimalSeparatorAlwaysShown = result.decimalSeparatorAlwaysShown,
+ decimalDigits = result.decimalDigits;
+
/// A number format for compact representations, e.g. "1.2M" instead
/// of "1,200,000".
factory NumberFormat.compact({String locale}) {
@@ -947,13 +949,13 @@
/// The code point for the locale's zero digit.
///
/// Initialized when the locale is set.
- int _localeZero = 0;
+ final int _localeZero;
/// The difference between our zero and '0'.
///
/// In other words, a constant _localeZero - _zero. Initialized when
/// the locale is set.
- int _zeroOffset = 0;
+ final int _zeroOffset;
/// Returns the prefix for [x] based on whether it's positive or negative.
/// In en_US this would be '' and '-' respectively.