Skip to content

Commit

Permalink
Add config setting: NewOperatorIsNotAllowed (#732)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefH authored Sep 10, 2023
1 parent d5122c9 commit 0b56ddd
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 12 deletions.
7 changes: 6 additions & 1 deletion src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,10 @@ private Expression ParseIdentifier()
return ParseFunctionIsNull();

case KeywordsHelper.FUNCTION_NEW:
if (_parsingConfig.DisallowNewKeyword)
{
throw ParseError(Res.NewOperatorIsNotAllowed);
}
return ParseNew();

case KeywordsHelper.FUNCTION_NULLPROPAGATION:
Expand Down Expand Up @@ -1354,9 +1358,10 @@ private Expression ParseNew()
if (_textParser.CurrentToken.Id == TokenId.Identifier)
{
var newTypeName = _textParser.CurrentToken.Text;

_textParser.NextToken();

while (_textParser.CurrentToken.Id == TokenId.Dot || _textParser.CurrentToken.Id == TokenId.Plus)
while (_textParser.CurrentToken.Id is TokenId.Dot or TokenId.Plus)
{
var sep = _textParser.CurrentToken.Text;
_textParser.NextToken();
Expand Down
13 changes: 10 additions & 3 deletions src/System.Linq.Dynamic.Core/ParsingConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ public class ParsingConfig
/// <summary>
/// Default ParsingConfig
/// </summary>
public static ParsingConfig Default { get; } = new ParsingConfig();
public static ParsingConfig Default { get; } = new();

/// <summary>
/// Default ParsingConfig for EntityFramework Core 2.1 and higher
/// </summary>
public static ParsingConfig DefaultEFCore21 { get; } = new ParsingConfig
public static ParsingConfig DefaultEFCore21 { get; } = new()
{
EvaluateGroupByAtDatabase = true
};
Expand All @@ -30,7 +30,7 @@ public class ParsingConfig
/// <summary>
/// Default ParsingConfig for CosmosDb
/// </summary>
public static ParsingConfig DefaultCosmosDb { get; } = new ParsingConfig
public static ParsingConfig DefaultCosmosDb { get; } = new()
{
RenameEmptyParameterExpressionNames = true
};
Expand Down Expand Up @@ -227,4 +227,11 @@ public IQueryableAnalyzer QueryableAnalyzer
/// Default value is <c>false</c>.
/// </summary>
public bool SupportDotInPropertyNames { get; set; } = false;

/// <summary>
/// Disallows the New() keyword to be used to construct a class.
///
/// Default value is <c>false</c>.
/// </summary>
public bool DisallowNewKeyword { get; set; } = false;
}
1 change: 1 addition & 0 deletions src/System.Linq.Dynamic.Core/Res.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal static class Res
public const string MinusCannotBeAppliedToUnsignedInteger = "'-' cannot be applied to unsigned integers.";
public const string MissingAsClause = "Expression is missing an 'as' clause";
public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other";
public const string NewOperatorIsNotAllowed = "Using the new operator is not allowed via the ParsingConfig.";
public const string NoApplicableAggregate = "No applicable aggregate method '{0}({1})' exists";
public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'";
public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Linq.Dynamic.Core.Parser;
using System.Linq.Expressions;
using FluentAssertions;
using FluentAssertions;
using Xunit;

namespace System.Linq.Dynamic.Core.Tests.Parser
Expand All @@ -11,7 +9,7 @@ partial class ExpressionParserTests
public void ParseMemberAccess_DictionaryIndex_On_Dynamic()
{
// Arrange
var products = (new ProductDynamic[0]).AsQueryable();
var products = new ProductDynamic[0].AsQueryable();

// Act
var expression = products.Where("Properties.Name == @0", "First Product").Expression;
Expand All @@ -31,4 +29,4 @@ public class ProductDynamic

public dynamic Properties { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Parser;
using System.Linq.Expressions;
using FluentAssertions;
Expand Down Expand Up @@ -216,9 +217,10 @@ public void ParseTypeAccess_Via_Constructor_DynamicType_To_String(string newExpr
// Arrange
var parameter = Expression.Parameter(typeof(int));
var parameter2 = Expression.Parameter(typeof(int));
var returnType = DynamicClassFactory.CreateType(new List<DynamicProperty> {
new DynamicProperty("a", typeof(int)),
new DynamicProperty("b", typeof(int))
var returnType = DynamicClassFactory.CreateType(new List<DynamicProperty>
{
new("a", typeof(int)),
new("b", typeof(int))
});

// Act
Expand All @@ -228,4 +230,27 @@ public void ParseTypeAccess_Via_Constructor_DynamicType_To_String(string newExpr
// Assert
expression.ToString().Should().Match(newExpression2);
}

[Fact]
public void Parse_NewOperator_When_DisallowNewKeyword_Is_True_Should_Throw_Exception()
{
// Arrange
var parameter = Expression.Parameter(typeof(int));
var returnType = DynamicClassFactory.CreateType(new List<DynamicProperty>
{
new("a", typeof(int))
});
var config = new ParsingConfig
{
DisallowNewKeyword = true
};

// Act
var parser = new ExpressionParser(new[] { parameter }, "new(1 as a)", new object[] { }, config);

Action action = () => parser.Parse(returnType);

// Assert
action.Should().Throw<ParseException>().Which.Message.Should().Be(Res.NewOperatorIsNotAllowed);
}
}

0 comments on commit 0b56ddd

Please sign in to comment.