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

loresoft / EntityFrameworkCore.Generator / 15072048022

16 May 2025 03:31PM UTC coverage: 55.392% (-1.4%) from 56.772%
15072048022

push

github

pwelter34
enable nullable support

616 of 1271 branches covered (48.47%)

Branch coverage included in aggregate %.

233 of 397 new or added lines in 61 files covered. (58.69%)

17 existing lines in 11 files now uncovered.

1824 of 3134 relevant lines covered (58.2%)

88.56 hits per line

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

81.18
/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()
22✔
15
    {
16
        MappingBaseType = "IEntityTypeConfiguration";
22✔
17
    }
22✔
18

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

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

23

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

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

33
        var methodName = ParseMethodName(node);
1,044!
34

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

63
        base.VisitInvocationExpression(node);
1,044✔
64
    }
1,044✔
65

66

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

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

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

83
        return methodName ?? string.Empty;
1,044✔
84
    }
85

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

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

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

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

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

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

114
        return propertyName;
250✔
115
    }
116

117

118
    private void ParseHasOne(InvocationExpressionSyntax node)
119
    {
120
        if (node == null || ParsedEntity == null)
14!
121
            return;
×
122

123
        _currentRelationship ??= new ParsedRelationship();
14!
124

125
        var propertyName = ParseLambaExpression(node);
14✔
126
        if (!string.IsNullOrEmpty(propertyName))
14✔
127
            _currentRelationship.PropertyName = propertyName;
14✔
128

129
        // add and reset current relationship
130
        if (_currentRelationship.IsValid())
14✔
131
            ParsedEntity.Relationships.Add(_currentRelationship);
12✔
132

133
        _currentRelationship = null;
14✔
134
    }
14✔
135

136
    private void ParseWithMany(InvocationExpressionSyntax node)
137
    {
138
        if (node == null || ParsedEntity == null)
14!
139
            return;
×
140

141
        var propertyName = ParseLambaExpression(node);
14✔
142
        if (string.IsNullOrEmpty(propertyName))
14!
143
            return;
×
144

145
        _currentRelationship ??= new ParsedRelationship();
14!
146
        _currentRelationship.PrimaryPropertyName = propertyName;
14✔
147
    }
14✔
148

149
    private void ParseForeignKey(InvocationExpressionSyntax node)
150
    {
151
        if (node == null || ParsedEntity == null)
12!
152
            return;
×
153

154
        var propertyName = ParseLambaExpression(node);
12✔
155

156
        if (string.IsNullOrEmpty(propertyName))
12!
157
            return;
×
158

159
        _currentRelationship ??= new ParsedRelationship();
12!
160
        _currentRelationship.Properties.Add(propertyName);
12✔
161
    }
12✔
162

163
    private void ParseConstraintName(InvocationExpressionSyntax node)
164
    {
165
        if (node == null || ParsedEntity == null)
14!
166
            return;
×
167

168
        var constraitName = node
14✔
169
            .ArgumentList
14✔
170
            .DescendantNodes()
14✔
171
            .OfType<LiteralExpressionSyntax>()
14✔
172
            .Select(t => t.Token.ValueText)
14✔
173
            .FirstOrDefault();
14✔
174

175
        _currentRelationship ??= new ParsedRelationship();
14✔
176
        _currentRelationship.RelationshipName = constraitName;
14✔
177
    }
14✔
178

179

180
    private void ParseProperty(InvocationExpressionSyntax node)
181
    {
182
        if (node == null || _currentProperty == null || ParsedEntity == null)
210!
183
            return;
×
184

185
        var propertyName = ParseLambaExpression(node);
210✔
186
        if (!string.IsNullOrEmpty(propertyName))
210✔
187
            _currentProperty.PropertyName = propertyName;
210✔
188

189
        // add and reset current property
190
        if (_currentProperty.IsValid())
210✔
191
            ParsedEntity.Properties.Add(_currentProperty);
210✔
192

193
        _currentProperty = null;
210✔
194
    }
210✔
195

196
    private void ParseColumnName(InvocationExpressionSyntax node)
197
    {
198
        if (node == null || ParsedEntity == null)
210!
199
            return;
×
200

201
        var columnName = node
210✔
202
            .ArgumentList
210✔
203
            .DescendantNodes()
210✔
204
            .OfType<LiteralExpressionSyntax>()
210✔
205
            .Select(t => t.Token.ValueText)
210✔
206
            .FirstOrDefault();
210✔
207

208
        if (string.IsNullOrEmpty(columnName))
210!
209
            return;
×
210

211
        _currentProperty = new ParsedProperty { ColumnName = columnName };
210✔
212
    }
210✔
213

214
    private void ParseTable(InvocationExpressionSyntax node)
215
    {
216
        if (node == null || ParsedEntity == null)
22!
217
            return;
×
218

219
        var arguments = node
22✔
220
            .ArgumentList
22✔
221
            .DescendantNodes()
22✔
222
            .OfType<LiteralExpressionSyntax>()
22✔
223
            .Select(t => t.Token.ValueText)
44✔
224
            .ToList();
22✔
225

226
        if (arguments.Count == 0)
22!
227
            return;
×
228

229
        if (arguments.Count >= 1)
22✔
230
            ParsedEntity.TableName = arguments[0];
22✔
231

232
        if (arguments.Count >= 2)
22✔
233
            ParsedEntity.TableSchema = arguments[1];
22✔
234
    }
22✔
235

236
    private void ParseClassNames(ClassDeclarationSyntax node)
237
    {
238
        if (node == null)
22!
239
            return;
×
240

241
        var baseType = node.BaseList
22!
242
            ?.DescendantNodes()
22✔
243
            .OfType<GenericNameSyntax>()
22✔
244
            .FirstOrDefault(t => t.Identifier.ValueText == MappingBaseType);
44✔
245

246
        if (baseType == null)
22!
247
            return;
×
248

249
        var firstArgument = baseType
22✔
250
            .TypeArgumentList
22✔
251
            .Arguments
22✔
252
            .FirstOrDefault();
22✔
253

254
        if (firstArgument == null)
22!
NEW
255
            return;
×
256

257
        // last identifier is class name
258
        var entityClass = firstArgument
22✔
259
            .DescendantNodesAndSelf()
22✔
260
            .OfType<IdentifierNameSyntax>()
22✔
261
            .Select(s => s.Identifier.ValueText)
88✔
262
            .LastOrDefault();
22✔
263

264
        var mappingClass = node.Identifier.Text;
22✔
265

266
        if (string.IsNullOrEmpty(entityClass) || string.IsNullOrEmpty(mappingClass))
22!
267
            return;
×
268

269
        if (ParsedEntity == null)
22✔
270
            ParsedEntity = new ParsedEntity();
22✔
271

272
        ParsedEntity.MappingClass = mappingClass;
22✔
273
        ParsedEntity.EntityClass = entityClass;
22✔
274
    }
22✔
275
}
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