Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions src/System.Linq.Dynamic.Core/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ interface ILogicalSignatures
void F(bool? x, bool? y);
}

interface IShiftSignatures
{
void F(int x, int y);
void F(uint x, int y);
void F(long x, int y);
void F(ulong x, int y);
void F(int? x, int y);
void F(uint? x, int y);
void F(long? x, int y);
void F(ulong? x, int y);
void F(int x, int? y);
void F(uint x, int? y);
void F(long x, int? y);
void F(ulong x, int? y);
void F(int? x, int? y);
void F(uint? x, int? y);
void F(long? x, int? y);
void F(ulong? x, int? y);
}

interface IArithmeticSignatures
{
void F(int x, int y);
Expand Down Expand Up @@ -739,11 +759,11 @@ Expression ParseShiftOperator()
switch (op.Id)
{
case TokenId.DoubleLessThan:
CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.Text, ref left, ref right, op.Pos);
CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
left = Expression.LeftShift(left, right);
break;
case TokenId.DoubleGreaterThan:
CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.Text, ref left, ref right, op.Pos);
CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
left = Expression.RightShift(left, right);
break;
}
Expand Down
23 changes: 19 additions & 4 deletions test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -787,20 +787,35 @@ public void ExpressionTests_Select_ExpandoObjects()

[Fact]
public void ExpressionTests_Shift()
{
ExpressionTests_ShiftInternal<sbyte, int>();
ExpressionTests_ShiftInternal<byte, int>();
ExpressionTests_ShiftInternal<short, int>();
ExpressionTests_ShiftInternal<ushort, int>();
ExpressionTests_ShiftInternal<int, int>();
ExpressionTests_ShiftInternal<uint, uint>();
ExpressionTests_ShiftInternal<long, long>();
ExpressionTests_ShiftInternal<ulong, ulong>();
}

private static void ExpressionTests_ShiftInternal<TItemType, TResult>()
{
//Arrange
var lst = new List<int> { 10, 20, 30 };
var lst = new[] { 10, 20, 30 }.Select(item => (TItemType)Convert.ChangeType(item, typeof(TItemType)));
var qry = lst.AsQueryable();
int? nullableShift = 2;

//Act
var result1 = qry.Select("it << 1");
var result2 = qry.Select("it >> 1");
var result3 = qry.Where("it << 2 = 80");
var result4 = qry.Where("it << @0 = 80", nullableShift);

//Assert
Assert.Equal(new object[] { 20, 40, 60 }, result1.Cast<object>().ToArray());
Assert.Equal(new object[] { 5, 10, 15 }, result2.Cast<object>().ToArray());
Assert.Equal(20, result3.Single());
Assert.Equal(new[] { 20, 40, 60 }.Select(item => Convert.ChangeType(item, typeof(TResult))).ToArray(), result1.Cast<object>().ToArray());
Assert.Equal(new[] { 5, 10, 15 }.Select(item => Convert.ChangeType(item, typeof(TResult))).ToArray(), result2.Cast<object>().ToArray());
Assert.Equal(Convert.ChangeType(20, typeof(TItemType)), result3.Single());
Assert.Equal(Convert.ChangeType(20, typeof(TItemType)), result4.Single());
}

[Fact]
Expand Down