Skip to content

Commit

Permalink
Fixed: Incorrect Handling of Qualifiers in ConstantExpressionHelper (#…
Browse files Browse the repository at this point in the history
…824)

* include ParseRealLiteral tests

* Change ParseRealLiteral to remove literals before parsing

* Merge master

* NumberParserTests to split the tests NumberParser_Parse[Type]Literal
  • Loading branch information
RenanCarlosPereira authored Jun 25, 2024
1 parent 1bd7a90 commit d14b76e
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 49 deletions.
25 changes: 20 additions & 5 deletions src/System.Linq.Dynamic.Core/Parser/NumberParser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Globalization;
using System.Globalization;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Validation;
using System.Linq.Expressions;
Expand Down Expand Up @@ -161,19 +161,34 @@ public Expression ParseIntegerLiteral(int tokenPosition, string text)
/// </summary>
public Expression ParseRealLiteral(string text, char qualifier, bool stripQualifier)
{
if (stripQualifier)
{
var pos = text.Length - 1;
while (pos >= 0 && Qualifiers.Contains(text[pos]))
{
pos--;
}

if (pos < text.Length - 1)
{
qualifier = text[pos + 1];
text = text.Substring(0, pos + 1);
}
}

switch (qualifier)
{
case 'f':
case 'F':
return _constantExpressionHelper.CreateLiteral(ParseNumber(stripQualifier ? text.Substring(0, text.Length - 1) : text, typeof(float))!, text);
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(float))!, text);

case 'm':
case 'M':
return _constantExpressionHelper.CreateLiteral(ParseNumber(stripQualifier ? text.Substring(0, text.Length - 1) : text, typeof(decimal))!, text);
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(decimal))!, text);

case 'd':
case 'D':
return _constantExpressionHelper.CreateLiteral(ParseNumber(stripQualifier ? text.Substring(0, text.Length - 1) : text, typeof(double))!, text);
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(double))!, text);

default:
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(double))!, text);
Expand Down Expand Up @@ -298,4 +313,4 @@ private Expression ParseAsBinary(int tokenPosition, string text, bool isNegative
throw new ParseException(string.Format(_culture, Res.InvalidBinaryIntegerLiteral, text), tokenPosition);
}
}
}
}
136 changes: 92 additions & 44 deletions test/System.Linq.Dynamic.Core.Tests/Parser/NumberParserTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using FluentAssertions;
using FluentAssertions;
using System.Collections.Generic;
using System.Globalization;
using System.Linq.Dynamic.Core.Parser;
Expand All @@ -15,15 +15,15 @@ public static object[][] Decimals()
{
return new object[][]
{
new object[] { "de-DE", "1", 1m },
new object[] { "de-DE", "-42", -42m },
new object[] { "de-DE", "3,215", 3.215m },
new object[] { "de-DE", "3.215", 3215m },

new object[] { null, "1", 1m },
new object[] { null, "-42", -42m },
new object[] { null, "3,215", 3215m },
new object[] { null, "3.215", 3.215m }
new object[] {"de-DE", "1", 1m},
new object[] {"de-DE", "-42", -42m},
new object[] {"de-DE", "3,215", 3.215m},
new object[] {"de-DE", "3.215", 3215m},

new object[] {null, "1", 1m},
new object[] {null, "-42", -42m},
new object[] {null, "3,215", 3215m},
new object[] {null, "3.215", 3.215m}
};
}

Expand All @@ -48,23 +48,23 @@ public static object[][] Floats()
{
return new object[][]
{
new object[] { "de-DE", "1", 1f },
new object[] { "de-DE", "-42", -42f },
new object[] { "de-DE", "3,215", 3.215f },
new object[] { "de-DE", "3.215", 3215f },
new object[] { "de-DE", "1,2345E-4", 0.00012345f },
new object[] { "de-DE", "1,2345e-4", 0.00012345f },
new object[] { "de-DE", "1,2345E4", 12345d },
new object[] { "de-DE", "1,2345e4", 12345d },

new object[] { null, "1", 1f },
new object[] { null, "-42", -42f },
new object[] { null, "3,215", 3215f },
new object[] { null, "3.215", 3.215f },
new object[] { null, "1.2345E-4", 0.00012345f },
new object[] { null, "1.2345e-4", 0.00012345f },
new object[] { null, "1.2345E4", 12345f },
new object[] { null, "1.2345e4", 12345f }
new object[] {"de-DE", "1", 1f},
new object[] {"de-DE", "-42", -42f},
new object[] {"de-DE", "3,215", 3.215f},
new object[] {"de-DE", "3.215", 3215f},
new object[] {"de-DE", "1,2345E-4", 0.00012345f},
new object[] {"de-DE", "1,2345e-4", 0.00012345f},
new object[] {"de-DE", "1,2345E4", 12345d},
new object[] {"de-DE", "1,2345e4", 12345d},

new object[] {null, "1", 1f},
new object[] {null, "-42", -42f},
new object[] {null, "3,215", 3215f},
new object[] {null, "3.215", 3.215f},
new object[] {null, "1.2345E-4", 0.00012345f},
new object[] {null, "1.2345e-4", 0.00012345f},
new object[] {null, "1.2345E4", 12345f},
new object[] {null, "1.2345e4", 12345f}
};
}

Expand All @@ -89,23 +89,23 @@ public static IEnumerable<object[]> Doubles()
{
return new object[][]
{
new object[] { "de-DE", "1", 1d },
new object[] { "de-DE", "-42", -42d },
new object[] { "de-DE", "3,215", 3.215d },
new object[] { "de-DE", "3.215", 3215d },
new object[] { "de-DE", "1,2345E-4", 0.00012345d },
new object[] { "de-DE", "1,2345e-4", 0.00012345d },
new object[] { "de-DE", "1,2345E4", 12345d },
new object[] { "de-DE", "1,2345e4", 12345d },

new object[] { null, "1", 1d },
new object[] { null, "-42", -42d },
new object[] { null, "3,215", 3215d },
new object[] { null, "3.215", 3.215d },
new object[] { null, "1.2345E-4", 0.00012345d },
new object[] { null, "1.2345e-4", 0.00012345d },
new object[] { null, "1.2345E4", 12345d },
new object[] { null, "1.2345e4", 12345d }
new object[] {"de-DE", "1", 1d},
new object[] {"de-DE", "-42", -42d},
new object[] {"de-DE", "3,215", 3.215d},
new object[] {"de-DE", "3.215", 3215d},
new object[] {"de-DE", "1,2345E-4", 0.00012345d},
new object[] {"de-DE", "1,2345e-4", 0.00012345d},
new object[] {"de-DE", "1,2345E4", 12345d},
new object[] {"de-DE", "1,2345e4", 12345d},

new object[] {null, "1", 1d},
new object[] {null, "-42", -42d},
new object[] {null, "3,215", 3215d},
new object[] {null, "3.215", 3.215d},
new object[] {null, "1.2345E-4", 0.00012345d},
new object[] {null, "1.2345e-4", 0.00012345d},
new object[] {null, "1.2345E4", 12345d},
new object[] {null, "1.2345e4", 12345d}
};
}

Expand Down Expand Up @@ -152,5 +152,53 @@ public void NumberParser_ParseIntegerLiteral(string text, double expected)
// Assert
result.Value.Should().Be(expected);
}

[Theory]
[InlineData("42", 'm', 42)]
[InlineData("-42", 'm', -42)]
[InlineData("42m", 'm', 42)]
[InlineData("-42m", 'm', -42)]
public void NumberParser_ParseDecimalLiteral(string text, char qualifier, decimal expected)
{
// Arrange

// Act
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;

// Assert
result!.Value.Should().Be(expected);
}

[Theory]
[InlineData("42", 'd', 42)]
[InlineData("-42", 'd', -42)]
[InlineData("42d", 'd', 42)]
[InlineData("-42d", 'd', -42)]
public void NumberParser_ParseDoubleLiteral(string text, char qualifier, double expected)
{
// Arrange

// Act
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;

// Assert
result!.Value.Should().Be(expected);
}

[Theory]
[InlineData("42", 'f', 42)]
[InlineData("-42", 'f', -42)]
[InlineData("42f", 'f', 42)]
[InlineData("-42f", 'f', -42)]
public void NumberParser_ParseFloatLiteral(string text, char qualifier, float expected)
{
// Arrange

// Act
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;

// Assert
result!.Value.Should().Be(expected);
}
}
}

0 comments on commit d14b76e

Please sign in to comment.