Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case insensitivity option is now properly used inside lambda expressions #222

Merged
merged 1 commit into from
Jan 20, 2022
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
5 changes: 3 additions & 2 deletions src/DynamicExpresso.Core/ParserArguments.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DynamicExpresso.Parsing;
using DynamicExpresso.Parsing;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -108,7 +108,8 @@ public bool TryGetParameters(string name, out ParameterExpression expression)

public IEnumerable<MethodInfo> GetExtensionMethods(string methodName)
{
return Settings.ExtensionMethods.Where(p => p.Name == methodName);
var comparer = Settings.KeyComparer;
return Settings.ExtensionMethods.Where(p => comparer.Equals(p.Name, methodName));
}
}
}
4 changes: 2 additions & 2 deletions src/DynamicExpresso.Core/Parsing/ParserSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public ParserSettings(bool caseInsensitive, bool lateBindObject)

private ParserSettings(ParserSettings other) : this(other.CaseInsensitive, other.LateBindObject)
{
_knownTypes = new Dictionary<string, ReferenceType>(other._knownTypes);
_identifiers = new Dictionary<string, Identifier>(other._identifiers);
_knownTypes = new Dictionary<string, ReferenceType>(other._knownTypes, other._knownTypes.Comparer);
_identifiers = new Dictionary<string, Identifier>(other._identifiers, other._identifiers.Comparer);
_extensionMethods = new HashSet<MethodInfo>(other._extensionMethods);

AssignmentOperators = other.AssignmentOperators;
Expand Down
49 changes: 45 additions & 4 deletions test/DynamicExpresso.UnitTest/GithubIssues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ public void GitHub_Issue_203()
var listInt = target.Eval<List<int>>("Utils.Array(list)", new Parameter("list", list));
Assert.AreEqual(Utils.Array(list), listInt);
}
[Test]

[Test]
public void GitHub_Issue_205_Property_on_nullable()
{
var interpreter = new Interpreter();
Expand Down Expand Up @@ -461,15 +461,56 @@ public void GitHub_Issue_217()
Assert.AreEqual(2, target.Eval("Utils.Any(null)"));
}

public class Utils
[Test]
public void GitHub_Issue_221_Case_insensitivity()
{
var interpreter = new Interpreter(InterpreterOptions.LambdaExpressions | InterpreterOptions.DefaultCaseInsensitive)
.Reference(typeof(DateTimeOffset))
.Reference(typeof(GithubIssuesTestExtensionsMethods))
.SetFunction("Now", (Func<DateTimeOffset>)(() => DateTimeOffset.UtcNow))
.SetVariable("List", new List<DateTimeOffset> { DateTimeOffset.UtcNow.AddDays(5) })
.SetVariable("DateInThePast", DateTimeOffset.UtcNow.AddDays(-5));

// actual case
Assert.IsTrue(interpreter.Eval<bool>("List.Any(x => x > Now())"));
Assert.IsTrue(interpreter.Eval<bool>("List.Any(x => x is DateTimeOffset)"));
Assert.IsFalse(interpreter.Eval<bool>("DateInThePast.IsInFuture()"));

// case insensivity outside lambda expressions
Assert.IsFalse(interpreter.Eval<bool>("dateinthepast > now()")); // identifier
Assert.IsTrue(interpreter.Eval<bool>("dateinthepast is datetimeoffset)")); // known type
Assert.IsFalse(interpreter.Eval<bool>("dateinthepast.isinfuture()")); // extension method

// ensure the case insensitivity option is also used in the lambda expression
Assert.IsTrue(interpreter.Eval<bool>("list.Any(x => x > now())")); // identifier
Assert.IsTrue(interpreter.Eval<bool>("list.Any(x => x is datetimeoffset)")); // known type
Assert.IsTrue(interpreter.Eval<bool>("list.Any(x => x.isinfuture())")); // extension method
}

[Test]
public void GitHub_Issue_221_Reflection_not_allowed()
{
var interpreter = new Interpreter(InterpreterOptions.LambdaExpressions | InterpreterOptions.Default)
.SetVariable("list", new List<Type> { typeof(double) });

Assert.Throws<ReflectionNotAllowedException>(() => interpreter.Parse("typeof(double).GetMethods()"));
Assert.Throws<ReflectionNotAllowedException>(() => interpreter.Parse("list.SelectMany(t => t.GetMethods())"));
}


public static class Utils
{
public static List<T> Array<T>(IEnumerable<T> collection) => new List<T>(collection);
public static List<dynamic> Array(params dynamic[] array) => Array((IEnumerable<dynamic>)array);
public static IEnumerable<dynamic> Select<TSource>(IEnumerable<TSource> collection, string expression) => new List<dynamic>();
public static IEnumerable<dynamic> Select<TSource>(IEnumerable<TSource> collection, string expression) => new List<dynamic>();
public static IEnumerable<dynamic> Select(IEnumerable collection, string expression) => new List<dynamic>();
public static int Any<T>(IEnumerable<T> collection) => 1;
public static int Any(IEnumerable collection) => 2;
}
}

internal static class GithubIssuesTestExtensionsMethods
{
public static bool IsInFuture(this DateTimeOffset date) => date > DateTimeOffset.UtcNow;
}
}