Skip to content

Commit 5d164f0

Browse files
author
Bart Koelman
committed
Changed IncludeExpression.Elements type and IncludeElementExpression.Children type from IReadOnlyCollection to IImmutableList
1 parent d56c7d3 commit 5d164f0

15 files changed

+57
-71
lines changed

src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ public IncludeExpression FromRelationshipChains(IEnumerable<ResourceFieldChainEx
6868
{
6969
ArgumentGuard.NotNull(chains, nameof(chains));
7070

71-
IReadOnlyCollection<IncludeElementExpression> elements = ConvertChainsToElements(chains);
71+
IImmutableList<IncludeElementExpression> elements = ConvertChainsToElements(chains);
7272
return elements.Any() ? new IncludeExpression(elements) : IncludeExpression.Empty;
7373
}
7474

75-
private static IReadOnlyCollection<IncludeElementExpression> ConvertChainsToElements(IEnumerable<ResourceFieldChainExpression> chains)
75+
private static IImmutableList<IncludeElementExpression> ConvertChainsToElements(IEnumerable<ResourceFieldChainExpression> chains)
7676
{
7777
var rootNode = new MutableIncludeNode(null);
7878

@@ -81,7 +81,7 @@ private static IReadOnlyCollection<IncludeElementExpression> ConvertChainsToElem
8181
ConvertChainToElement(chain, rootNode);
8282
}
8383

84-
return rootNode.Children.Values.Select(child => child.ToExpression()).ToArray();
84+
return rootNode.Children.Values.Select(child => child.ToExpression()).ToImmutableArray();
8585
}
8686

8787
private static void ConvertChainToElement(ResourceFieldChainExpression chain, MutableIncludeNode rootNode)
@@ -161,7 +161,7 @@ public MutableIncludeNode(RelationshipAttribute relationship)
161161

162162
public IncludeElementExpression ToExpression()
163163
{
164-
IncludeElementExpression[] elementChildren = Children.Values.Select(child => child.ToExpression()).ToArray();
164+
ImmutableArray<IncludeElementExpression> elementChildren = Children.Values.Select(child => child.ToExpression()).ToImmutableArray();
165165
return new IncludeElementExpression(_relationship, elementChildren);
166166
}
167167
}

src/JsonApiDotNetCore/Queries/Expressions/IncludeElementExpression.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
2+
using System.Collections.Immutable;
33
using System.Linq;
44
using System.Text;
55
using JetBrains.Annotations;
@@ -14,14 +14,14 @@ namespace JsonApiDotNetCore.Queries.Expressions
1414
public class IncludeElementExpression : QueryExpression
1515
{
1616
public RelationshipAttribute Relationship { get; }
17-
public IReadOnlyCollection<IncludeElementExpression> Children { get; }
17+
public IImmutableList<IncludeElementExpression> Children { get; }
1818

1919
public IncludeElementExpression(RelationshipAttribute relationship)
20-
: this(relationship, Array.Empty<IncludeElementExpression>())
20+
: this(relationship, ImmutableArray<IncludeElementExpression>.Empty)
2121
{
2222
}
2323

24-
public IncludeElementExpression(RelationshipAttribute relationship, IReadOnlyCollection<IncludeElementExpression> children)
24+
public IncludeElementExpression(RelationshipAttribute relationship, IImmutableList<IncludeElementExpression> children)
2525
{
2626
ArgumentGuard.NotNull(relationship, nameof(relationship));
2727
ArgumentGuard.NotNull(children, nameof(children));

src/JsonApiDotNetCore/Queries/Expressions/IncludeExpression.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45
using JetBrains.Annotations;
56

@@ -15,9 +16,9 @@ public class IncludeExpression : QueryExpression
1516

1617
public static readonly IncludeExpression Empty = new();
1718

18-
public IReadOnlyCollection<IncludeElementExpression> Elements { get; }
19+
public IImmutableList<IncludeElementExpression> Elements { get; }
1920

20-
public IncludeExpression(IReadOnlyCollection<IncludeElementExpression> elements)
21+
public IncludeExpression(IImmutableList<IncludeElementExpression> elements)
2122
{
2223
ArgumentGuard.NotNullNorEmpty(elements, nameof(elements));
2324

@@ -26,7 +27,7 @@ public IncludeExpression(IReadOnlyCollection<IncludeElementExpression> elements)
2627

2728
private IncludeExpression()
2829
{
29-
Elements = Array.Empty<IncludeElementExpression>();
30+
Elements = ImmutableArray<IncludeElementExpression>.Empty;
3031
}
3132

3233
public override TResult Accept<TArgument, TResult>(QueryExpressionVisitor<TArgument, TResult> visitor, TArgument argument)

src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System.Collections.Generic;
21
using System.Collections.Immutable;
3-
using System.Linq;
42
using JetBrains.Annotations;
53
using JsonApiDotNetCore.Configuration;
64

@@ -55,7 +53,7 @@ public override QueryExpression VisitLogical(LogicalExpression expression, TArgu
5553
{
5654
if (expression != null)
5755
{
58-
var newTerms = VisitList(expression.Terms, argument);
56+
IImmutableList<FilterExpression> newTerms = VisitList(expression.Terms, argument);
5957

6058
if (newTerms.Count == 1)
6159
{
@@ -270,7 +268,7 @@ public override QueryExpression VisitInclude(IncludeExpression expression, TArgu
270268
{
271269
if (expression != null)
272270
{
273-
IReadOnlyCollection<IncludeElementExpression> newElements = VisitSequence(expression.Elements, argument);
271+
IImmutableList<IncludeElementExpression> newElements = VisitList(expression.Elements, argument);
274272

275273
if (newElements.Count == 0)
276274
{
@@ -288,7 +286,7 @@ public override QueryExpression VisitIncludeElement(IncludeElementExpression exp
288286
{
289287
if (expression != null)
290288
{
291-
IReadOnlyCollection<IncludeElementExpression> newElements = VisitSequence(expression.Children, argument);
289+
IImmutableList<IncludeElementExpression> newElements = VisitList(expression.Children, argument);
292290

293291
var newExpression = new IncludeElementExpression(expression.Relationship, newElements);
294292
return newExpression.Equals(expression) ? expression : newExpression;
@@ -302,22 +300,6 @@ public override QueryExpression VisitQueryableHandler(QueryableHandlerExpression
302300
return expression;
303301
}
304302

305-
protected virtual IReadOnlyCollection<TExpression> VisitSequence<TExpression>(IEnumerable<TExpression> elements, TArgument argument)
306-
where TExpression : QueryExpression
307-
{
308-
var newElements = new List<TExpression>();
309-
310-
foreach (TExpression element in elements)
311-
{
312-
if (Visit(element, argument) is TExpression newElement)
313-
{
314-
newElements.Add(newElement);
315-
}
316-
}
317-
318-
return newElements;
319-
}
320-
321303
protected virtual IImmutableList<TExpression> VisitList<TExpression>(IImmutableList<TExpression> elements, TArgument argument)
322304
where TExpression : QueryExpression
323305
{

src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ protected IncludeExpression ParseInclude(int? maximumDepth)
5858
return IncludeChainConverter.FromRelationshipChains(chains);
5959
}
6060

61-
private static void ValidateMaximumIncludeDepth(int? maximumDepth, IReadOnlyCollection<ResourceFieldChainExpression> chains)
61+
private static void ValidateMaximumIncludeDepth(int? maximumDepth, IEnumerable<ResourceFieldChainExpression> chains)
6262
{
6363
if (maximumDepth != null)
6464
{

src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,21 @@ private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection<Expre
125125
// @formatter:keep_existing_linebreaks restore
126126
// @formatter:wrap_chained_method_calls restore
127127

128-
IReadOnlyCollection<IncludeElementExpression> includeElements =
128+
IImmutableList<IncludeElementExpression> includeElements =
129129
ProcessIncludeSet(include.Elements, topLayer, new List<RelationshipAttribute>(), constraints);
130130

131131
return !ReferenceEquals(includeElements, include.Elements)
132132
? includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty
133133
: include;
134134
}
135135

136-
private IReadOnlyCollection<IncludeElementExpression> ProcessIncludeSet(IReadOnlyCollection<IncludeElementExpression> includeElements,
137-
QueryLayer parentLayer, ICollection<RelationshipAttribute> parentRelationshipChain, ICollection<ExpressionInScope> constraints)
136+
private IImmutableList<IncludeElementExpression> ProcessIncludeSet(IImmutableList<IncludeElementExpression> includeElements, QueryLayer parentLayer,
137+
ICollection<RelationshipAttribute> parentRelationshipChain, ICollection<ExpressionInScope> constraints)
138138
{
139-
IReadOnlyCollection<IncludeElementExpression> includeElementsEvaluated =
140-
GetIncludeElements(includeElements, parentLayer.ResourceContext) ?? Array.Empty<IncludeElementExpression>();
139+
IImmutableList<IncludeElementExpression> includeElementsEvaluated =
140+
GetIncludeElements(includeElements, parentLayer.ResourceContext) ?? ImmutableArray<IncludeElementExpression>.Empty;
141141

142-
var updatesInChildren = new Dictionary<IncludeElementExpression, IReadOnlyCollection<IncludeElementExpression>>();
142+
var updatesInChildren = new Dictionary<IncludeElementExpression, IImmutableList<IncludeElementExpression>>();
143143

144144
foreach (IncludeElementExpression includeElement in includeElementsEvaluated)
145145
{
@@ -181,7 +181,7 @@ private IReadOnlyCollection<IncludeElementExpression> ProcessIncludeSet(IReadOnl
181181

182182
if (includeElement.Children.Any())
183183
{
184-
IReadOnlyCollection<IncludeElementExpression> updatedChildren =
184+
IImmutableList<IncludeElementExpression> updatedChildren =
185185
ProcessIncludeSet(includeElement.Children, child, relationshipChain, constraints);
186186

187187
if (!ReferenceEquals(includeElement.Children, updatedChildren))
@@ -195,18 +195,19 @@ private IReadOnlyCollection<IncludeElementExpression> ProcessIncludeSet(IReadOnl
195195
return !updatesInChildren.Any() ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren);
196196
}
197197

198-
private static IReadOnlyCollection<IncludeElementExpression> ApplyIncludeElementUpdates(IEnumerable<IncludeElementExpression> includeElements,
199-
IDictionary<IncludeElementExpression, IReadOnlyCollection<IncludeElementExpression>> updatesInChildren)
198+
private static IImmutableList<IncludeElementExpression> ApplyIncludeElementUpdates(IImmutableList<IncludeElementExpression> includeElements,
199+
IDictionary<IncludeElementExpression, IImmutableList<IncludeElementExpression>> updatesInChildren)
200200
{
201-
List<IncludeElementExpression> newIncludeElements = includeElements.ToList();
201+
ImmutableArray<IncludeElementExpression>.Builder newElementsBuilder = ImmutableArray.CreateBuilder<IncludeElementExpression>(includeElements.Count);
202+
newElementsBuilder.AddRange(includeElements);
202203

203-
foreach ((IncludeElementExpression existingElement, IReadOnlyCollection<IncludeElementExpression> updatedChildren) in updatesInChildren)
204+
foreach ((IncludeElementExpression existingElement, IImmutableList<IncludeElementExpression> updatedChildren) in updatesInChildren)
204205
{
205-
int existingIndex = newIncludeElements.IndexOf(existingElement);
206-
newIncludeElements[existingIndex] = new IncludeElementExpression(existingElement.Relationship, updatedChildren);
206+
int existingIndex = newElementsBuilder.IndexOf(existingElement);
207+
newElementsBuilder[existingIndex] = new IncludeElementExpression(existingElement.Relationship, updatedChildren);
207208
}
208209

209-
return newIncludeElements;
210+
return newElementsBuilder.ToImmutable();
210211
}
211212

212213
/// <inheritdoc />
@@ -294,7 +295,7 @@ private IncludeExpression RewriteIncludeForSecondaryEndpoint(IncludeExpression r
294295
? new IncludeElementExpression(secondaryRelationship, relativeInclude.Elements)
295296
: new IncludeElementExpression(secondaryRelationship);
296297

297-
return new IncludeExpression(parentElement.AsArray());
298+
return new IncludeExpression(ImmutableArray.Create(parentElement));
298299
}
299300

300301
private FilterExpression CreateFilterByIds<TId>(IReadOnlyCollection<TId> ids, AttrAttribute idAttribute, FilterExpression existingFilter)
@@ -310,7 +311,7 @@ private FilterExpression CreateFilterByIds<TId>(IReadOnlyCollection<TId> ids, At
310311
}
311312
else if (ids.Count > 1)
312313
{
313-
IImmutableSet<LiteralConstantExpression> constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToImmutableHashSet();
314+
ImmutableHashSet<LiteralConstantExpression> constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToImmutableHashSet();
314315
filter = new AnyExpression(idChain, constants);
315316
}
316317

@@ -322,8 +323,8 @@ public QueryLayer ComposeForUpdate<TId>(TId id, ResourceContext primaryResource)
322323
{
323324
ArgumentGuard.NotNull(primaryResource, nameof(primaryResource));
324325

325-
IncludeElementExpression[] includeElements = _targetedFields.Relationships
326-
.Select(relationship => new IncludeElementExpression(relationship)).ToArray();
326+
ImmutableArray<IncludeElementExpression> includeElements = _targetedFields.Relationships
327+
.Select(relationship => new IncludeElementExpression(relationship)).ToImmutableArray();
327328

328329
AttrAttribute primaryIdAttribute = GetIdAttribute(primaryResource);
329330

@@ -398,7 +399,7 @@ public QueryLayer ComposeForHasMany<TId>(HasManyAttribute hasManyRelationship, T
398399

399400
return new QueryLayer(leftResourceContext)
400401
{
401-
Include = new IncludeExpression(new IncludeElementExpression(hasManyRelationship).AsArray()),
402+
Include = new IncludeExpression(ImmutableArray.Create(new IncludeElementExpression(hasManyRelationship))),
402403
Filter = leftFilter,
403404
Projection = new Dictionary<ResourceFieldAttribute, QueryLayer>
404405
{
@@ -421,7 +422,7 @@ public IResourceDefinitionAccessor GetResourceDefinitionAccessor()
421422
return _resourceDefinitionAccessor;
422423
}
423424

424-
protected virtual IReadOnlyCollection<IncludeElementExpression> GetIncludeElements(IReadOnlyCollection<IncludeElementExpression> includeElements,
425+
protected virtual IImmutableList<IncludeElementExpression> GetIncludeElements(IImmutableList<IncludeElementExpression> includeElements,
425426
ResourceContext resourceContext)
426427
{
427428
ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));
@@ -434,8 +435,8 @@ protected virtual FilterExpression GetFilter(IReadOnlyCollection<QueryExpression
434435
ArgumentGuard.NotNull(expressionsInScope, nameof(expressionsInScope));
435436
ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));
436437

437-
IImmutableList<FilterExpression> filters = expressionsInScope.OfType<FilterExpression>().ToImmutableArray();
438-
FilterExpression filter = filters.Count > 1 ? new LogicalExpression(LogicalOperator.And, filters) : filters.FirstOrDefault();
438+
ImmutableArray<FilterExpression> filters = expressionsInScope.OfType<FilterExpression>().ToImmutableArray();
439+
FilterExpression filter = filters.Length > 1 ? new LogicalExpression(LogicalOperator.And, filters) : filters.FirstOrDefault();
439440

440441
return _resourceDefinitionAccessor.OnApplyFilter(resourceContext.ResourceType, filter);
441442
}

src/JsonApiDotNetCore/Queries/Internal/QueryableBuilding/QueryClauseBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public override Expression VisitResourceFieldChain(ResourceFieldChainExpression
6565
return CreatePropertyExpressionFromComponents(LambdaScope.Accessor, components);
6666
}
6767

68-
private static MemberExpression CreatePropertyExpressionFromComponents(Expression source, IReadOnlyCollection<string> components)
68+
private static MemberExpression CreatePropertyExpressionFromComponents(Expression source, IEnumerable<string> components)
6969
{
7070
MemberExpression property = null;
7171

src/JsonApiDotNetCore/Resources/IResourceDefinition.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Collections.Immutable;
23
using System.Linq;
34
using System.Threading;
45
using System.Threading.Tasks;
@@ -44,7 +45,7 @@ public interface IResourceDefinition<TResource, TId>
4445
/// <returns>
4546
/// The new set of includes. Return an empty collection to remove all inclusions (never return <c>null</c>).
4647
/// </returns>
47-
IReadOnlyCollection<IncludeElementExpression> OnApplyIncludes(IReadOnlyCollection<IncludeElementExpression> existingIncludes);
48+
IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes);
4849

4950
/// <summary>
5051
/// Enables to extend, replace or remove a filter that is being applied on a set of this resource type.

src/JsonApiDotNetCore/Resources/IResourceDefinitionAccessor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45
using System.Threading;
56
using System.Threading.Tasks;
@@ -17,7 +18,7 @@ public interface IResourceDefinitionAccessor
1718
/// <summary>
1819
/// Invokes <see cref="IResourceDefinition{TResource,TId}.OnApplyIncludes" /> for the specified resource type.
1920
/// </summary>
20-
IReadOnlyCollection<IncludeElementExpression> OnApplyIncludes(Type resourceType, IReadOnlyCollection<IncludeElementExpression> existingIncludes);
21+
IImmutableList<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableList<IncludeElementExpression> existingIncludes);
2122

2223
/// <summary>
2324
/// Invokes <see cref="IResourceDefinition{TResource,TId}.OnApplyFilter" /> for the specified resource type.

src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public JsonApiResourceDefinition(IResourceGraph resourceGraph)
5252
}
5353

5454
/// <inheritdoc />
55-
public virtual IReadOnlyCollection<IncludeElementExpression> OnApplyIncludes(IReadOnlyCollection<IncludeElementExpression> existingIncludes)
55+
public virtual IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes)
5656
{
5757
return existingIncludes;
5858
}

src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using JetBrains.Annotations;
@@ -28,7 +29,7 @@ public ResourceDefinitionAccessor(IResourceContextProvider resourceContextProvid
2829
}
2930

3031
/// <inheritdoc />
31-
public IReadOnlyCollection<IncludeElementExpression> OnApplyIncludes(Type resourceType, IReadOnlyCollection<IncludeElementExpression> existingIncludes)
32+
public IImmutableList<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableList<IncludeElementExpression> existingIncludes)
3233
{
3334
ArgumentGuard.NotNull(resourceType, nameof(resourceType));
3435

0 commit comments

Comments
 (0)