• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / EntityFrameworkCore.Generator / 15747844377

19 Jun 2025 02:19AM UTC coverage: 54.825%. First build
15747844377

Pull #673

github

web-flow
Merge 1e2d81d9b into 9e66c43b6
Pull Request #673: Use full name for generic types

646 of 1343 branches covered (48.1%)

Branch coverage included in aggregate %.

1 of 6 new or added lines in 1 file covered. (16.67%)

1882 of 3268 relevant lines covered (57.59%)

61.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.48
/src/EntityFrameworkCore.Generator.Core/Extensions/GenerationExtensions.cs
1
using System.Diagnostics.CodeAnalysis;
2
using System.Text;
3

4
using EntityFrameworkCore.Generator.Metadata.Generation;
5

6
namespace EntityFrameworkCore.Generator.Extensions;
7

8
public static class GenerationExtensions
9
{
10
    #region Data
11
    private static readonly HashSet<string> _csharpKeywords = new(StringComparer.Ordinal)
1✔
12
    {
1✔
13
        "as", "do", "if", "in", "is",
1✔
14
        "for", "int", "new", "out", "ref", "try",
1✔
15
        "base", "bool", "byte", "case", "char", "else", "enum", "goto", "lock", "long", "null", "this", "true", "uint", "void",
1✔
16
        "break", "catch", "class", "const", "event", "false", "fixed", "float", "sbyte", "short", "throw", "ulong", "using", "while",
1✔
17
        "double", "extern", "object", "params", "public", "return", "sealed", "sizeof", "static", "string", "struct", "switch", "typeof", "unsafe", "ushort",
1✔
18
        "checked", "decimal", "default", "finally", "foreach", "private", "virtual",
1✔
19
        "abstract", "continue", "delegate", "explicit", "implicit", "internal", "operator", "override", "readonly", "volatile",
1✔
20
        "__arglist", "__makeref", "__reftype", "interface", "namespace", "protected", "unchecked",
1✔
21
        "__refvalue", "stackalloc"
1✔
22
    };
1✔
23

24
    private static readonly HashSet<string> _defaultNamespaces =
1✔
25
    [
1✔
26
        "System",
1✔
27
        "System.Collections.Generic",
1✔
28
    ];
1✔
29

30
    private static readonly Dictionary<Type, string> _csharpTypeAlias = new(16)
1✔
31
    {
1✔
32
        { typeof(bool), "bool" },
1✔
33
        { typeof(byte), "byte" },
1✔
34
        { typeof(char), "char" },
1✔
35
        { typeof(decimal), "decimal" },
1✔
36
        { typeof(double), "double" },
1✔
37
        { typeof(float), "float" },
1✔
38
        { typeof(int), "int" },
1✔
39
        { typeof(long), "long" },
1✔
40
        { typeof(object), "object" },
1✔
41
        { typeof(sbyte), "sbyte" },
1✔
42
        { typeof(short), "short" },
1✔
43
        { typeof(string), "string" },
1✔
44
        { typeof(uint), "uint" },
1✔
45
        { typeof(ulong), "ulong" },
1✔
46
        { typeof(ushort), "ushort" },
1✔
47
        { typeof(void), "void" }
1✔
48
    };
1✔
49
    #endregion
50

51
    public static string ToFieldName(this string name)
52
    {
53
        ArgumentException.ThrowIfNullOrEmpty(name);
×
54

55
        return "_" + name.ToCamelCase();
×
56
    }
57

58
    public static string MakeUnique(this string name, Func<string, bool> exists)
59
    {
60
        ArgumentException.ThrowIfNullOrEmpty(name);
×
61
        ArgumentNullException.ThrowIfNull(exists);
×
62

63
        string uniqueName = name;
×
64
        int count = 1;
×
65

66
        while (exists(uniqueName))
×
67
            uniqueName = string.Concat(name, count++);
×
68

69
        return uniqueName;
×
70
    }
71

72
    public static bool IsKeyword(this string text)
73
    {
74
        ArgumentException.ThrowIfNullOrEmpty(text);
740✔
75

76
        return _csharpKeywords.Contains(text);
740✔
77
    }
78

79
    [return: NotNullIfNotNull(nameof(name))]
80
    public static string? ToSafeName(this string? name)
81
    {
82
        if (string.IsNullOrEmpty(name))
740!
83
            return name;
×
84

85
        if (!name.IsKeyword())
740!
86
            return name;
740✔
87

88
        return "@" + name;
×
89
    }
90

91
    public static string ToType(this Type type)
92
    {
93
        ArgumentNullException.ThrowIfNull(type);
221✔
94

95
        var stringBuilder = new StringBuilder();
221✔
96
        ProcessType(stringBuilder, type);
221✔
97
        return stringBuilder.ToString();
221✔
98
    }
99

100
    public static string? ToNullableType(this Type type, bool isNullable = false)
101
    {
102
        bool isValueType = type.IsValueType;
×
103

104
        var typeString = type.ToType();
×
105

106
        if (!isValueType || !isNullable)
×
107
            return typeString;
×
108

109
        return typeString.EndsWith('?') ? typeString : typeString + "?";
×
110
    }
111

112
    public static bool IsValueType(this string? type)
113
    {
114
        if (string.IsNullOrEmpty(type))
×
115
            return false;
×
116

117
        if (!type.StartsWith("System."))
×
118
            return false;
×
119

120
        var t = Type.GetType(type, false);
×
121
        return t != null && t.IsValueType;
×
122
    }
123

124
    public static string ToLiteral(this string value)
125
    {
126
        ArgumentException.ThrowIfNullOrEmpty(value);
662✔
127

128
        return value.Contains('\n') || value.Contains('\r')
662!
129
            ? "@\"" + value.Replace("\"", "\"\"") + "\""
662✔
130
            : "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
662✔
131
    }
132

133

134

135
    private static void ProcessType(StringBuilder builder, Type type)
136
    {
137
        if (type.IsGenericType)
247✔
138
        {
139
            var genericArguments = type.GetGenericArguments();
6✔
140
            ProcessGenericType(builder, type, genericArguments, genericArguments.Length);
6✔
141
        }
142
        else if (type.IsArray)
241✔
143
        {
144
            ProcessArrayType(builder, type);
18✔
145
        }
146
        else if (_csharpTypeAlias.TryGetValue(type, out var builtInName))
223✔
147
        {
148
            builder.Append(builtInName);
153✔
149
        }
150
        else if (type.Namespace.HasValue() && _defaultNamespaces.Contains(type.Namespace))
70✔
151
        {
152
            builder.Append(type.Name);
66✔
153
        }
154
        else
155
        {
156
            builder.Append(type.FullName ?? type.Name);
4!
157
        }
158
    }
4✔
159

160
    private static void ProcessArrayType(StringBuilder builder, Type type)
161
    {
162
        var innerType = type;
18✔
163
        while (innerType.IsArray)
37✔
164
        {
165
            innerType = innerType.GetElementType()!;
19✔
166
        }
167

168
        ProcessType(builder, innerType);
18✔
169

170
        while (type.IsArray)
37✔
171
        {
172
            builder.Append('[');
19✔
173
            builder.Append(',', type.GetArrayRank() - 1);
19✔
174
            builder.Append(']');
19✔
175
            type = type.GetElementType()!;
19✔
176
        }
177
    }
18✔
178

179
    private static void ProcessGenericType(StringBuilder builder, Type type, Type[] genericArguments, int length)
180
    {
181
        if (type.IsConstructedGenericType
6!
182
            && type.GetGenericTypeDefinition() == typeof(Nullable<>))
6✔
183
        {
184
            ProcessType(builder, type.GetUnderlyingType());
×
185
            builder.Append('?');
×
186
            return;
×
187
        }
188

189
        var offset = type.DeclaringType != null ? type.DeclaringType.GetGenericArguments().Length : 0;
6!
190
        var genericPartIndex = type.Name.IndexOf('`');
6✔
191
        if (genericPartIndex <= 0)
6!
192
        {
NEW
193
            if (type.Namespace.HasValue() && _defaultNamespaces.Contains(type.Namespace))
×
194
            {
NEW
195
                builder.Append(type.Name);
×
196
            }
197
            else
198
            {
NEW
199
                builder.Append(type.FullName ?? type.Name);
×
200
            }
201
            return;
×
202
        }
203

204
        if (type.Namespace.HasValue() && !_defaultNamespaces.Contains(type.Namespace))
6!
205
        {
NEW
206
            builder.Append(type.Namespace);
×
NEW
207
            builder.Append(".");
×
208
        }
209
        builder.Append(type.Name, 0, genericPartIndex);
6✔
210
        builder.Append('<');
6✔
211

212
        for (var i = offset; i < length; i++)
28✔
213
        {
214
            ProcessType(builder, genericArguments[i]);
8✔
215
            if (i + 1 == length)
8✔
216
            {
217
                continue;
218
            }
219

220
            builder.Append(',');
2✔
221
            if (!genericArguments[i + 1].IsGenericParameter)
2✔
222
            {
223
                builder.Append(' ');
2✔
224
            }
225
        }
226

227
        builder.Append('>');
6✔
228
    }
6✔
229
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc