Skip to content

Commit 12ff9fb

Browse files
committed
#95 part 2 instanciate newsted class
1 parent 4fc7688 commit 12ff9fb

File tree

3 files changed

+93
-73
lines changed

3 files changed

+93
-73
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,13 @@ ExpressionEvaluator evaluatorForMethodArgs()
25132513
.SetCategory("Bug resolution")
25142514
.SetCategory("NestedType");
25152515

2516+
yield return new TestCaseData(new ExpressionEvaluator()
2517+
, "new CodingSeb.ExpressionEvaluator.Tests.OtherNamespace.ClassInOtherNameSpace1.ANestedClass().Value1"
2518+
, null)
2519+
.Returns(45)
2520+
.SetCategory("Bug resolution")
2521+
.SetCategory("NestedType");
2522+
25162523
// end of issue #95
25172524

25182525
#endregion

CodingSeb.ExpressionEvaluator.Tests/TestsUtils/ClassInOtherNameSpace1.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
public class ClassInOtherNameSpace1
44
{
55
public int Value1 { get; set; } = 26;
6+
7+
public class ANestedClass
8+
{
9+
public int Value1 { get; set; } = 45;
10+
}
611
}
712
}

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 81 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public partial class ExpressionEvaluator
3131

3232
protected const string primaryTypesRegexPattern = @"(?<=^|[^\p{L}_])(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|ulong[?]?|void)(?=[^a-zA-Z_]|$)";
3333

34-
protected static readonly Regex varOrFunctionRegEx = new Regex(@"^((?<sign>[+-])|(?<prefixOperator>[+][+]|--)|(?<varKeyword>var)\s+|(?<dynamicKeyword>dynamic)\s+|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[\p{L}_](?>[\p{L}_0-9]*))(?>\s*)((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>|\?\?)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![\p{L}_0-9]))|((?<isgeneric>[<](?>([\p{L}_](?>[\p{L}_0-9]*)|(?>\s+)|[,\.])+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
34+
protected static readonly Regex varOrFunctionRegEx = new Regex(@"^((?<sign>[+-])|(?<prefixOperator>[+][+]|--)|(?<varKeyword>var)\s+|(?<dynamicKeyword>dynamic)\s+|((?<nullConditional>[?])?(?<inObject>\.))?)(?<name>[\p{L}_](?>[\p{L}_0-9]*))(?>\s*)((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>|\?\?)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![\p{L}_0-9]))|((?<isgeneric>[<](?>([\p{L}_](?>[\p{L}_0-9]*)|(?>\s+)|[,\.])+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
3535

3636
protected const string numberRegexOrigPattern = @"^(?<sign>[+-])?([0-9][0-9_{1}]*[0-9]|\d)(?<hasdecimal>{0}?([0-9][0-9_]*[0-9]|\d)(e[+-]?([0-9][0-9_]*[0-9]|\d))?)?(?<type>ul|[fdulm])?";
3737
protected string numberRegexPattern;
@@ -55,8 +55,7 @@ public partial class ExpressionEvaluator
5555
protected static readonly Regex initInNewBeginningRegex = new Regex(@"^(?>\s*){", RegexOptions.Compiled);
5656
protected static readonly Regex functionArgKeywordsRegex = new Regex(@"^\s*(?<keyword>out|ref|in)\s+((?<typeName>[\p{L}_][\p{L}_0-9\.\[\]<>]*[?]?)\s+(?=[\p{L}_]))?(?<toEval>(?<varName>[\p{L}_](?>[\p{L}_0-9]*))\s*(=.*)?)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
5757

58-
// Depending on OptionInlineNamespacesEvaluationActive. Initialized in constructor
59-
protected string InstanceCreationWithNewKeywordRegexPattern { get { return @"^new(?>\s*)((?<isAnonymous>[{{])|((?<name>[\p{L}_][\p{L}_0-9" + (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) + @"]*)(?>\s*)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?>\s*)((?<isfunction>[(])|(?<isArray>\[)|(?<isInit>[{{]))?))"; } }
58+
protected static readonly Regex instanceCreationWithNewKeywordRegex = new Regex(@"^new(?>\s*)((?<isAnonymous>[{{])|((?<name>[\p{L}_][\p{L}_0-9\.]*)(?>\s*)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?>\s*)((?<isfunction>[(])|(?<isArray>\[)|(?<isInit>[{{]))?))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
6059
protected string CastRegexPattern { get { return @"^\((?>\s*)(?<typeName>[\p{L}_][\p{L}_0-9" + (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) + @"\[\]<>]*[?]?)(?>\s*)\)"; } }
6160

6261
// To remove comments in scripts based on https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689
@@ -1724,7 +1723,7 @@ protected virtual bool EvaluateInstanceCreationWithNewKeyword(string expression,
17241723
if (!OptionNewKeywordEvaluationActive)
17251724
return false;
17261725

1727-
Match instanceCreationMatch = Regex.Match(expression.Substring(i), InstanceCreationWithNewKeywordRegexPattern, optionCaseSensitiveEvaluationActive ? RegexOptions.None : RegexOptions.IgnoreCase);
1726+
Match instanceCreationMatch = instanceCreationWithNewKeywordRegex.Match(expression.Substring(i));
17281727

17291728
if (instanceCreationMatch.Success
17301729
&& (stack.Count == 0
@@ -1769,9 +1768,11 @@ void InitSimpleObjet(object element, List<string> initArgs)
17691768
{
17701769
string completeName = instanceCreationMatch.Groups["name"].Value;
17711770
string genericTypes = instanceCreationMatch.Groups["isgeneric"].Value;
1772-
Type type = GetTypeByFriendlyName(completeName, genericTypes);
17731771

1774-
if (type == null)
1772+
int typeIndex = 0;
1773+
Type type = EvaluateType(completeName + genericTypes, ref typeIndex);
1774+
1775+
if (type == null || typeIndex > 0 && typeIndex < completeName.Length)
17751776
throw new ExpressionEvaluatorSyntaxErrorException($"Type or class {completeName}{genericTypes} is unknown");
17761777

17771778
void Init(object element, List<string> initArgs)
@@ -2439,73 +2440,7 @@ where method.GetParameters()[0].ParameterType == objType // static extMethod(thi
24392440
}
24402441
else
24412442
{
2442-
string typeName = $"{varFuncName}{((i < expression.Length && expression.Substring(i)[0] == '?') ? "?" : "") }";
2443-
Type staticType = GetTypeByFriendlyName(typeName, genericsTypes);
2444-
2445-
// For inline namespace parsing
2446-
if (staticType == null && OptionInlineNamespacesEvaluationActive)
2447-
{
2448-
int subIndex = 0;
2449-
Match namespaceMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2450-
2451-
while (staticType == null
2452-
&& namespaceMatch.Success
2453-
&& !namespaceMatch.Groups["sign"].Success
2454-
&& !namespaceMatch.Groups["assignationOperator"].Success
2455-
&& !namespaceMatch.Groups["postfixOperator"].Success
2456-
&& !namespaceMatch.Groups["isfunction"].Success
2457-
&& i + subIndex < expression.Length
2458-
&& !typeName.EndsWith("?"))
2459-
{
2460-
subIndex += namespaceMatch.Length;
2461-
typeName += $".{namespaceMatch.Groups["name"].Value}{((i + subIndex < expression.Length && expression.Substring(i + subIndex)[0] == '?') ? "?" : "") }";
2462-
2463-
staticType = GetTypeByFriendlyName(typeName, namespaceMatch.Groups["isgeneric"].Value);
2464-
2465-
if (staticType != null)
2466-
{
2467-
i += subIndex;
2468-
break;
2469-
}
2470-
2471-
namespaceMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2472-
}
2473-
}
2474-
2475-
// For nested type parsing
2476-
if (staticType != null)
2477-
{
2478-
int subIndex = 0;
2479-
Match nestedTypeMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2480-
Type nestedType = null;
2481-
2482-
while (nestedTypeMatch.Success
2483-
&& !nestedTypeMatch.Groups["sign"].Success
2484-
&& !nestedTypeMatch.Groups["assignationOperator"].Success
2485-
&& !nestedTypeMatch.Groups["postfixOperator"].Success
2486-
&& !nestedTypeMatch.Groups["isfunction"].Success
2487-
&& i + nestedTypeMatch.Length < expression.Length)
2488-
{
2489-
typeName += $"+{nestedTypeMatch.Groups["name"].Value}";
2490-
2491-
nestedType = GetTypeByFriendlyName(typeName, nestedTypeMatch.Groups["isgeneric"].Value);
2492-
2493-
if (nestedType != null)
2494-
{
2495-
i += nestedTypeMatch.Length;
2496-
staticType = nestedType;
2497-
}
2498-
else
2499-
{
2500-
break;
2501-
}
2502-
2503-
nestedTypeMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2504-
}
2505-
}
2506-
2507-
if (typeName.EndsWith("?") && staticType != null)
2508-
i++;
2443+
Type staticType = EvaluateType(expression, ref i, varFuncName, genericsTypes);
25092444

25102445
if (staticType != null)
25112446
{
@@ -2547,6 +2482,79 @@ where method.GetParameters()[0].ParameterType == objType // static extMethod(thi
25472482
}
25482483
}
25492484

2485+
protected virtual Type EvaluateType(string expression,ref int i, string currentName = "", string genericsTypes = "")
2486+
{
2487+
string typeName = $"{currentName}{((i < expression.Length && expression.Substring(i)[0] == '?') ? "?" : "") }";
2488+
Type staticType = GetTypeByFriendlyName(typeName, genericsTypes);
2489+
2490+
// For inline namespace parsing
2491+
if (staticType == null && OptionInlineNamespacesEvaluationActive)
2492+
{
2493+
int subIndex = 0;
2494+
Match namespaceMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2495+
2496+
while (staticType == null
2497+
&& namespaceMatch.Success
2498+
&& !namespaceMatch.Groups["sign"].Success
2499+
&& !namespaceMatch.Groups["assignationOperator"].Success
2500+
&& !namespaceMatch.Groups["postfixOperator"].Success
2501+
&& !namespaceMatch.Groups["isfunction"].Success
2502+
&& i + subIndex < expression.Length
2503+
&& !typeName.EndsWith("?"))
2504+
{
2505+
subIndex += namespaceMatch.Length;
2506+
typeName += $"{namespaceMatch.Groups["inObject"].Value}{namespaceMatch.Groups["name"].Value}{((i + subIndex < expression.Length && expression.Substring(i + subIndex)[0] == '?') ? "?" : "") }";
2507+
2508+
staticType = GetTypeByFriendlyName(typeName, namespaceMatch.Groups["isgeneric"].Value);
2509+
2510+
if (staticType != null)
2511+
{
2512+
i += subIndex;
2513+
break;
2514+
}
2515+
2516+
namespaceMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2517+
}
2518+
}
2519+
2520+
if (typeName.EndsWith("?") && staticType != null)
2521+
i++;
2522+
2523+
// For nested type parsing
2524+
if (staticType != null)
2525+
{
2526+
int subIndex = 0;
2527+
Match nestedTypeMatch = varOrFunctionRegEx.Match(expression.Substring(i + subIndex));
2528+
while (nestedTypeMatch.Success
2529+
&& !nestedTypeMatch.Groups["sign"].Success
2530+
&& !nestedTypeMatch.Groups["assignationOperator"].Success
2531+
&& !nestedTypeMatch.Groups["postfixOperator"].Success
2532+
&& !nestedTypeMatch.Groups["isfunction"].Success)
2533+
{
2534+
subIndex = nestedTypeMatch.Length;
2535+
typeName += $"+{nestedTypeMatch.Groups["name"].Value}{((i + subIndex < expression.Length && expression.Substring(i + subIndex)[0] == '?') ? "?" : "") }";
2536+
2537+
Type nestedType = GetTypeByFriendlyName(typeName, nestedTypeMatch.Groups["isgeneric"].Value);
2538+
if (nestedType != null)
2539+
{
2540+
i += subIndex;
2541+
staticType = nestedType;
2542+
2543+
if (typeName.EndsWith("?"))
2544+
i++;
2545+
}
2546+
else
2547+
{
2548+
break;
2549+
}
2550+
2551+
nestedTypeMatch = varOrFunctionRegEx.Match(expression.Substring(i));
2552+
}
2553+
}
2554+
2555+
return staticType;
2556+
}
2557+
25502558
protected virtual bool EvaluateChar(string expression, Stack<object> stack, ref int i)
25512559
{
25522560
if (!OptionCharEvaluationActive)

0 commit comments

Comments
 (0)