From 0f2a444ff0c68cef32900b227b5d30094bc35d7d Mon Sep 17 00:00:00 2001 From: CodingSeb Date: Wed, 8 Jun 2022 09:27:27 +0200 Subject: [PATCH] Use ExceptionDispatchInfo to throw better exception (When BubbleExceptionContainer and TargetInvocationException (#138 and #124) --- .../CodingSeb.ExpressionEvaluator.csproj | 13 +++-- .../ExpressionEvaluator.cs | 51 +++++++++++++++---- TryWindow/MainWindow.xaml.cs | 5 +- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj b/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj index 8ad34bc..64ce61c 100644 --- a/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj +++ b/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj @@ -5,9 +5,9 @@ CodingSeb.ExpressionEvaluator A Simple Math and Pseudo C# Expression Evaluator in One C# File. Can also execute small C# like scripts Copyright © Coding Seb 2017 - 1.4.37.0 - 1.4.37.0 - 1.4.37.0 + 1.4.38.0 + 1.4.38.0 + 1.4.38.0 bin\$(Configuration)\ Coding Seb CodingSeb.ExpressionEvaluator @@ -19,7 +19,12 @@ https://github.com/codingseb/ExpressionEvaluator/blob/master/Icon.png?raw=true Icon.png false - * Correction of the explicit cast between primitive types and rounding numbers before (int)3.6 -> 4 now (int)3.6 -> 3 + * OptionInlineNamespacesEvaluationActive become OptionInlineNamespacesEvaluationRule and allow more possibilities with the addition of InlineNamespacesList + This option can now be one of those : + - InlineNamespacesEvaluationRule.AllowAll + - InlineNamespacesEvaluationRule.AllowOnlyInlineNamespacesList + - InlineNamespacesEvaluationRule.BlockOnlyInlineNamespacesList + - InlineNamespacesEvaluationRule.BlockAll LICENSE.md https://github.com/codingseb/ExpressionEvaluator true diff --git a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs index bf80299..bda43c5 100644 --- a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs +++ b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs @@ -1,6 +1,6 @@ /****************************************************************************************************** Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator) - Version : 1.4.37.0 + Version : 1.4.38.0 (if last digit (the forth) is not a zero, the version is an intermediate version and can be unstable) Author : Coding Seb @@ -16,6 +16,7 @@ using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; @@ -286,6 +287,8 @@ protected enum TryBlockEvaluatedState {ExpressionOperator.ConditionalAnd, (dynamic left, dynamic right) => { if ( left is BubbleExceptionContainer leftExceptionContainer) { + ExceptionDispatchInfo.Capture(leftExceptionContainer.Exception).Throw(); + // Will not go here but Resharper detect some errors because he does not know ExceptionDispatchInfo stuff. throw leftExceptionContainer.Exception; } else if (!left) @@ -294,6 +297,8 @@ protected enum TryBlockEvaluatedState } else if (right is BubbleExceptionContainer rightExceptionContainer) { + ExceptionDispatchInfo.Capture(rightExceptionContainer.Exception).Throw(); + // Will not go here but Resharper detect some errors because he does not know ExceptionDispatchInfo stuff. throw rightExceptionContainer.Exception; } else @@ -307,6 +312,8 @@ protected enum TryBlockEvaluatedState {ExpressionOperator.ConditionalOr, (dynamic left, dynamic right) => { if ( left is BubbleExceptionContainer leftExceptionContainer) { + ExceptionDispatchInfo.Capture(leftExceptionContainer.Exception).Throw(); + // Will not go here but Resharper detect some errors because he does not know ExceptionDispatchInfo stuff. throw leftExceptionContainer.Exception; } else if (left) @@ -315,6 +322,8 @@ protected enum TryBlockEvaluatedState } else if (right is BubbleExceptionContainer rightExceptionContainer) { + ExceptionDispatchInfo.Capture(rightExceptionContainer.Exception).Throw(); + // Will not go here but Resharper detect some errors because he does not know ExceptionDispatchInfo stuff. throw rightExceptionContainer.Exception; } else @@ -1129,7 +1138,14 @@ object ManageJumpStatementsOrExpressionEval(string expression) if (expression.StartsWith("throw ", StringComparisonForCasing)) { - throw Evaluate(expression.Remove(0, 6)) as Exception; + if (Evaluate(expression.Remove(0, 6)) is Exception exception) + { + ExceptionDispatchInfo.Capture(exception).Throw(); + } + else + { + throw new ExpressionEvaluatorSyntaxErrorException("throw keyword must be follow by an Exception instance"); + } } expression = returnKeywordRegex.Replace(expression, match => @@ -1595,7 +1611,8 @@ public object Evaluate(string expression) try { - ExpressionEvaluationEventArg expressionEvaluationEventArg = new ExpressionEvaluationEventArg(expression, this); + ExpressionEvaluationEventArg expressionEvaluationEventArg = + new ExpressionEvaluationEventArg(expression, this); ExpressionEvaluating?.Invoke(this, expressionEvaluationEventArg); @@ -1618,7 +1635,8 @@ public object Evaluate(string expression) if (!s.Trim().Equals(string.Empty)) { - throw new ExpressionEvaluatorSyntaxErrorException($"Invalid character [{(int)s[0]}:{s}]"); + throw new ExpressionEvaluatorSyntaxErrorException( + $"Invalid character [{(int)s[0]}:{s}]"); } } } @@ -1637,6 +1655,10 @@ public object Evaluate(string expression) return result; } + catch (TargetInvocationException exception) when (exception.InnerException != null) + { + ExceptionDispatchInfo.Capture(exception.InnerException).Throw(); + } finally { evaluationStackCount--; @@ -3088,7 +3110,9 @@ protected virtual bool EvaluateString(string expression, Stack stack, re object obj = Evaluate(innerExp.ToString()); if (obj is BubbleExceptionContainer bubbleExceptionContainer) - throw bubbleExceptionContainer.Exception; + { + ExceptionDispatchInfo.Capture(bubbleExceptionContainer.Exception).Throw(); + } resultString.Append(obj); } @@ -3283,7 +3307,8 @@ void EvaluateFirstPreviousUnaryOp(int j) { if (item is BubbleExceptionContainer bubbleExceptionContainer) { - throw bubbleExceptionContainer.Exception; //Throw the first occuring error + //Throw the first occuring error + ExceptionDispatchInfo.Capture(bubbleExceptionContainer.Exception).Throw(); } } throw new ExpressionEvaluatorSyntaxErrorException("Syntax error. Check that no operator is missing"); @@ -3291,7 +3316,7 @@ void EvaluateFirstPreviousUnaryOp(int j) else if (evaluationStackCount == 1 && stack.Peek() is BubbleExceptionContainer bubbleExceptionContainer) { //We reached the top level of the evaluation. So we want to throw the resulting exception. - throw bubbleExceptionContainer.Exception; + ExceptionDispatchInfo.Capture(bubbleExceptionContainer.Exception).Throw(); } return stack.Pop(); @@ -3364,7 +3389,9 @@ protected virtual object ManageKindOfAssignation(string expression, ref int inde } if (result is BubbleExceptionContainer exceptionContainer) - throw exceptionContainer.Exception; + { + ExceptionDispatchInfo.Capture(exceptionContainer.Exception).Throw(); + } if (stack != null) { @@ -3395,9 +3422,9 @@ protected virtual void AssignVariable(string varName, object value) { Variables[varName] = Convert.ChangeType(value, stronglyTypedVariable.Type); } - catch + catch(Exception exception) { - throw new InvalidCastException($"A object of type {typeToAssign} can not be cast implicitely in {stronglyTypedVariable.Type}"); + throw new InvalidCastException($"A object of type {typeToAssign} can not be cast implicitely in {stronglyTypedVariable.Type}", exception); } } } @@ -4117,8 +4144,10 @@ protected virtual Type GetTypeByFriendlyName(string typeName, string genericType } } } - catch (ExpressionEvaluatorSyntaxErrorException) + catch (ExpressionEvaluatorSyntaxErrorException exception) { + ExceptionDispatchInfo.Capture(exception).Throw(); + // Will not go here but Resharper detect some errors because he does not know ExceptionDispatchInfo stuff. throw; } catch { } diff --git a/TryWindow/MainWindow.xaml.cs b/TryWindow/MainWindow.xaml.cs index 0aeff2a..cce3215 100644 --- a/TryWindow/MainWindow.xaml.cs +++ b/TryWindow/MainWindow.xaml.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -94,11 +95,11 @@ private async void CalculateButton_Click(object sender, RoutedEventArgs e) if (exception == null) ResultTextBlock.Text = result; else - throw exception; + ExceptionDispatchInfo.Capture(exception).Throw(); } catch (Exception exception) { - ResultTextBlock.Text = exception.Message; + ResultTextBlock.Text = exception.Message + "\r\n" + exception.StackTrace; } ExecutionTimeTextBlock.Text = $"Execution time : {stopWatch.Elapsed}";