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

loresoft / EntityFrameworkCore.Generator / 15284929111

27 May 2025 08:21PM UTC coverage: 55.036% (+0.2%) from 54.862%
15284929111

push

github

pwelter34
remove VB support, cleanup ToType

638 of 1315 branches covered (48.52%)

Branch coverage included in aggregate %.

65 of 83 new or added lines in 4 files covered. (78.31%)

1859 of 3222 relevant lines covered (57.7%)

61.23 hits per line

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

71.82
/src/EntityFrameworkCore.Generator.Core/Parsing/MappingVisitor.cs
1
using EntityFrameworkCore.Generator.Metadata.Parsing;
2

3
using Microsoft.CodeAnalysis.CSharp;
4
using Microsoft.CodeAnalysis.CSharp.Syntax;
5

6
namespace EntityFrameworkCore.Generator.Parsing;
7

8
public class MappingVisitor : CSharpSyntaxWalker
9
{
10
    private ParsedProperty? _currentProperty;
11
    private ParsedRelationship? _currentRelationship;
12

13

14
    public MappingVisitor()
11✔
15
    {
16
        MappingBaseType = "IEntityTypeConfiguration";
11✔
17
    }
11✔
18

19
    public string MappingBaseType { get; set; }
22✔
20

21
    public ParsedEntity? ParsedEntity { get; set; }
436✔
22

23

24
    public override void VisitClassDeclaration(ClassDeclarationSyntax node)
25
    {
26
        ParseClassNames(node);
11✔
27
        base.VisitClassDeclaration(node);
11✔
28
    }
11✔
29

30
    public override void VisitInvocationExpression(InvocationExpressionSyntax node)
31
    {
32

33
        var methodName = ParseMethodName(node);
522!
34

35
        switch (methodName)
36
        {
37
            case "HasConstraintName":
38
                ParseConstraintName(node);
7✔
39
                break;
7✔
40
            case "HasForeignKey":
41
                ParseForeignKey(node);
6✔
42
                break;
6✔
43
            case "WithMany":
44
            case "WithOne":
45
                ParseWithMany(node);
7✔
46
                break;
7✔
47
            case "HasMany":
48
            case "HasOne":
49
                ParseHasOne(node);
7✔
50
                break;
7✔
51
            case "HasColumnName":
52
                ParseColumnName(node);
105✔
53
                break;
105✔
54
            case "Property":
55
                ParseProperty(node);
105✔
56
                break;
105✔
57
            case "ToTable":
58
            case "ToView":
59
                ParseTable(node);
11✔
60
                break;
61
        }
62

63
        base.VisitInvocationExpression(node);
522✔
64
    }
522✔
65

66

67
    private static string ParseMethodName(InvocationExpressionSyntax node)
68
    {
69
        var memberAccess = node
522✔
70
            .ChildNodes()
522✔
71
            .OfType<MemberAccessExpressionSyntax>()
522✔
72
            .FirstOrDefault();
522✔
73

74
        if (memberAccess == null)
522!
75
            return string.Empty;
×
76

77
        var methodName = memberAccess
522✔
78
            .ChildNodes()
522✔
79
            .OfType<IdentifierNameSyntax>()
522✔
80
            .Select(s => s.Identifier.ValueText)
655✔
81
            .LastOrDefault();
522✔
82

83
        return methodName ?? string.Empty;
522✔
84
    }
85

86
    private static string? ParseLambaExpression(InvocationExpressionSyntax node)
87
    {
88
        if (node == null)
125!
89
            return null;
×
90

91
        var lambaExpression = node
125✔
92
            .ArgumentList
125✔
93
            .DescendantNodes()
125✔
94
            .OfType<LambdaExpressionSyntax>()
125✔
95
            .FirstOrDefault();
125✔
96

97
        if (lambaExpression == null)
125!
98
            return null;
×
99

100
        var simpleExpression = lambaExpression
125✔
101
            .ChildNodes()
125✔
102
            .OfType<MemberAccessExpressionSyntax>()
125✔
103
            .FirstOrDefault();
125✔
104

105
        if (simpleExpression == null)
125!
106
            return null;
×
107

108
        var propertyName = simpleExpression
125✔
109
            .ChildNodes()
125✔
110
            .OfType<IdentifierNameSyntax>()
125✔
111
            .Select(s => s.Identifier.ValueText)
250✔
112
            .LastOrDefault();
125✔
113

114
        return propertyName;
125✔
115
    }
116

117
    private List<string>? ParseLambdaExpressionForAnonymousObject(InvocationExpressionSyntax node)
118
    {
119
        if (node == null)
×
120
            return null;
×
121

122
        var lambdaExpression = node
×
123
            .ArgumentList
×
124
            .DescendantNodes()
×
125
            .OfType<LambdaExpressionSyntax>()
×
126
            .FirstOrDefault();
×
127

128
        if (lambdaExpression == null)
×
129
            return null;
×
130

131
        var anonymousObject = lambdaExpression
×
132
            .ChildNodes()
×
133
            .OfType<AnonymousObjectCreationExpressionSyntax>()
×
134
            .FirstOrDefault();
×
135

136
        if (anonymousObject == null)
×
137
            return null;
×
138

NEW
139
        return anonymousObject
×
140
            .ChildNodes()
×
141
            .OfType<AnonymousObjectMemberDeclaratorSyntax>()
×
142
            .Select(declarator => declarator
×
143
                .ChildNodes()
×
144
                .OfType<MemberAccessExpressionSyntax>()
×
145
                .FirstOrDefault())
×
NEW
146
            .OfType<MemberAccessExpressionSyntax>()
×
147
            .Select(memberAccess => memberAccess
×
148
                .ChildNodes()
×
149
                .OfType<IdentifierNameSyntax>()
×
150
                .Select(identifier => identifier.Identifier.ValueText)
×
151
                .LastOrDefault())
×
NEW
152
            .OfType<string>()
×
153
            .ToList();
×
154
    }
155

156
    private void ParseHasOne(InvocationExpressionSyntax node)
157
    {
158
        if (node == null || ParsedEntity == null)
7!
159
            return;
×
160

161
        _currentRelationship ??= new ParsedRelationship();
7!
162

163
        var propertyName = ParseLambaExpression(node);
7✔
164
        if (!string.IsNullOrEmpty(propertyName))
7✔
165
            _currentRelationship.PropertyName = propertyName;
7✔
166

167
        // add and reset current relationship
168
        if (_currentRelationship.IsValid())
7✔
169
            ParsedEntity.Relationships.Add(_currentRelationship);
6✔
170

171
        _currentRelationship = null;
7✔
172
    }
7✔
173

174
    private void ParseWithMany(InvocationExpressionSyntax node)
175
    {
176
        if (node == null || ParsedEntity == null)
7!
177
            return;
×
178

179
        var propertyName = ParseLambaExpression(node);
7✔
180
        if (string.IsNullOrEmpty(propertyName))
7!
181
            return;
×
182

183
        _currentRelationship ??= new ParsedRelationship();
7!
184
        _currentRelationship.PrimaryPropertyName = propertyName;
7✔
185
    }
7✔
186

187
    private void ParseForeignKey(InvocationExpressionSyntax node)
188
    {
189
        if (node == null || ParsedEntity == null)
6!
190
            return;
×
191

192
        List<string>? propertyNames = null;
6✔
193
        if (ParseLambaExpression(node) is string propertyName && !string.IsNullOrEmpty(propertyName))
6!
194
            propertyNames = [propertyName];
6✔
195
        else
196
            propertyNames = ParseLambdaExpressionForAnonymousObject(node);
×
197

198
        if (propertyNames == null)
6!
199
            return;
×
200

201
        _currentRelationship ??= new ParsedRelationship();
6!
202
        _currentRelationship.Properties.AddRange(propertyNames);
6✔
203
    }
6✔
204

205
    private void ParseConstraintName(InvocationExpressionSyntax node)
206
    {
207
        if (node == null || ParsedEntity == null)
7!
208
            return;
×
209

210
        var constraitName = node
7✔
211
            .ArgumentList
7✔
212
            .DescendantNodes()
7✔
213
            .OfType<LiteralExpressionSyntax>()
7✔
214
            .Select(t => t.Token.ValueText)
7✔
215
            .FirstOrDefault();
7✔
216

217
        _currentRelationship ??= new ParsedRelationship();
7✔
218
        _currentRelationship.RelationshipName = constraitName;
7✔
219
    }
7✔
220

221

222
    private void ParseProperty(InvocationExpressionSyntax node)
223
    {
224
        if (node == null || _currentProperty == null || ParsedEntity == null)
105!
225
            return;
×
226

227
        var propertyName = ParseLambaExpression(node);
105✔
228
        if (!string.IsNullOrEmpty(propertyName))
105✔
229
            _currentProperty.PropertyName = propertyName;
105✔
230

231
        // add and reset current property
232
        if (_currentProperty.IsValid())
105✔
233
            ParsedEntity.Properties.Add(_currentProperty);
105✔
234

235
        _currentProperty = null;
105✔
236
    }
105✔
237

238
    private void ParseColumnName(InvocationExpressionSyntax node)
239
    {
240
        if (node == null || ParsedEntity == null)
105!
241
            return;
×
242

243
        var columnName = node
105✔
244
            .ArgumentList
105✔
245
            .DescendantNodes()
105✔
246
            .OfType<LiteralExpressionSyntax>()
105✔
247
            .Select(t => t.Token.ValueText)
105✔
248
            .FirstOrDefault();
105✔
249

250
        if (string.IsNullOrEmpty(columnName))
105!
251
            return;
×
252

253
        _currentProperty = new ParsedProperty { ColumnName = columnName };
105✔
254
    }
105✔
255

256
    private void ParseTable(InvocationExpressionSyntax node)
257
    {
258
        if (node == null || ParsedEntity == null)
11!
259
            return;
×
260

261
        var arguments = node
11✔
262
            .ArgumentList
11✔
263
            .DescendantNodes()
11✔
264
            .OfType<LiteralExpressionSyntax>()
11✔
265
            .Select(t => t.Token.ValueText)
22✔
266
            .ToList();
11✔
267

268
        if (arguments.Count == 0)
11!
269
            return;
×
270

271
        if (arguments.Count >= 1)
11✔
272
            ParsedEntity.TableName = arguments[0];
11✔
273

274
        if (arguments.Count >= 2)
11✔
275
            ParsedEntity.TableSchema = arguments[1];
11✔
276
    }
11✔
277

278
    private void ParseClassNames(ClassDeclarationSyntax node)
279
    {
280
        if (node == null)
11!
281
            return;
×
282

283
        var baseType = node.BaseList
11!
284
            ?.DescendantNodes()
11✔
285
            .OfType<GenericNameSyntax>()
11✔
286
            .FirstOrDefault(t => t.Identifier.ValueText == MappingBaseType);
22✔
287

288
        if (baseType == null)
11!
289
            return;
×
290

291
        var firstArgument = baseType
11✔
292
            .TypeArgumentList
11✔
293
            .Arguments
11✔
294
            .FirstOrDefault();
11✔
295

296
        if (firstArgument == null)
11!
297
            return;
×
298

299
        // last identifier is class name
300
        var entityClass = firstArgument
11✔
301
            .DescendantNodesAndSelf()
11✔
302
            .OfType<IdentifierNameSyntax>()
11✔
303
            .Select(s => s.Identifier.ValueText)
44✔
304
            .LastOrDefault();
11✔
305

306
        var mappingClass = node.Identifier.Text;
11✔
307

308
        if (string.IsNullOrEmpty(entityClass) || string.IsNullOrEmpty(mappingClass))
11!
309
            return;
×
310

311
        if (ParsedEntity == null)
11✔
312
            ParsedEntity = new ParsedEntity();
11✔
313

314
        ParsedEntity.MappingClass = mappingClass;
11✔
315
        ParsedEntity.EntityClass = entityClass;
11✔
316
    }
11✔
317
}
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

© 2026 Coveralls, Inc