diff --git a/src/Hyperbee.Json/Filters/Parser/FilterParser.cs b/src/Hyperbee.Json/Filters/Parser/FilterParser.cs index cac31577..ff9ba1a6 100644 --- a/src/Hyperbee.Json/Filters/Parser/FilterParser.cs +++ b/src/Hyperbee.Json/Filters/Parser/FilterParser.cs @@ -46,7 +46,7 @@ internal static Expression Parse( ReadOnlySpan filter, FilterContext context ) + internal static Expression Parse( ref ParserState state, FilterContext context ) // recursion entrypoint { // validate input if ( context == null ) @@ -373,36 +373,30 @@ Operator.NotEquals when IsNumerical( left.Expression?.Type ) || IsNumerical( rig private static class ExpressionConverter { - // Cache the MethodInfo for GetAsValue method - private static readonly MethodInfo GetAsValueMethodInfo = typeof( IValueAccessor ) - .GetMethod( nameof( IValueAccessor.GetAsValue ) ); + // Cached delegate for calling IValueAccessorGetAsValue( IEnumerable nodes ) - // Cache the compiled delegate for calling GetAsValue method private static readonly Func, IEnumerable, object> GetAsValueDelegate; static ExpressionConverter() { - // Create parameters for the expression + // Pre-compile the delegate to call the GetAsValue method + var accessorParam = Expression.Parameter( typeof( IValueAccessor ), "accessor" ); var expressionParam = Expression.Parameter( typeof( IEnumerable ), "expression" ); - // Create the expression to call the GetAsValue method - var callExpression = Expression.Call( accessorParam, GetAsValueMethodInfo, expressionParam ); + var methodInfo = typeof(IValueAccessor).GetMethod( nameof( IValueAccessor.GetAsValue ) ); + var callExpression = Expression.Call( accessorParam, methodInfo!, expressionParam ); - // Compile the expression into a delegate GetAsValueDelegate = Expression.Lambda, IEnumerable, object>>( callExpression, accessorParam, expressionParam ).Compile(); } public static Expression ConvertToValue( IValueAccessor accessor, Expression expression ) { - if ( expression == null ) - return null; - - if ( expression.Type != typeof( IEnumerable ) ) + if ( expression == null || expression.Type != typeof( IEnumerable ) ) return expression; - // Create an expression representing the instance of the descriptor + // Create an expression representing the instance of the accessor var accessorExpression = Expression.Constant( accessor ); // Use the compiled delegate to create an expression to call the GetAsValue method @@ -427,7 +421,6 @@ public static Expression ConvertToNumber( Expression expression ) return expression; } - } private class ExprItem( Expression expression, Operator op ) diff --git a/test/Hyperbee.Json.Tests/Evaluators/FilterExtenstionFunctionTests.cs b/test/Hyperbee.Json.Tests/Parsers/FilterExtensionFunctionTests.cs similarity index 87% rename from test/Hyperbee.Json.Tests/Evaluators/FilterExtenstionFunctionTests.cs rename to test/Hyperbee.Json.Tests/Parsers/FilterExtensionFunctionTests.cs index 9a20bb93..1ce59077 100644 --- a/test/Hyperbee.Json.Tests/Evaluators/FilterExtenstionFunctionTests.cs +++ b/test/Hyperbee.Json.Tests/Parsers/FilterExtensionFunctionTests.cs @@ -2,17 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Text.Json; using System.Text.Json.Nodes; -using Hyperbee.Json.Descriptors.Element; -using Hyperbee.Json.Descriptors.Node; using Hyperbee.Json.Extensions; using Hyperbee.Json.Filters.Parser; using Hyperbee.Json.Tests.TestSupport; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Expression = System.Linq.Expressions.Expression; -namespace Hyperbee.Json.Tests.Evaluators; +namespace Hyperbee.Json.Tests.Parsers; [TestClass] public class FilterExtensionFunctionTests : JsonTestBase diff --git a/test/Hyperbee.Json.Tests/Evaluators/FilterExpressionParserTests.cs b/test/Hyperbee.Json.Tests/Parsers/FilterParserTests.cs similarity index 96% rename from test/Hyperbee.Json.Tests/Evaluators/FilterExpressionParserTests.cs rename to test/Hyperbee.Json.Tests/Parsers/FilterParserTests.cs index 460402cf..4ddbe4df 100644 --- a/test/Hyperbee.Json.Tests/Evaluators/FilterExpressionParserTests.cs +++ b/test/Hyperbee.Json.Tests/Parsers/FilterParserTests.cs @@ -10,10 +10,10 @@ using Hyperbee.Json.Tests.TestSupport; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Hyperbee.Json.Tests.Evaluators; +namespace Hyperbee.Json.Tests.Parsers; [TestClass] -public class FilterExpressionParserTests : JsonTestBase +public class FilterParserTests : JsonTestBase { [DataTestMethod] [DataRow( "((\"world\" == 'world') && (1 == 1))", true, typeof( JsonElement ) )] @@ -126,13 +126,13 @@ public void Should_MatchExpectedResult_WhenUsingFunctions( string filter, bool e } [DataTestMethod] - [DataRow( "length(@.store.book) == 4", true, typeof( JsonElement ) )] [DataRow( "length(@.store.book) == 4 ", true, typeof( JsonElement ) )] + [DataRow( "length (@.store.book) == 4 ", true, typeof(JsonElement) )] [DataRow( " length(@.store.book) == 4", true, typeof( JsonElement ) )] [DataRow( " length(@.store.book) == 4 ", true, typeof( JsonElement ) )] [DataRow( " length( @.store.book ) == 4 ", true, typeof( JsonElement ) )] - [DataRow( "4 == length(@.store.book)", true, typeof( JsonElement ) )] [DataRow( "4 == length( @.store.book ) ", true, typeof( JsonElement ) )] + [DataRow( "4 == length ( @.store.book ) ", true, typeof(JsonElement) )] [DataRow( " 4 == length(@.store.book)", true, typeof( JsonElement ) )] [DataRow( " 4 == length(@.store.book) ", true, typeof( JsonElement ) )] [DataRow( " 4 == length( @.store.book ) ", true, typeof( JsonElement ) )] @@ -192,7 +192,8 @@ private static bool Execute( Expression expression, ParameterExpression param, T return func( new JsonElement() ); } - else if ( sourceType == typeof( JsonNode ) ) + + if ( sourceType == typeof( JsonNode ) ) { var func = Expression .Lambda>( expression, param ) @@ -200,10 +201,8 @@ private static bool Execute( Expression expression, ParameterExpression param, T return func( JsonNode.Parse( "{}" ) ); } - else - { - throw new NotImplementedException(); - } + + throw new NotImplementedException(); } private static bool CompileAndExecute( string filter, Type sourceType ) diff --git a/test/Hyperbee.Json.Tests/Tokenizer/JsonPathQueryTokenizerTests.cs b/test/Hyperbee.Json.Tests/Parsers/JsonPathQueryParserTests.cs similarity index 87% rename from test/Hyperbee.Json.Tests/Tokenizer/JsonPathQueryTokenizerTests.cs rename to test/Hyperbee.Json.Tests/Parsers/JsonPathQueryParserTests.cs index d32ecdd9..9ce26565 100644 --- a/test/Hyperbee.Json.Tests/Tokenizer/JsonPathQueryTokenizerTests.cs +++ b/test/Hyperbee.Json.Tests/Parsers/JsonPathQueryParserTests.cs @@ -1,10 +1,10 @@ using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Hyperbee.Json.Tests.Tokenizer; +namespace Hyperbee.Json.Tests.Parsers; [TestClass] -public class JsonPathQueryTokenizerTests +public class JsonPathQueryParserTests { [DataTestMethod] [DataRow( "$", "{$|s}" )] @@ -33,20 +33,20 @@ public class JsonPathQueryTokenizerTests public void Should_tokenize_json_path( string jsonPath, string expected ) { // act - var tokens = JsonPathQueryParser.Parse( jsonPath ); + var pathSegment = JsonPathQueryParser.Parse( jsonPath ); // arrange - var result = TokensToString( tokens ); + var result = SegmentsToString( pathSegment ); // assert Assert.AreEqual( expected, result ); return; - static string TokensToString( JsonPathSegment segment ) + static string SegmentsToString( JsonPathSegment segment ) { - return string.Join( ';', segment.AsEnumerable().Select( TokenToString ) ); + return string.Join( ';', segment.AsEnumerable().Select( SegmentToString ) ); - static string TokenToString( JsonPathSegment segment ) + static string SegmentToString( JsonPathSegment segment ) { var (singular, selectors) = segment; var selectorType = singular ? "s" : "g"; // s:singular, g:group diff --git a/test/Hyperbee.Json.Tests/TestSupport/JsonPathPair.cs b/test/Hyperbee.Json.Tests/TestSupport/JsonPathPair.cs deleted file mode 100644 index 2592216d..00000000 --- a/test/Hyperbee.Json.Tests/TestSupport/JsonPathPair.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Hyperbee.Json.Tests.TestSupport; - -// public record JsonPathPair -// { -// public string Path { get; init; } -// public dynamic Value { get; init; } -// } diff --git a/test/Hyperbee.Json.Tests/TestSupport/JsonTestBase.cs b/test/Hyperbee.Json.Tests/TestSupport/JsonTestBase.cs index eba658a6..7e393c98 100644 --- a/test/Hyperbee.Json.Tests/TestSupport/JsonTestBase.cs +++ b/test/Hyperbee.Json.Tests/TestSupport/JsonTestBase.cs @@ -45,9 +45,6 @@ public static TType GetDocument( string filename = null ) if ( type == typeof( JsonDocument ) ) return (TType) (object) ReadJsonDocument( filename ); - //if ( type == typeof(JsonElement) ) - // return (TType)(object) ReadJsonDocument( filename )?.RootElement; - if ( type == typeof( JsonNode ) ) return (TType) (object) ReadJsonNode( filename ); @@ -59,9 +56,6 @@ public static object GetDocument( Type target, string filename = null ) if ( target == typeof( JsonDocument ) ) return GetDocument( filename ); - //if ( target == typeof(JsonElement) ) - // return GetDocument( filename )?.RootElement; - if ( target == typeof( JsonNode ) ) return GetDocument( filename );