Skip to content

Commit dbc904e

Browse files
committed
Better management of encapsulated generics types
1 parent d30a561 commit dbc904e

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,8 @@ public void TypeTesting(string expression, Type type)
867867
#region Generic types Management
868868

869869
[TestCase("List(\"Hello\", \"Test\").Cast<string>().ToList<string>().GetType()", ExpectedResult = typeof(List<string>) , Category = "List function, Generics")]
870-
[TestCase("new List<string>().GetType()", ExpectedResult = typeof(List<string>) , Category = "List function, Generics")]
870+
[TestCase("new List<string>().GetType()", ExpectedResult = typeof(List<string>) , Category = "new Keyword, Generics")]
871+
[TestCase("new Dictionary<string,List<int>>().GetType()", ExpectedResult = typeof(Dictionary<string, List<int>>) , Category = "new Keyword, Generics")]
871872

872873
#endregion
873874

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public class ExpressionEvaluator
3535
private static readonly Regex internalCharRegex = new Regex(@"^['](\\[']|[^'])*[']");
3636
private static readonly Regex indexingBeginningRegex = new Regex(@"^[?]?\[");
3737
private static readonly Regex assignationOrPostFixOperatorRegex = new Regex(@"^\s*((?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])|(?<postfixOperator>([+][+]|--)(?![" + diactiticsKeywordsRegexPattern + @"0-9])))");
38-
private static readonly Regex genericsDecodeRegex = new Regex("[^,<>]+(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?", RegexOptions.Compiled);
38+
private static readonly Regex genericsDecodeRegex = new Regex("(?<name>[^,<>]+)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?", RegexOptions.Compiled);
39+
private static readonly Regex genericsEndOnlyOneTrim = new Regex(@"\s+[>]\s+$");
3940

4041
private static readonly Regex endOfStringWithDollar = new Regex("^([^\"{\\\\]|\\\\[\\\\\"0abfnrtv])*[\"{]");
4142
private static readonly Regex endOfStringWithoutDollar = new Regex("^([^\"\\\\]|\\\\[\\\\\"0abfnrtv])*[\"]");
@@ -50,9 +51,9 @@ public class ExpressionEvaluator
5051

5152

5253
// Depending on OptionInlineNamespacesEvaluationActive. Initialized in constructor
53-
private string CastRegexPattern { get { return $@"^\(\s*(?<typeName>[{ diactiticsKeywordsRegexPattern }][{ diactiticsKeywordsRegexPattern }0-9\{ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) }[\]<>]*[?]?)\s*\)"; } }
5454
private string InstanceCreationWithNewKeywordRegexPattern { get { return $@"^new\s+(?<name>[{ diactiticsKeywordsRegexPattern }][{ diactiticsKeywordsRegexPattern}0-9{ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) }]*)\s*(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?\s*((?<isfunction>[(])|(?<isArray>\[))?"; } }
5555
private Regex instanceCreationWithNewKeywordRegex = null;
56+
private string CastRegexPattern { get { return $@"^\(\s*(?<typeName>[{ diactiticsKeywordsRegexPattern }][{ diactiticsKeywordsRegexPattern }0-9\{ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) }[\]<>]*[?]?)\s*\)"; } }
5657
private Regex castRegex = null;
5758

5859
private static readonly string primaryTypesRegexPattern = @"(?<=^|[^" + diactiticsKeywordsRegexPattern + @"])(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|void)(?=[^a-zA-Z_]|$)";
@@ -1348,6 +1349,7 @@ private bool EvaluateCast(string restOfExpression, Stack<object> stack, ref int
13481349
if (castMatch.Success)
13491350
{
13501351
string typeName = castMatch.Groups["typeName"].Value;
1352+
13511353
Type type = GetTypeByFriendlyName(typeName);
13521354

13531355
if (type != null)
@@ -1426,7 +1428,7 @@ private bool EvaluateInstanceCreationWithNewKeyword(string expr, string restOfEx
14261428
List<string> constructorArgs = GetExpressionsBetweenParenthesesOrOtherImbricableBrackets(expr, ref i, true);
14271429

14281430
if (type == null)
1429-
throw new ExpressionEvaluatorSyntaxErrorException($"type or class {completeName} is unknown");
1431+
throw new ExpressionEvaluatorSyntaxErrorException($"Type or class {completeName}{genericTypes} is unknown");
14301432

14311433
List<object> cArgs = constructorArgs.ConvertAll(arg => Evaluate(arg));
14321434
stack.Push(Activator.CreateInstance(type, cArgs.ToArray()));
@@ -2499,9 +2501,9 @@ private MethodInfo MakeConcreteMethodIfGeneric(MethodInfo methodInfo, string gen
24992501
private Type[] GetConcreteTypes(string genericsTypes)
25002502
{
25012503
return genericsDecodeRegex
2502-
.Matches(genericsTypes.TrimStart(' ', '<').TrimEnd(' ', '>'))
2504+
.Matches(genericsEndOnlyOneTrim.Replace(genericsTypes.TrimStart(' ', '<'), ""))
25032505
.Cast<Match>()
2504-
.Select(match => GetTypeByFriendlyName(match.Value))
2506+
.Select(match => GetTypeByFriendlyName(match.Groups["name"].Value, match.Groups["isgeneric"].Value, true))
25052507
.ToArray();
25062508
}
25072509

@@ -2660,7 +2662,7 @@ private bool DefaultFunctions(string name, List<string> args, out object result)
26602662
return functionExists;
26612663
}
26622664

2663-
private Type GetTypeByFriendlyName(string typeName, string genericTypes = "")
2665+
private Type GetTypeByFriendlyName(string typeName, string genericTypes = "", bool throwExceptionIfNotFound = false)
26642666
{
26652667
Type result = null;
26662668
try
@@ -2703,11 +2705,18 @@ private Type GetTypeByFriendlyName(string typeName, string genericTypes = "")
27032705
}
27042706
}
27052707
}
2708+
catch(ExpressionEvaluatorSyntaxErrorException)
2709+
{
2710+
throw;
2711+
}
27062712
catch { }
27072713

27082714
if (result != null && TypesToBlock.Contains(result))
27092715
result = null;
27102716

2717+
if (result == null && throwExceptionIfNotFound)
2718+
throw new ExpressionEvaluatorSyntaxErrorException($"Type or class {typeName}{genericTypes} is unknown");
2719+
27112720
return result;
27122721
}
27132722

0 commit comments

Comments
 (0)