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

lucaslorentz / auto-compute / 18248126920

04 Oct 2025 06:41PM UTC coverage: 83.401% (-0.2%) from 83.552%
18248126920

push

github

lucaslorentz
Add EmptyEntityContext that doesn't track

0 of 5 new or added lines in 2 files covered. (0.0%)

1849 of 2217 relevant lines covered (83.4%)

863.13 hits per line

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

75.51
/src/LLL.AutoCompute/EntityContextPropagators/LinqMethodsEntityContextPropagator.cs
1
using System.Linq.Expressions;
2
using LLL.AutoCompute.EntityContexts;
3
using LLL.AutoCompute.EntityContextTransformers;
4

5
namespace LLL.AutoCompute.EntityContextPropagators;
6

7
public class LinqMethodsEntityContextPropagator(Lazy<IObservedEntityTypeResolver?> entityTypeResolver)
20✔
8
    : IEntityContextPropagator
9
{
10
    public void PropagateEntityContext(
11
        Expression node,
12
        IComputedExpressionAnalysis analysis)
13
    {
14
        if (node is MethodCallExpression methodCallExpression)
3,384✔
15
        {
16
            if (methodCallExpression.Method.DeclaringType == typeof(Enumerable) || methodCallExpression.Method.DeclaringType == typeof(Queryable))
248✔
17
            {
18
                foreach (var arg in methodCallExpression.Arguments.Skip(1))
800✔
19
                {
20
                    if (GetLambda(arg) is LambdaExpression lambda)
174✔
21
                    {
22
                        foreach (var param in lambda.Parameters)
584✔
23
                        {
24
                            analysis.PropagateEntityContext(
146✔
25
                                methodCallExpression.Arguments[0],
146✔
26
                                EntityContextKeys.Element,
146✔
27
                                param,
146✔
28
                                EntityContextKeys.None,
146✔
29
                                new ScopedEntityContextTransformer()
146✔
30
                            );
146✔
31
                        }
32
                    }
33
                }
34

35
                switch (methodCallExpression.Method.Name)
226✔
36
                {
37
                    case nameof(Enumerable.All):
38
                    case nameof(Enumerable.Any):
39
                    case nameof(Enumerable.Contains):
40
                        analysis.AddAction(() =>
4✔
41
                        {
4✔
42
                            var entityContext = analysis.ResolveEntityContext(methodCallExpression.Arguments[0], EntityContextKeys.Element);
8✔
43
                            entityContext.MarkNavigationToLoadAll();
8✔
44
                        });
4✔
45
                        break;
4✔
46

47
                    case nameof(Enumerable.AsEnumerable):
48
                    case nameof(Enumerable.Cast):
49
                    case nameof(Enumerable.DefaultIfEmpty):
50
                    case nameof(Enumerable.OfType):
51
                    case nameof(Enumerable.Order):
52
                    case nameof(Enumerable.OrderBy):
53
                    case nameof(Enumerable.OrderByDescending):
54
                    case nameof(Enumerable.Reverse):
55
                    case nameof(Enumerable.Skip):
56
                    case nameof(Enumerable.SkipLast):
57
                    case nameof(Enumerable.SkipWhile):
58
                    case nameof(Enumerable.Take):
59
                    case nameof(Enumerable.TakeLast):
60
                    case nameof(Enumerable.TakeWhile):
61
                    case nameof(Enumerable.ThenBy):
62
                    case nameof(Enumerable.ThenByDescending):
63
                    case nameof(Enumerable.ToArray):
64
                    case nameof(Enumerable.ToList):
65
                    case nameof(Enumerable.ToHashSet):
66
                        analysis.PropagateEntityContext(
6✔
67
                            methodCallExpression.Arguments[0],
6✔
68
                            EntityContextKeys.Element,
6✔
69
                            node,
6✔
70
                            EntityContextKeys.Element
6✔
71
                        );
6✔
72
                        break;
6✔
73

74
                    case nameof(Enumerable.Distinct):
75
                    case nameof(Enumerable.DistinctBy):
76
                        analysis.PropagateEntityContext(
4✔
77
                            methodCallExpression.Arguments[0],
4✔
78
                            EntityContextKeys.Element,
4✔
79
                            node,
4✔
80
                            EntityContextKeys.Element,
4✔
81
                            new DistinctEntityContextTransformer()
4✔
82
                        );
4✔
83
                        break;
4✔
84

85
                    case nameof(Enumerable.Where):
86
                        {
87
                            analysis.PropagateEntityContext(
74✔
88
                                methodCallExpression.Arguments[0],
74✔
89
                                EntityContextKeys.Element,
74✔
90
                                node,
74✔
91
                                EntityContextKeys.Element
74✔
92
                            );
74✔
93
                        }
94
                        break;
74✔
95

96
                    case nameof(Enumerable.ElementAt):
97
                    case nameof(Enumerable.ElementAtOrDefault):
98
                    case nameof(Enumerable.First):
99
                    case nameof(Enumerable.FirstOrDefault):
100
                    case nameof(Enumerable.Last):
101
                    case nameof(Enumerable.LastOrDefault):
102
                    case nameof(Enumerable.Single):
103
                    case nameof(Enumerable.SingleOrDefault):
104
                        analysis.PropagateEntityContext(
×
105
                            methodCallExpression.Arguments[0],
×
106
                            EntityContextKeys.Element,
×
107
                            node,
×
108
                            EntityContextKeys.None
×
109
                        );
×
110
                        break;
×
111

112
                    case nameof(Enumerable.Append):
113
                        analysis.PropagateEntityContext(
×
114
                            [
×
115
                                (methodCallExpression.Arguments[0], EntityContextKeys.Element),
×
116
                                (methodCallExpression.Arguments[1], EntityContextKeys.None),
×
117
                            ],
×
118
                            node,
×
119
                            EntityContextKeys.Element
×
120
                        );
×
121
                        break;
×
122

123
                    case nameof(Enumerable.Concat):
124
                    case nameof(Enumerable.Except):
125
                    case nameof(Enumerable.ExceptBy):
126
                    case nameof(Enumerable.Intersect):
127
                    case nameof(Enumerable.IntersectBy):
128
                        analysis.PropagateEntityContext(
28✔
129
                            [
28✔
130
                                (methodCallExpression.Arguments[0], EntityContextKeys.Element),
28✔
131
                                (methodCallExpression.Arguments[1], EntityContextKeys.Element),
28✔
132
                            ],
28✔
133
                            node,
28✔
134
                            EntityContextKeys.Element
28✔
135
                        );
28✔
136
                        break;
28✔
137

138
                    case nameof(Enumerable.ToDictionary):
139
                        {
140
                            if (methodCallExpression.Arguments is [_, var keySelector, ..]
4✔
141
                                && GetLambda(keySelector) is LambdaExpression lambda)
4✔
142
                            {
143
                                analysis.PropagateEntityContext(
4✔
144
                                    lambda.Body,
4✔
145
                                    EntityContextKeys.None,
4✔
146
                                    node,
4✔
147
                                    EntityContextKeys.Element + EntityContextKeys.Key
4✔
148
                                );
4✔
149
                            }
150

151
                            if (methodCallExpression.Arguments is [_, _, var valueSelector, ..]
4✔
152
                                && GetLambda(valueSelector) is LambdaExpression valueLambda)
4✔
153
                            {
154
                                analysis.PropagateEntityContext(
×
155
                                    valueLambda.Body,
×
156
                                    EntityContextKeys.Element,
×
157
                                    node,
×
158
                                    EntityContextKeys.Element + EntityContextKeys.Value
×
159
                                );
×
160
                            }
161
                            else if (methodCallExpression.Arguments is [var source, ..])
4✔
162
                            {
163
                                analysis.PropagateEntityContext(
4✔
164
                                    source,
4✔
165
                                    EntityContextKeys.Element,
4✔
166
                                    node,
4✔
167
                                    EntityContextKeys.Element + EntityContextKeys.Value
4✔
168
                                );
4✔
169
                            }
170
                        }
171
                        break;
4✔
172

173
                    case nameof(Enumerable.GroupBy):
174
                    case nameof(Enumerable.ToLookup):
175
                        {
176
                            if (methodCallExpression.Arguments is [_, var keySelector, ..]
4✔
177
                                && GetLambda(keySelector) is LambdaExpression lambda)
4✔
178
                            {
179
                                analysis.PropagateEntityContext(
4✔
180
                                    lambda.Body,
4✔
181
                                    EntityContextKeys.None,
4✔
182
                                    node,
4✔
183
                                    EntityContextKeys.Element + EntityContextKeys.Key
4✔
184
                                );
4✔
185
                            }
186

187
                            if (methodCallExpression.Arguments is [_, _, var valueSelector, ..]
4✔
188
                                && GetLambda(valueSelector) is LambdaExpression valueLambda)
4✔
189
                            {
190
                                analysis.PropagateEntityContext(
×
191
                                    valueLambda.Body,
×
192
                                    EntityContextKeys.None,
×
193
                                    node,
×
194
                                    EntityContextKeys.Element + EntityContextKeys.Element
×
195
                                );
×
196
                            }
197
                            else if (methodCallExpression.Arguments is [var source, ..])
4✔
198
                            {
199
                                analysis.PropagateEntityContext(
4✔
200
                                    source,
4✔
201
                                    EntityContextKeys.Element,
4✔
202
                                    node,
4✔
203
                                    EntityContextKeys.Element + EntityContextKeys.Element
4✔
204
                                );
4✔
205
                            }
206
                        }
207
                        break;
4✔
208

209
                    case nameof(Enumerable.Select):
210
                        {
211
                            if (methodCallExpression.Arguments is [_, var selector, ..]
10✔
212
                                && GetLambda(selector) is LambdaExpression selectorLambda)
10✔
213
                            {
214
                                analysis.PropagateEntityContext(
10✔
215
                                    selectorLambda.Body,
10✔
216
                                    EntityContextKeys.None,
10✔
217
                                    node,
10✔
218
                                    EntityContextKeys.Element
10✔
219
                                );
10✔
220
                            }
221
                        }
222
                        break;
10✔
223

224
                    case nameof(Enumerable.SelectMany):
225
                        {
226
                            if (methodCallExpression.Arguments is [_, var selector, ..]
4✔
227
                                && GetLambda(selector) is LambdaExpression selectorLambda)
4✔
228
                            {
229
                                analysis.PropagateEntityContext(
4✔
230
                                    selectorLambda.Body,
4✔
231
                                    EntityContextKeys.Element,
4✔
232
                                    node,
4✔
233
                                    EntityContextKeys.Element
4✔
234
                                );
4✔
235
                            }
236
                        }
237
                        break;
4✔
238

239
                    case nameof(Enumerable.Empty):
240
                        var elementType = methodCallExpression.Method.GetGenericArguments().First();
×
241
                        var observedEntityType = entityTypeResolver.Value?.Resolve(elementType);
×
242
                        if (observedEntityType is not null)
×
243
                        {
244
                            analysis.AddContext(
×
245
                                node,
×
246
                                EntityContextKeys.Element,
×
NEW
247
                                new EmptyEntityContext(node, observedEntityType)
×
248
                            );
×
249
                        }
250
                        break;
251
                }
252
            }
253
        }
254
    }
255

256
    private static LambdaExpression? GetLambda(Expression expression)
257
    {
258
        return expression switch
196✔
259
        {
196✔
260
            LambdaExpression lambda => lambda,
364✔
261
            ConstantExpression { Value: LambdaExpression lambda } => lambda,
196✔
262
            _ => null
224✔
263
        };
196✔
264
    }
265
}
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