diff --git a/src/DynamicExpresso.Core/Identifier.cs b/src/DynamicExpresso.Core/Identifier.cs index 85b95e16..b4dd799d 100644 --- a/src/DynamicExpresso.Core/Identifier.cs +++ b/src/DynamicExpresso.Core/Identifier.cs @@ -22,13 +22,13 @@ public Identifier(string name, Expression expression) } } - internal class FunctionIdentifier : Identifier + public class FunctionIdentifier : Identifier { - internal FunctionIdentifier(string name, Delegate value) : base(name, new MethodGroupExpression(value)) + public FunctionIdentifier(string name, Delegate value) : base(name, new MethodGroupExpression(value)) { } - internal void AddOverload(Delegate overload) + public void AddOverload(Delegate overload) { ((MethodGroupExpression)Expression).AddOverload(overload); } diff --git a/src/DynamicExpresso.Core/Parsing/Parser.cs b/src/DynamicExpresso.Core/Parsing/Parser.cs index a2fffa6c..b63ae101 100644 --- a/src/DynamicExpresso.Core/Parsing/Parser.cs +++ b/src/DynamicExpresso.Core/Parsing/Parser.cs @@ -524,7 +524,7 @@ public bool IsShiftOperator(out ExpressionType shiftType) // << could be a token, but is not for symmetry else if (_token.id == TokenId.LessThan && _parseChar == '<') { - NextToken(); // consume next < + NextToken(); // consume next < shiftType = ExpressionType.LeftShift; return true; } @@ -1019,7 +1019,7 @@ private Expression ParseIdentifier() { return ParseTypeKeyword(knownType); } - + // Working context implementation //if (it != null) // return ParseMemberAccess(null, it); @@ -1228,7 +1228,7 @@ private Expression ParseMethodGroupInvocation(MethodGroupExpression methodGroup, applicableMethods = FindBestMethod(candidates.Select(_ => _.Method), args); if (applicableMethods.Length == 0) - throw CreateParseException(errorPos, ErrorMessages.ArgsIncompatibleWithDelegate); + throw CreateParseException(errorPos, ErrorMessages.AmbiguousDelegateInvocation); if (applicableMethods.Length > 1) throw CreateParseException(errorPos, ErrorMessages.AmbiguousDelegateInvocation); @@ -1250,7 +1250,7 @@ private Type ParseKnownType() private bool TryParseKnownType(string name, out Type type) { - // if the type is unknown, we need to restart parsing + // if the type is unknown, we need to restart parsing var originalPos = _token.pos; _arguments.TryGetKnownType(name, out type); @@ -2362,7 +2362,7 @@ private static bool IsWritable(Expression expression) } case ExpressionType.Parameter: return true; - + } return false; @@ -2497,7 +2497,7 @@ private Expression GenerateGreaterThan(Expression left, Expression right) return GenerateBinary(ExpressionType.GreaterThan, left, right); } - + private Expression GenerateGreaterThanEqual(Expression left, Expression right) { @@ -3090,7 +3090,7 @@ private static Expression GenerateNullableTypeConversion(Expression expr) } /// - /// Expression that wraps over an interpreter. This is used when parsing a lambda expression + /// Expression that wraps over an interpreter. This is used when parsing a lambda expression /// definition, because we don't know the parameters type before resolution. /// private class InterpreterExpression : Expression diff --git a/test/DynamicExpresso.UnitTest/GithubIssues.cs b/test/DynamicExpresso.UnitTest/GithubIssues.cs index ba7e65d1..80411cbf 100644 --- a/test/DynamicExpresso.UnitTest/GithubIssues.cs +++ b/test/DynamicExpresso.UnitTest/GithubIssues.cs @@ -221,11 +221,40 @@ static bool GetGFunction2(string arg = null) Assert.Throws(() => interpreter.Eval("GFunction(arg)")); // there should be an ambiguous call exception, but GFunction1 is used - // because gFunc1.Method.GetParameters()[0].HasDefaultValue == true + // because gFunc1.Method.GetParameters()[0].HasDefaultValue == true // and gFunc2.Method.GetParameters()[0].HasDefaultValue == false Assert.False((bool)interpreter.Eval("GFunction()")); } + [Test] + public void Github_Issue_159() + { + // GetGFunction2 is defined inside the test function + static bool GetGFunction2(string arg = null) + { + return arg == null; + } + + GFunction gFunc1 = GetGFunction1; + GFunction gFunc2 = GetGFunction2; + + var interpreter = new Interpreter(); + interpreter.SetFunction("GFunction", gFunc1); + interpreter.SetFunction("GFunction", gFunc2); + interpreter.SetVariable("arg", "arg"); + + // ambiguous call + var exception = Assert.Throws(() => interpreter.Eval("GFunction(arg)")); + Assert.AreEqual("Ambiguous invocation of delegate (multiple overloads found) (at index 0).", exception.Message); + + interpreter = new Interpreter(); + interpreter.SetIdentifier(new FunctionIdentifier("GFunction", gFunc1)); + interpreter.SetIdentifier(new FunctionIdentifier("GFunction", gFunc2)); + interpreter.SetVariable("arg", "arg"); + + // normal call + Assert.False((bool)interpreter.Eval("GFunction(arg)")); + } #endif [Test] @@ -497,7 +526,6 @@ public void GitHub_Issue_221_Reflection_not_allowed() Assert.Throws(() => interpreter.Parse("list.SelectMany(t => t.GetMethods())")); } - public static class Utils { public static List Array(IEnumerable collection) => new List(collection);