diff --git a/.github/workflows/SonarCloud.yml b/.github/workflows/SonarCloud.yml
index 547f0cbb..b82b5aa3 100644
--- a/.github/workflows/SonarCloud.yml
+++ b/.github/workflows/SonarCloud.yml
@@ -13,13 +13,14 @@ jobs:
# (PRs from forks can't access secrets other than secrets.GITHUB_TOKEN for security reasons)
if: ${{ !github.event.pull_request.head.repo.fork }}
env:
- version: '3.2.1'
- versionFile: '3.2.1'
+ version: '3.2.2'
+ versionFile: '3.2.2'
steps:
- - name: Set up JDK 11
- uses: actions/setup-java@v1
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
with:
- java-version: 1.11
+ distribution: 'microsoft'
+ java-version: '17'
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
diff --git a/appveyor.yml b/appveyor.yml
index 1ab2889b..b352f4a0 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -23,7 +23,7 @@ for:
- ps: dotnet restore SmartFormat.sln --verbosity quiet
- ps: dotnet add .\SmartFormat.Tests\SmartFormat.Tests.csproj package AltCover
- ps: |
- $version = "3.2.1"
+ $version = "3.2.2"
$versionFile = $version + "." + ${env:APPVEYOR_BUILD_NUMBER}
if ($env:APPVEYOR_PULL_REQUEST_NUMBER) {
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 3736ab5e..754858ee 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -8,8 +8,8 @@
Copyright 2011-$(CurrentYear) SmartFormat Projecthttps://github.com/axuno/SmartFormat.gittrue
- 3.2.1
- 3.2.1
+ 3.2.2
+ 3.2.23.0.0latesttrue
diff --git a/src/SmartFormat.Tests/Extensions/PluralLocalizationFormatterTests.cs b/src/SmartFormat.Tests/Extensions/PluralLocalizationFormatterTests.cs
index 6c1e182b..0deaa524 100644
--- a/src/SmartFormat.Tests/Extensions/PluralLocalizationFormatterTests.cs
+++ b/src/SmartFormat.Tests/Extensions/PluralLocalizationFormatterTests.cs
@@ -49,6 +49,31 @@ public void Explicit_Formatter_Without_IEnumerable_Arg_Should_Throw()
Assert.That(() => smart.Format("{0:plural:One|Two}", new object()), Throws.Exception.TypeOf());
}
+ [TestCase("")] // no string
+ [TestCase(false)] // no boolean
+ [TestCase(3.40282347E+38f)] // float.MaxValue exceeds decimal.MaxValue
+ public void Explicit_Formatter_Without_Valid_Argument_Should_Throw(object arg)
+ {
+ var smart = Smart.CreateDefaultSmartFormat();
+ Assert.That(() => smart.Format("{0:plural:One|Two}", arg), Throws.Exception.TypeOf(), "Invalid argument type or value");
+ }
+
+ [TestCase("String", "String")]
+ [TestCase(false, "other")]
+ [TestCase(default(string?), "other")]
+ public void AutoDetect_Formatter_Should_Not_Handle_bool_string_null(object arg, string expected)
+ {
+ var smart = new SmartFormatter()
+ .AddExtensions(new DefaultSource())
+ .AddExtensions(new PluralLocalizationFormatter { CanAutoDetect = true },
+ new ConditionalFormatter { CanAutoDetect = true },
+ new DefaultFormatter());
+
+ // Result comes from ConditionalFormatter!
+ var result = smart.Format("{0:{}|other}", arg);
+ Assert.That(result, Is.EqualTo(expected));
+ }
+
[TestCase(0)]
[TestCase(1)]
[TestCase(100)]
@@ -337,34 +362,4 @@ public void Pluralization_With_Changed_SplitChar(int numOfPeople, string format,
var result = smart.Format(format, data);
Assert.That(result, Is.EqualTo(expected));
}
-
- [Test]
- public void DoesNotHandle_Bool_WhenCanAutoDetect_IsTrue()
- {
- var smart = new SmartFormatter()
- .AddExtensions(new DefaultSource())
- .AddExtensions(new PluralLocalizationFormatter { CanAutoDetect = true }, // Should not handle the bool
- new ConditionalFormatter { CanAutoDetect = true }, // Should handle the bool
- new DefaultFormatter());
-
- var result = smart.Format(new CultureInfo("ar"), "{0:yes|no}", true);
- Assert.That(result, Is.EqualTo("yes"));
- }
-
- [TestCase("A", "[A]")]
- [TestCase(default(string?), "null")]
- public void DoesNotHandle_NonDecimalValues_WhenCanAutoDetect_IsTrue(string? category, string expected)
- {
- var smart = new SmartFormatter()
- .AddExtensions(new DefaultSource())
- .AddExtensions(new ReflectionSource())
- // Should not handle because "Category" value cannot convert to decimal
- .AddExtensions(new PluralLocalizationFormatter { CanAutoDetect = true },
- // Should detect and handle the format
- new ConditionalFormatter { CanAutoDetect = true },
- new DefaultFormatter());
-
- var result = smart.Format(new CultureInfo("en"), "{Category:[{}]|null}", new { Category = category });
- Assert.That(result, Is.EqualTo(expected));
- }
}
diff --git a/src/SmartFormat/Extensions/PluralLocalizationFormatter.cs b/src/SmartFormat/Extensions/PluralLocalizationFormatter.cs
index ae637b36..81b8f1dc 100644
--- a/src/SmartFormat/Extensions/PluralLocalizationFormatter.cs
+++ b/src/SmartFormat/Extensions/PluralLocalizationFormatter.cs
@@ -14,6 +14,7 @@ namespace SmartFormat.Extensions;
///
/// A class to format following culture specific pluralization rules.
+/// The maximum value the formatter can process is .
///
public class PluralLocalizationFormatter : IFormatter
{
@@ -79,7 +80,7 @@ public PluralLocalizationFormatter(string defaultTwoLetterIsoLanguageName)
/// called by its name in the input format string.
///
/// Auto detection only works with more than 1 format argument.
- /// Is recommended to set to . This will be the default in a future version.
+ /// It is recommended to set to . This will be the default in a future version.
///
///
///
@@ -102,31 +103,30 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
var format = formattingInfo.Format;
var current = formattingInfo.CurrentValue;
-
- if (format == null) return false;
- // Extract the plural words from the format string:
+ if (format == null) return false;
+
+ // Extract the plural words from the format string
var pluralWords = format.Split(SplitChar);
+ var useAutoDetection = string.IsNullOrEmpty(formattingInfo.Placeholder?.FormatterName);
+
// This extension requires at least two plural words for auto detection
- // For locales
- if (pluralWords.Count <= 1 && string.IsNullOrEmpty(formattingInfo.Placeholder?.FormatterName))
- {
- // Auto detection calls just return a failure to evaluate
- return false;
- }
+ // Valid types for auto detection are checked later
+ if (useAutoDetection && pluralWords.Count <= 1) return false;
decimal value;
- // Check whether arguments can be handled by this formatter
-
- // We can format numbers, and IEnumerables. For IEnumerables we look at the number of items
- // in the collection: this means the user can e.g. use the same parameter for both plural and list, for example
- // 'Smart.Format("The following {0:plural:person is|people are} impressed: {0:list:{}|, |, and}", new[] { "bob", "alice" });'
+ /*
+ Check whether arguments can be handled by this formatter:
+ We can format numbers, and IEnumerables. For IEnumerables we look at the number of items
+ in the collection: this means the user can e.g. use the same parameter for both plural and list, for example
+ 'Smart.Format("The following {0:plural:person is|people are} impressed: {0:list:{}|, |, and}", new[] { "bob", "alice" });'
+ */
switch (current)
{
- case IConvertible convertible when current is not bool && TryGetDecimalValue(convertible, null, out value):
+ case IConvertible convertible when convertible is not bool or string && TryGetDecimalValue(convertible, null, out value):
break;
case IEnumerable