Skip to content

Commit 3fe78aa

Browse files
committed
Small refactor for better exception in ternary stuff
1 parent f8bda99 commit 3fe78aa

File tree

2 files changed

+43
-35
lines changed

2 files changed

+43
-35
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs

+36-27
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,10 @@ public void TypeTesting(string expression, Type type)
800800
[TestCase("ListOfType(typeof(int), 1,2,3 )[0]", ExpectedResult = 1, Category = "Standard Functions,ListOfType Function,Indexing")]
801801
[TestCase("ListOfType(typeof(int), 1,2,3 )[1]", ExpectedResult = 2, Category = "Standard Functions,ListOfType Function,Indexing")]
802802
[TestCase("ListOfType(typeof(int), 1,2,3 )[2]", ExpectedResult = 3, Category = "Standard Functions,ListOfType Function,Indexing")]
803-
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\" ).GetType()", ExpectedResult = typeof(List<string>), Category = "Standard Functions,ListOfType Function,Instance Property")]
804-
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\" ).Count", ExpectedResult = 2, Category = "Standard Functions,ListOfType Function,Instance Property")]
805-
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\" )[0]", ExpectedResult = "hello", Category = "Standard Functions,ListOfType Function,Indexing")]
806-
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\" )[1]", ExpectedResult = "Test", Category = "Standard Functions,ListOfType Function,Indexing")]
803+
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\").GetType()", ExpectedResult = typeof(List<string>), Category = "Standard Functions,ListOfType Function,Instance Property")]
804+
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\").Count", ExpectedResult = 2, Category = "Standard Functions,ListOfType Function,Instance Property")]
805+
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\")[0]", ExpectedResult = "hello", Category = "Standard Functions,ListOfType Function,Indexing")]
806+
[TestCase("ListOfType(typeof(string), \"hello\",\"Test\")[1]", ExpectedResult = "Test", Category = "Standard Functions,ListOfType Function,Indexing")]
807807
#endregion
808808

809809
#region Log Function
@@ -1111,27 +1111,16 @@ public static IEnumerable<TestCaseData> TestCasesForWithCustomVariablesExpressio
11111111
yield return new TestCaseData("nullVar?[1][3]", onInstanceVariables, true).SetCategory("Instance Property,Null Conditional indexing").Returns(null);
11121112
yield return new TestCaseData("simpleArray2?[3]?.Trim()", onInstanceVariables, true).SetCategory("Instance Property,Null Conditional indexing").Returns(null);
11131113

1114-
yield return new TestCaseData( "false && 1/0 == 0", onInstanceVariables, true ).SetCategory( "Instance Property,And Conditional" ).Returns( false );
1115-
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.StartsWith(\"ABC\")", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1116-
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.StartsWith(\"ABC\")", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1117-
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.StartsWith(\"ABC\") == false", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1118-
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.StartsWith(\"ABC\") == false", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1119-
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.Length < 2", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1120-
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.Length < 2", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1121-
yield return new TestCaseData( "true || 1/0 == 0", onInstanceVariables, true ).SetCategory( "Instance Property,Or Conditional" ).Returns( true );
1122-
yield return new TestCaseData( "false && true || true", onInstanceVariables, true ).SetCategory( "Instance Property,Or Conditional,And Conditional,Precedence check" ).Returns( true );
1123-
yield return new TestCaseData( "true || true && false", onInstanceVariables, true ).SetCategory( "Instance Property,Or Conditional,And Conditional,Precedence check" ).Returns( true );
1124-
1125-
yield return new TestCaseData("simpleInt.ToString()", onInstanceVariables, true).SetCategory("Instance Method").Returns("42");
1126-
yield return new TestCaseData("simpleInt.ToString().Length", onInstanceVariables, true).SetCategory("Instance Method,Instance Property").Returns(2);
1127-
11281114
yield return new TestCaseData("customObject.IntProperty", onInstanceVariables, true).SetCategory("Instance Property").Returns(25);
11291115
yield return new TestCaseData("customObject?.IntProperty", onInstanceVariables, true).SetCategory("Instance Property").Returns(25);
11301116
yield return new TestCaseData("customObject.intField", onInstanceVariables, true).SetCategory("Instance Field").Returns(12);
11311117
yield return new TestCaseData("customObject?.intField", onInstanceVariables, true).SetCategory("Instance Field").Returns(12);
11321118
yield return new TestCaseData("customObject.Add3To(9)", onInstanceVariables, true).SetCategory("Instance Method").Returns(12);
11331119
yield return new TestCaseData("customObject?.Add3To(5)", onInstanceVariables, true).SetCategory("Instance Method").Returns(8);
11341120

1121+
yield return new TestCaseData("simpleInt.ToString()", onInstanceVariables, true).SetCategory("Instance Method").Returns("42");
1122+
yield return new TestCaseData("simpleInt.ToString().Length", onInstanceVariables, true).SetCategory("Instance Method,Instance Property").Returns(2);
1123+
11351124
yield return new TestCaseData("ClassForTest1.StaticIntProperty", onInstanceVariables, true).SetCategory("Static Property").Returns(67);
11361125
yield return new TestCaseData("ClassForTest1.StaticStringMethod(\"Bob\")", onInstanceVariables, true).SetCategory("Static Method").Returns("Hello Bob");
11371126

@@ -1153,10 +1142,24 @@ public static IEnumerable<TestCaseData> TestCasesForWithCustomVariablesExpressio
11531142
yield return new TestCaseData("simpleInt--", onInstanceVariables, true).SetCategory("Postfix operator, --").Returns(42);
11541143
yield return new TestCaseData("simpleInt-- - simpleInt", onInstanceVariables, true).SetCategory("Postfix operator, --").Returns(1);
11551144

1156-
yield return new TestCaseData("false && 1/0>0", onInstanceVariables, true ).SetCategory( "Conditional And, negative left operand (should respect left associativity)" ).Returns( false );
1157-
yield return new TestCaseData("true || 1/0>0", onInstanceVariables, true ).SetCategory( "Conditional Or, positive left operand (should respect left associativity)" ).Returns( true );
1158-
yield return new TestCaseData("false && (true && 1/0>0)", onInstanceVariables, true ).SetCategory( "Conditional And, negative left operand (should respect left associativity)" ).Returns( false );
1159-
yield return new TestCaseData("true || (false || 1/0>0)", onInstanceVariables, true ).SetCategory( "Conditional Or, positive left operand (should respect left associativity)" ).Returns( true );
1145+
yield return new TestCaseData("false && 1/0>0", onInstanceVariables, true).SetCategory("Conditional And, negative left operand (should respect left associativity)").Returns(false);
1146+
yield return new TestCaseData("true || 1/0>0", onInstanceVariables, true).SetCategory("Conditional Or, positive left operand (should respect left associativity)").Returns(true);
1147+
yield return new TestCaseData("false && (true && 1/0>0)", onInstanceVariables, true).SetCategory("Conditional And, negative left operand (should respect left associativity)").Returns(false);
1148+
yield return new TestCaseData("true || (false || 1/0>0)", onInstanceVariables, true).SetCategory("Conditional Or, positive left operand (should respect left associativity)").Returns(true);
1149+
yield return new TestCaseData("false && 1/0 == 0", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1150+
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.StartsWith(\"ABC\")", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1151+
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.StartsWith(\"ABC\")", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1152+
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.StartsWith(\"ABC\") == false", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1153+
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.StartsWith(\"ABC\") == false", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1154+
yield return new TestCaseData("!string.IsNullOrEmpty(nullVar) && nullVar.Length < 2", onInstanceVariables, true).SetCategory("Instance Property,And Conditional").Returns(false);
1155+
yield return new TestCaseData("string.IsNullOrEmpty(nullVar) || nullVar.Length < 2", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1156+
yield return new TestCaseData("true || 1/0 == 0", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional").Returns(true);
1157+
yield return new TestCaseData("false && true || true", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional,And Conditional,Precedence check").Returns(true);
1158+
yield return new TestCaseData("true || true && false", onInstanceVariables, true).SetCategory("Instance Property,Or Conditional,And Conditional,Precedence check").Returns(true);
1159+
yield return new TestCaseData("false && nullVar.What ? nullVar.Text : \"Hello\"", onInstanceVariables, true).SetCategory("Instance Property,Ternary operator, And Conditional").Returns("Hello");
1160+
yield return new TestCaseData("false && (false && nullVar.What ? nullVar.boolValue : true) ? nullVar.Text : \"Hello\"", onInstanceVariables, true).SetCategory("Instance Property,Ternary operator, And Conditional").Returns("Hello");
1161+
1162+
11601163
#endregion
11611164

11621165
#region Delegates as a variable
@@ -1442,7 +1445,8 @@ public static IEnumerable<TestCaseData> TestCasesForExceptionThrowingEvaluation
14421445
evaluator = new ExpressionEvaluator(new Dictionary<string, object>
14431446
{
14441447
{ "P1var", "P1" },
1445-
{ "myObj", new ClassForTest1() }
1448+
{ "myObj", new ClassForTest1() },
1449+
{ "nullVar", null },
14461450
});
14471451

14481452
evaluator.PreEvaluateVariable += (sender, e) =>
@@ -1462,10 +1466,15 @@ public static IEnumerable<TestCaseData> TestCasesForExceptionThrowingEvaluation
14621466
yield return new TestCaseData(evaluator, "myObj.PropertyThatWillFailed", typeof(ExpressionEvaluatorSyntaxErrorException)).SetCategory("OnTheFly canceled Var");
14631467
yield return new TestCaseData(evaluator, "myObj.Add3To(5)", typeof(ExpressionEvaluatorSyntaxErrorException)).SetCategory("OnTheFly canceled Func");
14641468
yield return new TestCaseData(evaluator, "Abs(-5)", typeof(ExpressionEvaluatorSyntaxErrorException)).SetCategory("OnTheFly canceled Func");
1465-
yield return new TestCaseData(evaluator, "true && 1/0>0",typeof(DivideByZeroException) ).SetCategory( "Conditional And, positive left operand (should lead to exception)" );
1466-
yield return new TestCaseData(evaluator, "false || 1/0>0", typeof( DivideByZeroException ) ).SetCategory( "Conditional Or, positive left operand (should lead to exception associativity)" );
1467-
yield return new TestCaseData(evaluator, "true && (true && 1/0>0)", typeof( DivideByZeroException ) ).SetCategory( "Conditional And, positive left operand (should lead to exception)" );
1468-
yield return new TestCaseData(evaluator, "false || (false || 1/0>0)", typeof( DivideByZeroException ) ).SetCategory( "Conditional Or, positive left operand (should lead to exception associativity)" );
1469+
#endregion
1470+
1471+
#region Bugs corrections
1472+
1473+
yield return new TestCaseData(evaluator, "true && 1/0>0", typeof(DivideByZeroException)).SetCategory("Conditional And, positive left operand (should lead to exception)");
1474+
yield return new TestCaseData(evaluator, "false || 1/0>0", typeof(DivideByZeroException)).SetCategory("Conditional Or, positive left operand (should lead to exception associativity)");
1475+
yield return new TestCaseData(evaluator, "true && (true && 1/0>0)", typeof(DivideByZeroException)).SetCategory("Conditional And, positive left operand (should lead to exception)");
1476+
yield return new TestCaseData(evaluator, "false || (false || 1/0>0)", typeof(DivideByZeroException)).SetCategory("Conditional Or, positive left operand (should lead to exception associativity)");
1477+
14691478
#endregion
14701479
}
14711480
}

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1541,14 +1541,7 @@ public object Evaluate(string expression)
15411541
}
15421542
}
15431543

1544-
var res = ProcessStack(stack);
1545-
if (evaluationStackCount == 1 && res is BubbleExceptionContainer bubbleExceptionContainer)
1546-
{
1547-
//We reached the top level of the evaluation. So we want to throw the resulting exception.
1548-
throw bubbleExceptionContainer.Exception;
1549-
}
1550-
1551-
return res;
1544+
return ProcessStack(stack);
15521545
}
15531546
finally
15541547
{
@@ -2966,6 +2959,12 @@ protected virtual object ProcessStack(Stack<object> stack)
29662959
}
29672960
throw new ExpressionEvaluatorSyntaxErrorException("Syntax error. Check that no operator is missing");
29682961
}
2962+
else if (evaluationStackCount == 1 && stack.Peek() is BubbleExceptionContainer bubbleExceptionContainer)
2963+
{
2964+
//We reached the top level of the evaluation. So we want to throw the resulting exception.
2965+
throw bubbleExceptionContainer.Exception;
2966+
}
2967+
29692968
return stack.Pop();
29702969
}
29712970

0 commit comments

Comments
 (0)