-
-
Notifications
You must be signed in to change notification settings - Fork 245
Expand file tree
/
Copy pathKeywordsHelper.cs
More file actions
128 lines (107 loc) · 4.43 KB
/
KeywordsHelper.cs
File metadata and controls
128 lines (107 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Validation;
using System.Linq.Expressions;
using AnyOfTypes;
namespace System.Linq.Dynamic.Core.Parser;
internal class KeywordsHelper : IKeywordsHelper
{
public const string KEYWORD_IT = "it";
public const string KEYWORD_PARENT = "parent";
public const string KEYWORD_ROOT = "root";
public const string SYMBOL_IT = "$";
public const string SYMBOL_PARENT = "^";
public const string SYMBOL_ROOT = "~";
public const string FUNCTION_IIF = "iif";
public const string FUNCTION_ISNULL = "isnull";
public const string FUNCTION_NEW = "new";
public const string FUNCTION_NULLPROPAGATION = "np";
public const string FUNCTION_IS = "is";
public const string FUNCTION_AS = "as";
public const string FUNCTION_CAST = "cast";
private readonly ParsingConfig _config;
// Keywords compare case depends on the value from ParsingConfig.IsCaseSensitive
private readonly Dictionary<string, AnyOf<string, Expression, Type>> _keywordMapping;
// PreDefined Types are not IgnoreCase
private static readonly Dictionary<string, Type> PreDefinedTypeMapping = new();
// Custom DefinedTypes are not IgnoreCase
private readonly Dictionary<string, Type> _customTypeMapping = new();
static KeywordsHelper()
{
foreach (var type in PredefinedTypesHelper.PredefinedTypes.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key))
{
PreDefinedTypeMapping[type.FullName!] = type;
PreDefinedTypeMapping[type.Name] = type;
}
}
public KeywordsHelper(ParsingConfig config)
{
_config = Check.NotNull(config);
_keywordMapping = new(config.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase)
{
{ "true", Expression.Constant(true) },
{ "false", Expression.Constant(false) },
{ "null", Expression.Constant(null) },
{ SYMBOL_IT, SYMBOL_IT },
{ SYMBOL_PARENT, SYMBOL_PARENT },
{ SYMBOL_ROOT, SYMBOL_ROOT },
{ FUNCTION_IIF, FUNCTION_IIF },
{ FUNCTION_ISNULL, FUNCTION_ISNULL },
{ FUNCTION_NEW, FUNCTION_NEW },
{ FUNCTION_NULLPROPAGATION, FUNCTION_NULLPROPAGATION },
{ FUNCTION_IS, FUNCTION_IS },
{ FUNCTION_AS, FUNCTION_AS },
{ FUNCTION_CAST, FUNCTION_CAST }
};
if (config.AreContextKeywordsEnabled)
{
_keywordMapping.Add(KEYWORD_IT, KEYWORD_IT);
_keywordMapping.Add(KEYWORD_PARENT, KEYWORD_PARENT);
_keywordMapping.Add(KEYWORD_ROOT, KEYWORD_ROOT);
}
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (config.CustomTypeProvider != null)
{
foreach (var type in config.CustomTypeProvider.GetCustomTypes())
{
_customTypeMapping[type.FullName!] = type;
_customTypeMapping[type.Name] = type;
}
}
}
public bool TryGetValue(string name, out AnyOf<string, Expression, Type> keywordOrType)
{
// 1. Try to get as keyword
if (_keywordMapping.TryGetValue(name, out var keyWord))
{
keywordOrType = keyWord;
return true;
}
// 2. Try to get as predefined shorttype ("bool", "char", ...)
if (PredefinedTypesHelper.PredefinedTypesShorthands.TryGetValue(name, out var predefinedShortHandType))
{
keywordOrType = predefinedShortHandType;
return true;
}
// 3. Try to get as predefined type ("Boolean", "System.Boolean", ..., "DateTime", "System.DateTime", ...)
if (PreDefinedTypeMapping.TryGetValue(name, out var predefinedType))
{
keywordOrType = predefinedType;
return true;
}
// 4. Try to get as an enum from the system namespace
if (_config.SupportEnumerationsFromSystemNamespace && EnumerationsFromMscorlib.PredefinedEnumerationTypes.TryGetValue(name, out var predefinedEnumType))
{
keywordOrType = predefinedEnumType;
return true;
}
// 5. Try to get as custom type
if (_customTypeMapping.TryGetValue(name, out var customType))
{
keywordOrType = customType;
return true;
}
// 6. Not found, return false
keywordOrType = default;
return false;
}
}