Skip to content

Failure in ParseArgumentList when using lambda filter on list of dictionaries #793

@astarche

Description

@astarche

1. Description

Queries like ListOfDictionaries.Any(x => x.ContainsKey("key")) fail in ParseArgumentList.

Similar-but-different queries work fine, like ListOfDictionaries.Any(it.ContainsKey(\"test\")) and ListOfKeys.Any(x => x.Contains(\"test\")).

2. Exception

Exception message: ')' or ',' expected (at index 25)
Stack trace:
   at System.Linq.Dynamic.Core.Tokenizer.TextParser.ValidateToken(TokenId tokenId, String errorMessage) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\TextParser.cs:line 451
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseArgumentList() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 2197
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseEnumerable(Expression instance, Type elementType, String methodName, Int32 errorPos, Type type) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 2056
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess(Type type, Expression expression, String id) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 1797
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 813
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 800
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseArithmetic() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 745
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 712
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 688
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 476
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 408
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 327
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 310
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 292
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 272
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 259
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 243
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 158
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Type delegateType, ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 120
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 98
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, Type itType, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 356
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Any(IQueryable source, ParsingConfig config, String predicate, Object[] args) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 185
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Any(IQueryable source, String predicate, Object[] args) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 193
   at Program.TestQuery(DataRecord data, String expression)

3. Fiddle or Project

fiddle

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;

public record DataRecord(List<Dictionary<string, string>> ListOfDictionaries, Dictionary<string, string> FirstDict, List<string> ListOfKeys);
public class Program
{
	public static void Main()
	{
		var dataList = new List<Dictionary<string, string>>
		{
			new()
			{
				["test"] = "value1"
			},
			new()
			{
				["otherKey"] = "value2"
			},
			new()
			{
				["test"] = "value3"
			},
		};
		var data = new DataRecord(dataList, dataList[0], dataList.SelectMany(d => d.Keys).ToList());
		TestQuery(data, "FirstDict.ContainsKey(\"test\")"); // True
		TestQuery(data, "ListOfKeys.Any(x => x.Contains(\"test\"))"); // True
		TestQuery(data, "ListOfDictionaries.Any(it.ContainsKey(\"test\"))"); // True
		TestQuery(data, "ListOfDictionaries.Any(ContainsKey(\"test\"))"); // True
		TestQuery(data, "ListOfDictionaries.Any(x => x.ContainsKey(\"test\"))"); // ERROR!
	}

	private static void TestQuery(DataRecord data, string expression)
	{
		var queryableDataRecord = new[]
		{
			data
		}.AsQueryable();
		try
		{
			var result = queryableDataRecord.Any(expression);
			System.Console.WriteLine($"{result}: {expression}");
		}
		catch (Exception e)
		{
			System.Console.WriteLine($"ERROR: {expression} >> [{e}]");
		}
	}
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions