Skip to content

Commit 285b758

Browse files
committed
remove VB support, cleanup ToType
1 parent e35d620 commit 285b758

File tree

6 files changed

+178
-124
lines changed

6 files changed

+178
-124
lines changed
Lines changed: 119 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
using System;
2-
using System.Collections.Generic;
31
using System.Diagnostics.CodeAnalysis;
2+
using System.Text;
43

54
using EntityFrameworkCore.Generator.Metadata.Generation;
65

7-
using static System.Net.Mime.MediaTypeNames;
8-
96
namespace EntityFrameworkCore.Generator.Extensions;
107

118
public static class GenerationExtensions
@@ -24,52 +21,30 @@ public static class GenerationExtensions
2421
"__refvalue", "stackalloc"
2522
};
2623

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",
5127
"System.Collections.Generic",
52-
"System"
53-
};
28+
];
5429

55-
private static readonly Dictionary<string, string> _csharpTypeAlias = new(16)
30+
private static readonly Dictionary<Type, string> _csharpTypeAlias = new(16)
5631
{
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" }
7348
};
7449
#endregion
7550

@@ -94,79 +69,44 @@ public static string MakeUnique(this string name, Func<string, bool> exists)
9469
return uniqueName;
9570
}
9671

97-
public static bool IsKeyword(this string text, CodeLanguage language = CodeLanguage.CSharp)
72+
public static bool IsKeyword(this string text)
9873
{
9974
ArgumentException.ThrowIfNullOrEmpty(text);
10075

101-
return language == CodeLanguage.VisualBasic
102-
? _visualBasicKeywords.Contains(text)
103-
: _csharpKeywords.Contains(text);
76+
return _csharpKeywords.Contains(text);
10477
}
10578

10679
[return: NotNullIfNotNull(nameof(name))]
107-
public static string? ToSafeName(this string? name, CodeLanguage language = CodeLanguage.CSharp)
80+
public static string? ToSafeName(this string? name)
10881
{
10982
if (string.IsNullOrEmpty(name))
11083
return name;
11184

112-
if (!name.IsKeyword(language))
85+
if (!name.IsKeyword())
11386
return name;
11487

115-
return language == CodeLanguage.VisualBasic
116-
? string.Format("[{0}]", name)
117-
: "@" + name;
88+
return "@" + name;
11889
}
11990

120-
public static string ToType(this Type type, CodeLanguage language = CodeLanguage.CSharp)
91+
public static string ToType(this Type type)
12192
{
12293
ArgumentNullException.ThrowIfNull(type);
12394

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();
13898
}
13999

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)
159101
{
160102
bool isValueType = type.IsValueType;
161103

162-
var typeString = type.ToType(language);
104+
var typeString = type.ToType();
163105

164106
if (!isValueType || !isNullable)
165107
return typeString;
166108

167-
return language == CodeLanguage.VisualBasic
168-
? $"Nullable(Of {type})"
169-
: typeString + "?";
109+
return typeString.EndsWith('?') ? typeString : typeString + "?";
170110
}
171111

172112
public static bool IsValueType(this string? type)
@@ -189,4 +129,89 @@ public static string ToLiteral(this string value)
189129
? "@\"" + value.Replace("\"", "\"\"") + "\""
190130
: "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
191131
}
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+
}
192217
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace EntityFrameworkCore.Generator.Extensions;
2+
3+
public static class TypeExtensions
4+
{
5+
/// <summary>
6+
/// Gets the underlying type dealing with <see cref="T:Nullable`1"/>.
7+
/// </summary>
8+
/// <param name="type">The type.</param>
9+
/// <returns>Returns a type dealing with <see cref="T:Nullable`1"/>.</returns>
10+
public static Type GetUnderlyingType(this Type type)
11+
{
12+
ArgumentNullException.ThrowIfNull(type);
13+
return Nullable.GetUnderlyingType(type) ?? type;
14+
}
15+
16+
/// <summary>
17+
/// Determines whether the specified <paramref name="type"/> can be null.
18+
/// </summary>
19+
/// <param name="type">The type to check.</param>
20+
/// <returns>
21+
/// <c>true</c> if the specified <paramref name="type"/> can be null; otherwise, <c>false</c>.
22+
/// </returns>
23+
public static bool IsNullable(this Type type)
24+
{
25+
ArgumentNullException.ThrowIfNull(type);
26+
27+
if (!type.IsGenericType || type.IsGenericTypeDefinition)
28+
return false;
29+
30+
// Instantiated generic type only
31+
Type genericType = type.GetGenericTypeDefinition();
32+
return ReferenceEquals(genericType, typeof(Nullable<>));
33+
}
34+
}

src/EntityFrameworkCore.Generator.Core/Metadata/Generation/CodeLanguage.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/EntityFrameworkCore.Generator.Core/Parsing/MappingVisitor.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ private static string ParseMethodName(InvocationExpressionSyntax node)
114114
return propertyName;
115115
}
116116

117-
private List<string> ParseLambdaExpressionForAnonymousObject(InvocationExpressionSyntax node)
117+
private List<string>? ParseLambdaExpressionForAnonymousObject(InvocationExpressionSyntax node)
118118
{
119119
if (node == null)
120120
return null;
@@ -136,23 +136,21 @@ private List<string> ParseLambdaExpressionForAnonymousObject(InvocationExpressio
136136
if (anonymousObject == null)
137137
return null;
138138

139-
var propertyNames = anonymousObject
139+
return anonymousObject
140140
.ChildNodes()
141141
.OfType<AnonymousObjectMemberDeclaratorSyntax>()
142142
.Select(declarator => declarator
143143
.ChildNodes()
144144
.OfType<MemberAccessExpressionSyntax>()
145145
.FirstOrDefault())
146-
.Where(memberAccess => memberAccess != null)
146+
.OfType<MemberAccessExpressionSyntax>()
147147
.Select(memberAccess => memberAccess
148148
.ChildNodes()
149149
.OfType<IdentifierNameSyntax>()
150150
.Select(identifier => identifier.Identifier.ValueText)
151151
.LastOrDefault())
152-
.Where(propertyName => propertyName != null)
152+
.OfType<string>()
153153
.ToList();
154-
155-
return propertyNames;
156154
}
157155

158156
private void ParseHasOne(InvocationExpressionSyntax node)
@@ -191,9 +189,9 @@ private void ParseForeignKey(InvocationExpressionSyntax node)
191189
if (node == null || ParsedEntity == null)
192190
return;
193191

194-
List<string> propertyNames = null;
192+
List<string>? propertyNames = null;
195193
if (ParseLambaExpression(node) is string propertyName && !string.IsNullOrEmpty(propertyName))
196-
propertyNames = new List<string> { propertyName };
194+
propertyNames = [propertyName];
197195
else
198196
propertyNames = ParseLambdaExpressionForAnonymousObject(node);
199197

src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ private void GenerateRelationshipMapping(Relationship relationship)
227227
var primaryKeys = relationship.PrimaryProperties;
228228
var nonPrimaryPrincipalKey = !primaryKeys
229229
.Select(pp => relationship.PrimaryEntity.Properties.ByProperty(pp.PropertyName))
230-
.All(p => p.IsPrimaryKey ?? true);
230+
.All(p => p?.IsPrimaryKey ?? true);
231231

232232
if (nonPrimaryPrincipalKey)
233233
{

0 commit comments

Comments
 (0)