diff --git a/QueryKit.UnitTests/FilterParsingRegressionTests.cs b/QueryKit.UnitTests/FilterParsingRegressionTests.cs index 2116f59..eaacd16 100644 --- a/QueryKit.UnitTests/FilterParsingRegressionTests.cs +++ b/QueryKit.UnitTests/FilterParsingRegressionTests.cs @@ -28,21 +28,12 @@ public void decimal_value_uses_invariant_culture(string cultureName) [Theory] [InlineData("de-DE")] [InlineData("fr-FR")] - public void decimal_value_with_culture_decimal_comma_is_read_as_before(string cultureName) - { - var input = """Rating > 4,5"""; - - var filterExpression = WithCulture(cultureName, () => FilterParser.ParseFilter(input)); - - filterExpression.ToDisplayString().Should().Be("x => (x.Rating > 45)"); - } - - [Fact] - public void decimal_value_with_decimal_comma_is_not_accepted_in_a_culture_with_decimal_point() + [InlineData("en-US")] + public void decimal_value_with_decimal_comma_is_not_accepted(string cultureName) { var input = """Rating > 4,5"""; - var act = () => WithCulture("en-US", () => FilterParser.ParseFilter(input)); + var act = () => WithCulture(cultureName, () => FilterParser.ParseFilter(input)); act.Should().Throw(); } diff --git a/QueryKit/FilterParser.cs b/QueryKit/FilterParser.cs index 37bac4d..038cf69 100644 --- a/QueryKit/FilterParser.cs +++ b/QueryKit/FilterParser.cs @@ -206,24 +206,8 @@ from micros in DateTimeMicrosParser from timeZone in DateTimeZoneParser select dateFormat + timeFormat + micros + timeZone; - // A number with a '.' decimal point, or with the decimal separator of the current culture. - // The longer match wins, so '4.5' parses in every culture and '4,5' still parses in a culture that uses ','. - private static readonly Parser UnsignedNumberParser = input => - { - var invariant = Parse.DecimalInvariant(input); - var culture = Parse.Decimal(input); - return culture.WasSuccessful && (!invariant.WasSuccessful || culture.Remainder.Position > invariant.Remainder.Position) - ? culture - : invariant; - }; - + // A number always uses the '.' decimal point, so a filter has the same meaning in every culture. private static readonly Parser NumberParser = - from sign in Parse.Char('-').Optional().Select(x => x.IsDefined ? "-" : "") - from number in UnsignedNumberParser - select sign + number; - - // List items are separated by ',', so a list number always uses the '.' decimal point. - private static readonly Parser ListNumberParser = from sign in Parse.Char('-').Optional().Select(x => x.IsDefined ? "-" : "") from number in Parse.DecimalInvariant select sign + number; @@ -247,7 +231,7 @@ from closingQuotes in Parse.Char('"').Repeat(count).Text() .Or(GuidFormatParser) .Or(DateTimeFormatParser) .Or(TimeFormatParser) - .Or(ListNumberParser) + .Or(NumberParser) .Or(RawStringLiteralParser.Or(DoubleQuoteParser)) .Or(Identifier) .DelimitedBy(Parse.Char(',').Token()); @@ -472,7 +456,7 @@ private static Expression CreateRightExprFromType(Type leftExprType, string righ var targetType = leftExprType; if (isEnumerable) { - if (op.IsCountOperator() && (int.TryParse(right, out var intVal) || int.TryParse(right, NumberStyles.Integer, CultureInfo.InvariantCulture, out intVal))) + if (op.IsCountOperator() && int.TryParse(right, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) { return FilterValue.Parameter(intVal, typeof(int)); } @@ -1365,8 +1349,7 @@ private static bool IsPropertyPath(string value, Type entityType) if (value == "null" || value.StartsWith("\"") || value.StartsWith("[") || - value.Contains("-") && (DateTime.TryParse(value, out _) || DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) || - decimal.TryParse(value, out _) || + value.Contains("-") && DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out _) || decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out _) || bool.TryParse(value, out _) || Guid.TryParse(value, out _))