Skip to content

Commit d14b76e

Browse files
Fixed: Incorrect Handling of Qualifiers in ConstantExpressionHelper (#824)
* include ParseRealLiteral tests * Change ParseRealLiteral to remove literals before parsing * Merge master * NumberParserTests to split the tests NumberParser_Parse[Type]Literal
1 parent 1bd7a90 commit d14b76e

File tree

2 files changed

+112
-49
lines changed

2 files changed

+112
-49
lines changed

src/System.Linq.Dynamic.Core/Parser/NumberParser.cs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Globalization;
1+
using System.Globalization;
22
using System.Linq.Dynamic.Core.Exceptions;
33
using System.Linq.Dynamic.Core.Validation;
44
using System.Linq.Expressions;
@@ -161,19 +161,34 @@ public Expression ParseIntegerLiteral(int tokenPosition, string text)
161161
/// </summary>
162162
public Expression ParseRealLiteral(string text, char qualifier, bool stripQualifier)
163163
{
164+
if (stripQualifier)
165+
{
166+
var pos = text.Length - 1;
167+
while (pos >= 0 && Qualifiers.Contains(text[pos]))
168+
{
169+
pos--;
170+
}
171+
172+
if (pos < text.Length - 1)
173+
{
174+
qualifier = text[pos + 1];
175+
text = text.Substring(0, pos + 1);
176+
}
177+
}
178+
164179
switch (qualifier)
165180
{
166181
case 'f':
167182
case 'F':
168-
return _constantExpressionHelper.CreateLiteral(ParseNumber(stripQualifier ? text.Substring(0, text.Length - 1) : text, typeof(float))!, text);
183+
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(float))!, text);
169184

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

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

178193
default:
179194
return _constantExpressionHelper.CreateLiteral(ParseNumber(text, typeof(double))!, text);
@@ -298,4 +313,4 @@ private Expression ParseAsBinary(int tokenPosition, string text, bool isNegative
298313
throw new ParseException(string.Format(_culture, Res.InvalidBinaryIntegerLiteral, text), tokenPosition);
299314
}
300315
}
301-
}
316+
}

test/System.Linq.Dynamic.Core.Tests/Parser/NumberParserTests.cs

+92-44
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using FluentAssertions;
1+
using FluentAssertions;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.Linq.Dynamic.Core.Parser;
@@ -15,15 +15,15 @@ public static object[][] Decimals()
1515
{
1616
return new object[][]
1717
{
18-
new object[] { "de-DE", "1", 1m },
19-
new object[] { "de-DE", "-42", -42m },
20-
new object[] { "de-DE", "3,215", 3.215m },
21-
new object[] { "de-DE", "3.215", 3215m },
22-
23-
new object[] { null, "1", 1m },
24-
new object[] { null, "-42", -42m },
25-
new object[] { null, "3,215", 3215m },
26-
new object[] { null, "3.215", 3.215m }
18+
new object[] {"de-DE", "1", 1m},
19+
new object[] {"de-DE", "-42", -42m},
20+
new object[] {"de-DE", "3,215", 3.215m},
21+
new object[] {"de-DE", "3.215", 3215m},
22+
23+
new object[] {null, "1", 1m},
24+
new object[] {null, "-42", -42m},
25+
new object[] {null, "3,215", 3215m},
26+
new object[] {null, "3.215", 3.215m}
2727
};
2828
}
2929

@@ -48,23 +48,23 @@ public static object[][] Floats()
4848
{
4949
return new object[][]
5050
{
51-
new object[] { "de-DE", "1", 1f },
52-
new object[] { "de-DE", "-42", -42f },
53-
new object[] { "de-DE", "3,215", 3.215f },
54-
new object[] { "de-DE", "3.215", 3215f },
55-
new object[] { "de-DE", "1,2345E-4", 0.00012345f },
56-
new object[] { "de-DE", "1,2345e-4", 0.00012345f },
57-
new object[] { "de-DE", "1,2345E4", 12345d },
58-
new object[] { "de-DE", "1,2345e4", 12345d },
59-
60-
new object[] { null, "1", 1f },
61-
new object[] { null, "-42", -42f },
62-
new object[] { null, "3,215", 3215f },
63-
new object[] { null, "3.215", 3.215f },
64-
new object[] { null, "1.2345E-4", 0.00012345f },
65-
new object[] { null, "1.2345e-4", 0.00012345f },
66-
new object[] { null, "1.2345E4", 12345f },
67-
new object[] { null, "1.2345e4", 12345f }
51+
new object[] {"de-DE", "1", 1f},
52+
new object[] {"de-DE", "-42", -42f},
53+
new object[] {"de-DE", "3,215", 3.215f},
54+
new object[] {"de-DE", "3.215", 3215f},
55+
new object[] {"de-DE", "1,2345E-4", 0.00012345f},
56+
new object[] {"de-DE", "1,2345e-4", 0.00012345f},
57+
new object[] {"de-DE", "1,2345E4", 12345d},
58+
new object[] {"de-DE", "1,2345e4", 12345d},
59+
60+
new object[] {null, "1", 1f},
61+
new object[] {null, "-42", -42f},
62+
new object[] {null, "3,215", 3215f},
63+
new object[] {null, "3.215", 3.215f},
64+
new object[] {null, "1.2345E-4", 0.00012345f},
65+
new object[] {null, "1.2345e-4", 0.00012345f},
66+
new object[] {null, "1.2345E4", 12345f},
67+
new object[] {null, "1.2345e4", 12345f}
6868
};
6969
}
7070

@@ -89,23 +89,23 @@ public static IEnumerable<object[]> Doubles()
8989
{
9090
return new object[][]
9191
{
92-
new object[] { "de-DE", "1", 1d },
93-
new object[] { "de-DE", "-42", -42d },
94-
new object[] { "de-DE", "3,215", 3.215d },
95-
new object[] { "de-DE", "3.215", 3215d },
96-
new object[] { "de-DE", "1,2345E-4", 0.00012345d },
97-
new object[] { "de-DE", "1,2345e-4", 0.00012345d },
98-
new object[] { "de-DE", "1,2345E4", 12345d },
99-
new object[] { "de-DE", "1,2345e4", 12345d },
100-
101-
new object[] { null, "1", 1d },
102-
new object[] { null, "-42", -42d },
103-
new object[] { null, "3,215", 3215d },
104-
new object[] { null, "3.215", 3.215d },
105-
new object[] { null, "1.2345E-4", 0.00012345d },
106-
new object[] { null, "1.2345e-4", 0.00012345d },
107-
new object[] { null, "1.2345E4", 12345d },
108-
new object[] { null, "1.2345e4", 12345d }
92+
new object[] {"de-DE", "1", 1d},
93+
new object[] {"de-DE", "-42", -42d},
94+
new object[] {"de-DE", "3,215", 3.215d},
95+
new object[] {"de-DE", "3.215", 3215d},
96+
new object[] {"de-DE", "1,2345E-4", 0.00012345d},
97+
new object[] {"de-DE", "1,2345e-4", 0.00012345d},
98+
new object[] {"de-DE", "1,2345E4", 12345d},
99+
new object[] {"de-DE", "1,2345e4", 12345d},
100+
101+
new object[] {null, "1", 1d},
102+
new object[] {null, "-42", -42d},
103+
new object[] {null, "3,215", 3215d},
104+
new object[] {null, "3.215", 3.215d},
105+
new object[] {null, "1.2345E-4", 0.00012345d},
106+
new object[] {null, "1.2345e-4", 0.00012345d},
107+
new object[] {null, "1.2345E4", 12345d},
108+
new object[] {null, "1.2345e4", 12345d}
109109
};
110110
}
111111

@@ -152,5 +152,53 @@ public void NumberParser_ParseIntegerLiteral(string text, double expected)
152152
// Assert
153153
result.Value.Should().Be(expected);
154154
}
155+
156+
[Theory]
157+
[InlineData("42", 'm', 42)]
158+
[InlineData("-42", 'm', -42)]
159+
[InlineData("42m", 'm', 42)]
160+
[InlineData("-42m", 'm', -42)]
161+
public void NumberParser_ParseDecimalLiteral(string text, char qualifier, decimal expected)
162+
{
163+
// Arrange
164+
165+
// Act
166+
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;
167+
168+
// Assert
169+
result!.Value.Should().Be(expected);
170+
}
171+
172+
[Theory]
173+
[InlineData("42", 'd', 42)]
174+
[InlineData("-42", 'd', -42)]
175+
[InlineData("42d", 'd', 42)]
176+
[InlineData("-42d", 'd', -42)]
177+
public void NumberParser_ParseDoubleLiteral(string text, char qualifier, double expected)
178+
{
179+
// Arrange
180+
181+
// Act
182+
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;
183+
184+
// Assert
185+
result!.Value.Should().Be(expected);
186+
}
187+
188+
[Theory]
189+
[InlineData("42", 'f', 42)]
190+
[InlineData("-42", 'f', -42)]
191+
[InlineData("42f", 'f', 42)]
192+
[InlineData("-42f", 'f', -42)]
193+
public void NumberParser_ParseFloatLiteral(string text, char qualifier, float expected)
194+
{
195+
// Arrange
196+
197+
// Act
198+
var result = new NumberParser(_parsingConfig).ParseRealLiteral(text, qualifier, true) as ConstantExpression;
199+
200+
// Assert
201+
result!.Value.Should().Be(expected);
202+
}
155203
}
156204
}

0 commit comments

Comments
 (0)