Skip to content

Commit 404d9f2

Browse files
authored
Fixed ParseArgumentList when using lambda filter on list of dictionaries (#796)
* wip * ? * . * . * // #793
1 parent e8b5273 commit 404d9f2

File tree

4 files changed

+452
-352
lines changed

4 files changed

+452
-352
lines changed

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

+15-11
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ public class ExpressionParser
5353
public string ItName { get; private set; } = KeywordsHelper.KEYWORD_IT;
5454

5555
/// <summary>
56-
/// There was a problem when an expression contained multiple lambdas where
57-
/// the ItName was not cleared and freed for the next lambda. This variable
58-
/// stores the ItName of the last parsed lambda.
56+
/// There was a problem when an expression contained multiple lambdas where the ItName was not cleared and freed for the next lambda.
57+
/// This variable stores the ItName of the last parsed lambda.
5958
/// Not used internally by ExpressionParser, but used to preserve compatibility of parsingConfig.RenameParameterExpression
6059
/// which was designed to only work with mono-lambda expressions.
6160
/// </summary>
@@ -269,17 +268,19 @@ private Expression ParseNullCoalescingOperator()
269268
// => operator - Added Support for projection operator
270269
private Expression ParseLambdaOperator()
271270
{
272-
Expression expr = ParseOrOperator();
271+
var expr = ParseOrOperator();
272+
273273
if (_textParser.CurrentToken.Id == TokenId.Lambda && _it?.Type == expr.Type)
274274
{
275275
_textParser.NextToken();
276-
if (_textParser.CurrentToken.Id == TokenId.Identifier || _textParser.CurrentToken.Id == TokenId.OpenParen)
276+
if (_textParser.CurrentToken.Id is TokenId.Identifier or TokenId.OpenParen)
277277
{
278278
var right = ParseConditionalOperator();
279279
return Expression.Lambda(right, new[] { (ParameterExpression)expr });
280280
}
281281
_textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
282282
}
283+
283284
return expr;
284285
}
285286

@@ -1061,7 +1062,9 @@ private Expression ParseIt()
10611062
{
10621063
throw ParseError(Res.NoItInScope);
10631064
}
1065+
10641066
_textParser.NextToken();
1067+
10651068
return _it;
10661069
}
10671070

@@ -1784,6 +1787,12 @@ private Expression ParseMemberAccess(Type? type, Expression? expression, string?
17841787
_textParser.NextToken();
17851788
}
17861789

1790+
// Parse as Lambda
1791+
if (_textParser.CurrentToken.Id == TokenId.Lambda && _it?.Type == type)
1792+
{
1793+
return ParseAsLambda(id);
1794+
}
1795+
17871796
if (_textParser.CurrentToken.Id == TokenId.OpenParen)
17881797
{
17891798
var isStaticAccess = expression == null;
@@ -1866,11 +1875,6 @@ private Expression ParseMemberAccess(Type? type, Expression? expression, string?
18661875
return _expressionHelper.ConvertToExpandoObjectAndCreateDynamicExpression(expression!, type, id);
18671876
}
18681877
#endif
1869-
// Parse as Lambda
1870-
if (_textParser.CurrentToken.Id == TokenId.Lambda && _it?.Type == type)
1871-
{
1872-
return ParseAsLambda(id);
1873-
}
18741878

18751879
// This could be enum like "A.B.C.MyEnum.Value1" or "A.B.C+MyEnum.Value1".
18761880
//
@@ -2118,7 +2122,7 @@ private Expression ParseEnumerable(Expression instance, Type elementType, string
21182122
}
21192123
else
21202124
{
2121-
if (new[] { "Concat", "Contains", "DefaultIfEmpty", "Except", "Intersect", "Skip", "Take", "Union" }.Contains(methodName))
2125+
if (new[] { "Concat", "Contains", "ContainsKey", "DefaultIfEmpty", "Except", "Intersect", "Skip", "Take", "Union" }.Contains(methodName))
21222126
{
21232127
args = new[] { instance, args[0] };
21242128
}

0 commit comments

Comments
 (0)