From f0ff2c2a3aef6d0fae002c8a1b4f9b57e8e83679 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 30 Oct 2024 20:09:19 +0100 Subject: [PATCH] Refactor method calls and add new tests Modified `#if` directive in `NotNullWhenAttribute.cs` to include `NETSTANDARD2_0` and remove `NETSTANDARD1_3_OR_GREATER`. Updated `GenerateStaticMethodCall` in `ExpressionHelper.cs` to use `TryGetStaticMethod` instead of `GetStaticMethod`, throwing an `ArgumentException` if the method is not found. Replaced `GetStaticMethod` with `TryGetStaticMethod` in `ExpressionHelper.cs`. Added `MyView` class with nullable `Properties` dictionary to `ExpressionParserTests.cs`. Added `Parse_InvalidExpressionShouldThrowArgumentException` test to verify `ArgumentException` is thrown for invalid expressions. --- .../CodeAnalysis/NotNullWhenAttribute.cs | 2 +- .../Parser/ExpressionHelper.cs | 17 ++++++++--------- .../Parser/ExpressionParserTests.cs | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/System.Linq.Dynamic.Core/Compatibility/CodeAnalysis/NotNullWhenAttribute.cs b/src/System.Linq.Dynamic.Core/Compatibility/CodeAnalysis/NotNullWhenAttribute.cs index 676ef898..64c73cb6 100644 --- a/src/System.Linq.Dynamic.Core/Compatibility/CodeAnalysis/NotNullWhenAttribute.cs +++ b/src/System.Linq.Dynamic.Core/Compatibility/CodeAnalysis/NotNullWhenAttribute.cs @@ -22,7 +22,7 @@ // SOFTWARE. #endregion -#if NETSTANDARD1_3_OR_GREATER || NET35 || NET40 || NET45 || NET452 || NET46 || NETCOREAPP2_1 || UAP10_0 +#if NETSTANDARD1_3 || NETSTANDARD2_0 || NET35 || NET40 || NET45 || NET452 || NET46 || NETCOREAPP2_1 || UAP10_0 // ReSharper disable once CheckNamespace namespace System.Diagnostics.CodeAnalysis; diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs index f09ea38a..cc1ef839 100644 --- a/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs +++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs @@ -477,7 +477,11 @@ private void TryConvertTypes(ref Expression left, ref Expression right) private static Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right) { - var methodInfo = GetStaticMethod(methodName, left, right); + if (!TryGetStaticMethod(methodName, left, right, out var methodInfo)) + { + throw new ArgumentException($"Method '{methodName}' not found on type '{left.Type}' or '{right.Type}'"); + } + var parameters = methodInfo.GetParameters(); var parameterTypeLeft = parameters[0].ParameterType; var parameterTypeRight = parameters[1].ParameterType; @@ -495,15 +499,10 @@ private static Expression GenerateStaticMethodCall(string methodName, Expression return Expression.Call(null, methodInfo, [left, right]); } - private static MethodInfo GetStaticMethod(string methodName, Expression left, Expression right) + private static bool TryGetStaticMethod(string methodName, Expression left, Expression right, [NotNullWhen(true)] out MethodInfo? methodInfo) { - var methodInfo = left.Type.GetMethod(methodName, [left.Type, right.Type]); - if (methodInfo == null) - { - methodInfo = right.Type.GetMethod(methodName, [left.Type, right.Type])!; - } - - return methodInfo; + methodInfo = left.Type.GetMethod(methodName, [left.Type, right.Type]) ?? right.Type.GetMethod(methodName, [left.Type, right.Type]); + return methodInfo != null; } private static Expression? GetMethodCallExpression(MethodCallExpression methodCallExpression) diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs index d5bf0db3..22283e6b 100644 --- a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs @@ -27,6 +27,10 @@ public enum ExampleFlags D = 8, }; + public class MyView + { + public Dictionary? Properties { get; set; } + } public ExpressionParserTests() { @@ -421,8 +425,18 @@ public void Parse_StringConcat(string expression, string result) // Act var parsedExpression = parser.Parse(typeof(string)).ToString(); - + // Assert parsedExpression.Should().Be(result); } + + [Fact] + public void Parse_InvalidExpressionShouldThrowArgumentException() + { + // Arrange & Act + Action act = () => DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, "Properties[\"foo\"] > 2", Array.Empty()); + + // Assert + act.Should().Throw().WithMessage("Method 'Compare' not found on type 'System.String' or 'System.Int32'"); + } } \ No newline at end of file