1
- using System ;
2
- using System . Collections . Generic ;
3
1
using System . Diagnostics . CodeAnalysis ;
2
+ using System . Text ;
4
3
5
4
using EntityFrameworkCore . Generator . Metadata . Generation ;
6
5
7
- using static System . Net . Mime . MediaTypeNames ;
8
-
9
6
namespace EntityFrameworkCore . Generator . Extensions ;
10
7
11
8
public static class GenerationExtensions
@@ -24,52 +21,30 @@ public static class GenerationExtensions
24
21
"__refvalue" , "stackalloc"
25
22
} ;
26
23
27
- private static readonly HashSet < string > _visualBasicKeywords = new ( StringComparer . OrdinalIgnoreCase )
28
- {
29
- "as" , "do" , "if" , "in" , "is" , "me" , "of" , "on" , "or" , "to" ,
30
- "and" , "dim" , "end" , "for" , "get" , "let" , "lib" , "mod" , "new" , "not" , "rem" , "set" , "sub" , "try" , "xor" ,
31
- "ansi" , "auto" , "byte" , "call" , "case" , "cdbl" , "cdec" , "char" , "cint" , "clng" , "cobj" , "csng" , "cstr" , "date" , "each" , "else" ,
32
- "enum" , "exit" , "goto" , "like" , "long" , "loop" , "next" , "step" , "stop" , "then" , "true" , "wend" , "when" , "with" ,
33
- "alias" , "byref" , "byval" , "catch" , "cbool" , "cbyte" , "cchar" , "cdate" , "class" , "const" , "ctype" , "cuint" , "culng" , "endif" , "erase" , "error" ,
34
- "event" , "false" , "gosub" , "isnot" , "redim" , "sbyte" , "short" , "throw" , "ulong" , "until" , "using" , "while" ,
35
- "csbyte" , "cshort" , "double" , "elseif" , "friend" , "global" , "module" , "mybase" , "object" , "option" , "orelse" , "public" , "resume" , "return" , "select" , "shared" ,
36
- "single" , "static" , "string" , "typeof" , "ushort" ,
37
- "andalso" , "boolean" , "cushort" , "decimal" , "declare" , "default" , "finally" , "gettype" , "handles" , "imports" , "integer" , "myclass" , "nothing" , "partial" , "private" , "shadows" ,
38
- "trycast" , "unicode" , "variant" ,
39
- "assembly" , "continue" , "delegate" , "function" , "inherits" , "operator" , "optional" , "preserve" , "property" , "readonly" , "synclock" , "uinteger" , "widening" ,
40
- "addressof" , "interface" , "namespace" , "narrowing" , "overloads" , "overrides" , "protected" , "structure" , "writeonly" ,
41
- "addhandler" , "directcast" , "implements" , "paramarray" , "raiseevent" , "withevents" ,
42
- "mustinherit" , "overridable" ,
43
- "mustoverride" ,
44
- "removehandler" ,
45
- "class_finalize" , "notinheritable" , "notoverridable" ,
46
- "class_initialize"
47
- } ;
48
-
49
- private static readonly List < string > _defaultUsings = new List < string > ( )
50
- {
24
+ private static readonly HashSet < string > _defaultNamespaces =
25
+ [
26
+ "System" ,
51
27
"System.Collections.Generic" ,
52
- "System"
53
- } ;
28
+ ] ;
54
29
55
- private static readonly Dictionary < string , string > _csharpTypeAlias = new ( 16 )
30
+ private static readonly Dictionary < Type , string > _csharpTypeAlias = new ( 16 )
56
31
{
57
- { "System.Int16" , "short" } ,
58
- { "System.Int32" , "int" } ,
59
- { "System.Int64" , "long" } ,
60
- { "System.String" , "string" } ,
61
- { "System.Object" , "object" } ,
62
- { "System.Boolean" , "bool" } ,
63
- { "System.Void" , "void" } ,
64
- { "System.Char" , "char" } ,
65
- { "System.Byte" , "byte" } ,
66
- { "System.UInt16" , "ushort" } ,
67
- { "System.UInt32" , "uint" } ,
68
- { "System.UInt64" , "ulong" } ,
69
- { "System.SByte" , "sbyte" } ,
70
- { "System.Single" , "float" } ,
71
- { "System.Double" , "double" } ,
72
- { "System.Decimal" , "decimal" }
32
+ { typeof ( bool ) , "bool" } ,
33
+ { typeof ( byte ) , "byte" } ,
34
+ { typeof ( char ) , "char" } ,
35
+ { typeof ( decimal ) , "decimal" } ,
36
+ { typeof ( double ) , "double" } ,
37
+ { typeof ( float ) , "float" } ,
38
+ { typeof ( int ) , "int" } ,
39
+ { typeof ( long ) , "long" } ,
40
+ { typeof ( object ) , "object" } ,
41
+ { typeof ( sbyte ) , "sbyte" } ,
42
+ { typeof ( short ) , "short" } ,
43
+ { typeof ( string ) , "string" } ,
44
+ { typeof ( uint ) , "uint" } ,
45
+ { typeof ( ulong ) , "ulong" } ,
46
+ { typeof ( ushort ) , "ushort" } ,
47
+ { typeof ( void ) , "void" }
73
48
} ;
74
49
#endregion
75
50
@@ -94,79 +69,44 @@ public static string MakeUnique(this string name, Func<string, bool> exists)
94
69
return uniqueName ;
95
70
}
96
71
97
- public static bool IsKeyword ( this string text , CodeLanguage language = CodeLanguage . CSharp )
72
+ public static bool IsKeyword ( this string text )
98
73
{
99
74
ArgumentException . ThrowIfNullOrEmpty ( text ) ;
100
75
101
- return language == CodeLanguage . VisualBasic
102
- ? _visualBasicKeywords . Contains ( text )
103
- : _csharpKeywords . Contains ( text ) ;
76
+ return _csharpKeywords . Contains ( text ) ;
104
77
}
105
78
106
79
[ return : NotNullIfNotNull ( nameof ( name ) ) ]
107
- public static string ? ToSafeName ( this string ? name , CodeLanguage language = CodeLanguage . CSharp )
80
+ public static string ? ToSafeName ( this string ? name )
108
81
{
109
82
if ( string . IsNullOrEmpty ( name ) )
110
83
return name ;
111
84
112
- if ( ! name . IsKeyword ( language ) )
85
+ if ( ! name . IsKeyword ( ) )
113
86
return name ;
114
87
115
- return language == CodeLanguage . VisualBasic
116
- ? string . Format ( "[{0}]" , name )
117
- : "@" + name ;
88
+ return "@" + name ;
118
89
}
119
90
120
- public static string ToType ( this Type type , CodeLanguage language = CodeLanguage . CSharp )
91
+ public static string ToType ( this Type type )
121
92
{
122
93
ArgumentNullException . ThrowIfNull ( type ) ;
123
94
124
- if ( type . IsGenericType )
125
- {
126
- var genericType = type . GetGenericTypeDefinition ( ) . FullName !
127
- . Split ( '`' ) [ 0 ] ; // trim the `1 bit
128
-
129
- genericType = ToType ( genericType , language ) ;
130
-
131
- var elementType = ToType ( type . GetGenericArguments ( ) [ 0 ] . FullName ! , language ) ;
132
- return language == CodeLanguage . VisualBasic
133
- ? $ "{ genericType } (Of { elementType } )"
134
- : $ "{ genericType } <{ elementType } >";
135
- }
136
-
137
- return ToType ( type . FullName ?? type . Name , language ) ;
95
+ var stringBuilder = new StringBuilder ( ) ;
96
+ ProcessType ( stringBuilder , type ) ;
97
+ return stringBuilder . ToString ( ) ;
138
98
}
139
99
140
- public static string ToType ( this string type , CodeLanguage language = CodeLanguage . CSharp )
141
- {
142
- ArgumentException . ThrowIfNullOrEmpty ( type ) ;
143
-
144
- if ( type == "System.Xml.XmlDocument" )
145
- type = "System.String" ;
146
-
147
- if ( language == CodeLanguage . CSharp && _csharpTypeAlias . TryGetValue ( type , out var t ) )
148
- return t ;
149
-
150
- // drop common namespaces
151
- foreach ( var defaultUsing in _defaultUsings )
152
- if ( type . StartsWith ( defaultUsing ) )
153
- return type . Remove ( 0 , defaultUsing . Length + 1 ) ;
154
-
155
- return type ;
156
- }
157
-
158
- public static string ? ToNullableType ( this Type type , bool isNullable = false , CodeLanguage language = CodeLanguage . CSharp )
100
+ public static string ? ToNullableType ( this Type type , bool isNullable = false )
159
101
{
160
102
bool isValueType = type . IsValueType ;
161
103
162
- var typeString = type . ToType ( language ) ;
104
+ var typeString = type . ToType ( ) ;
163
105
164
106
if ( ! isValueType || ! isNullable )
165
107
return typeString ;
166
108
167
- return language == CodeLanguage . VisualBasic
168
- ? $ "Nullable(Of { type } )"
169
- : typeString + "?" ;
109
+ return typeString . EndsWith ( '?' ) ? typeString : typeString + "?" ;
170
110
}
171
111
172
112
public static bool IsValueType ( this string ? type )
@@ -189,4 +129,89 @@ public static string ToLiteral(this string value)
189
129
? "@\" " + value . Replace ( "\" " , "\" \" " ) + "\" "
190
130
: "\" " + value . Replace ( "\\ " , "\\ \\ " ) . Replace ( "\" " , "\\ \" " ) + "\" " ;
191
131
}
132
+
133
+
134
+
135
+ private static void ProcessType ( StringBuilder builder , Type type )
136
+ {
137
+ if ( type . IsGenericType )
138
+ {
139
+ var genericArguments = type . GetGenericArguments ( ) ;
140
+ ProcessGenericType ( builder , type , genericArguments , genericArguments . Length ) ;
141
+ }
142
+ else if ( type . IsArray )
143
+ {
144
+ ProcessArrayType ( builder , type ) ;
145
+ }
146
+ else if ( _csharpTypeAlias . TryGetValue ( type , out var builtInName ) )
147
+ {
148
+ builder . Append ( builtInName ) ;
149
+ }
150
+ else if ( type . Namespace . HasValue ( ) && _defaultNamespaces . Contains ( type . Namespace ) )
151
+ {
152
+ builder . Append ( type . Name ) ;
153
+ }
154
+ else
155
+ {
156
+ builder . Append ( type . FullName ?? type . Name ) ;
157
+ }
158
+ }
159
+
160
+ private static void ProcessArrayType ( StringBuilder builder , Type type )
161
+ {
162
+ var innerType = type ;
163
+ while ( innerType . IsArray )
164
+ {
165
+ innerType = innerType . GetElementType ( ) ! ;
166
+ }
167
+
168
+ ProcessType ( builder , innerType ) ;
169
+
170
+ while ( type . IsArray )
171
+ {
172
+ builder . Append ( '[' ) ;
173
+ builder . Append ( ',' , type . GetArrayRank ( ) - 1 ) ;
174
+ builder . Append ( ']' ) ;
175
+ type = type . GetElementType ( ) ! ;
176
+ }
177
+ }
178
+
179
+ private static void ProcessGenericType ( StringBuilder builder , Type type , Type [ ] genericArguments , int length )
180
+ {
181
+ if ( type . IsConstructedGenericType
182
+ && type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) )
183
+ {
184
+ ProcessType ( builder , type . GetUnderlyingType ( ) ) ;
185
+ builder . Append ( '?' ) ;
186
+ return ;
187
+ }
188
+
189
+ var offset = type . DeclaringType != null ? type . DeclaringType . GetGenericArguments ( ) . Length : 0 ;
190
+ var genericPartIndex = type . Name . IndexOf ( '`' ) ;
191
+ if ( genericPartIndex <= 0 )
192
+ {
193
+ builder . Append ( type . Name ) ;
194
+ return ;
195
+ }
196
+
197
+ builder . Append ( type . Name , 0 , genericPartIndex ) ;
198
+ builder . Append ( '<' ) ;
199
+
200
+ for ( var i = offset ; i < length ; i ++ )
201
+ {
202
+ ProcessType ( builder , genericArguments [ i ] ) ;
203
+ if ( i + 1 == length )
204
+ {
205
+ continue ;
206
+ }
207
+
208
+ builder . Append ( ',' ) ;
209
+ if ( ! genericArguments [ i + 1 ] . IsGenericParameter )
210
+ {
211
+ builder . Append ( ' ' ) ;
212
+ }
213
+ }
214
+
215
+ builder . Append ( '>' ) ;
216
+ }
192
217
}
0 commit comments