From 80031cba948ab3fb2da83ae7926a432b344f7428 Mon Sep 17 00:00:00 2001 From: Christophe PLAT Date: Mon, 19 Aug 2024 22:09:31 +0200 Subject: [PATCH] No longer try to parse a generic type if there's no possible candidates (#315) * No longer try to parse a generic type if there's no possible generic definition candidate in the known types. Fix #314 --- src/DynamicExpresso.Core/ParserArguments.cs | 10 ++++++++++ src/DynamicExpresso.Core/Parsing/Parser.cs | 9 +++++++-- test/DynamicExpresso.UnitTest/GithubIssues.cs | 12 ++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/DynamicExpresso.Core/ParserArguments.cs b/src/DynamicExpresso.Core/ParserArguments.cs index 0f5d8649..c4b68407 100644 --- a/src/DynamicExpresso.Core/ParserArguments.cs +++ b/src/DynamicExpresso.Core/ParserArguments.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using System.Reflection; using DynamicExpresso.Exceptions; +using System.Text.RegularExpressions; namespace DynamicExpresso { @@ -75,6 +76,15 @@ public bool TryGetKnownType(string name, out Type type) return false; } + /// + /// Returns true if the known types contain a generic type definition with the given name + any arity (e.g. name`1). + /// + internal bool HasKnownGenericTypeDefinition(string name) + { + var regex = new Regex("^" + name + "`\\d+$"); + return Settings.KnownTypes.Values.Any(refType => regex.IsMatch(refType.Name) && refType.Type.IsGenericTypeDefinition); + } + public bool TryGetIdentifier(string name, out Expression expression) { Identifier identifier; diff --git a/src/DynamicExpresso.Core/Parsing/Parser.cs b/src/DynamicExpresso.Core/Parsing/Parser.cs index 282526ec..5118524c 100644 --- a/src/DynamicExpresso.Core/Parsing/Parser.cs +++ b/src/DynamicExpresso.Core/Parsing/Parser.cs @@ -1399,9 +1399,14 @@ private bool TryParseKnownType(string name, out Type type) { // if the type is unknown, we need to restart parsing var originalPos = _token.pos; - _arguments.TryGetKnownType(name, out type); - type = ParseKnownGenericType(name, type); + // the name might reference a generic type, with an aliased name (e.g. List = MyList instead of List`1) + // it can also reference a generic type for which we don't know the arity yet (and therefore the name doesn't contain the `n suffix) + if (_arguments.TryGetKnownType(name, out type) || _arguments.HasKnownGenericTypeDefinition(name)) + { + type = ParseKnownGenericType(name, type); + } + type = ParseTypeModifiers(type); if (type == null) diff --git a/test/DynamicExpresso.UnitTest/GithubIssues.cs b/test/DynamicExpresso.UnitTest/GithubIssues.cs index 0edcc812..bb0f5441 100644 --- a/test/DynamicExpresso.UnitTest/GithubIssues.cs +++ b/test/DynamicExpresso.UnitTest/GithubIssues.cs @@ -836,6 +836,18 @@ public void GitHub_Issue_311() // It works if we cast to int Assert.AreEqual("AA", interpreter2.Eval("a.Substring((int)0, (int)2)")); } + + [Test] + public void GitHub_Issue_314() + { + var interpreter = new Interpreter(); + + var exception1 = Assert.Throws(() => interpreter.Eval("b < 1")); + Assert.AreEqual("b", exception1.Identifier); + + var exception2 = Assert.Throws(() => interpreter.Eval("b > 1")); + Assert.AreEqual("b", exception2.Identifier); + } } internal static class GithubIssuesTestExtensionsMethods