-
-
Notifications
You must be signed in to change notification settings - Fork 228
/
KeywordsHelper.cs
126 lines (106 loc) · 4.24 KB
/
KeywordsHelper.cs
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
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Dynamic.Core.Validation;
using System.Linq.Expressions;
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 are IgnoreCase
private readonly Dictionary<string, object> _keywordMapping = new(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 }
};
// PreDefined Types are not IgnoreCase
private static readonly Dictionary<string, object> _preDefinedTypeMapping = new();
// Custom DefinedTypes are not IgnoreCase
private readonly Dictionary<string, object> _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);
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, [NotNullWhen(true)] out object? 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 = null;
return false;
}
}