Skip to content

Commit d0f7cc1

Browse files
author
Bart Koelman
committed
Changed ResourceFieldChainExpression.Fields type from IReadOnlyCollection to IImmutableList
1 parent ae4a57b commit d0f7cc1

File tree

16 files changed

+70
-68
lines changed

16 files changed

+70
-68
lines changed

src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs

Lines changed: 9 additions & 5 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 JsonApiDotNetCore.Resources.Annotations;
56

@@ -63,15 +64,15 @@ public IReadOnlyCollection<ResourceFieldChainExpression> GetRelationshipChains(I
6364
/// }
6465
/// ]]></code>
6566
/// </example>
66-
public IncludeExpression FromRelationshipChains(IReadOnlyCollection<ResourceFieldChainExpression> chains)
67+
public IncludeExpression FromRelationshipChains(IEnumerable<ResourceFieldChainExpression> chains)
6768
{
6869
ArgumentGuard.NotNull(chains, nameof(chains));
6970

7071
IReadOnlyCollection<IncludeElementExpression> elements = ConvertChainsToElements(chains);
7172
return elements.Any() ? new IncludeExpression(elements) : IncludeExpression.Empty;
7273
}
7374

74-
private static IReadOnlyCollection<IncludeElementExpression> ConvertChainsToElements(IReadOnlyCollection<ResourceFieldChainExpression> chains)
75+
private static IReadOnlyCollection<IncludeElementExpression> ConvertChainsToElements(IEnumerable<ResourceFieldChainExpression> chains)
7576
{
7677
var rootNode = new MutableIncludeNode(null);
7778

@@ -137,10 +138,13 @@ public override object VisitIncludeElement(IncludeElementExpression expression,
137138

138139
private void FlushChain(IncludeElementExpression expression)
139140
{
140-
List<RelationshipAttribute> fieldsInChain = _parentRelationshipStack.Reverse().ToList();
141-
fieldsInChain.Add(expression.Relationship);
141+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder =
142+
ImmutableArray.CreateBuilder<ResourceFieldAttribute>(_parentRelationshipStack.Count + 1);
142143

143-
Chains.Add(new ResourceFieldChainExpression(fieldsInChain));
144+
chainBuilder.AddRange(_parentRelationshipStack.Reverse());
145+
chainBuilder.Add(expression.Relationship);
146+
147+
Chains.Add(new ResourceFieldChainExpression(chainBuilder.ToImmutable()));
144148
}
145149
}
146150

src/JsonApiDotNetCore/Queries/Expressions/ResourceFieldChainExpression.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 JetBrains.Annotations;
55
using JsonApiDotNetCore.Resources.Annotations;
@@ -12,16 +12,16 @@ namespace JsonApiDotNetCore.Queries.Expressions
1212
[PublicAPI]
1313
public class ResourceFieldChainExpression : IdentifierExpression
1414
{
15-
public IReadOnlyCollection<ResourceFieldAttribute> Fields { get; }
15+
public IImmutableList<ResourceFieldAttribute> Fields { get; }
1616

1717
public ResourceFieldChainExpression(ResourceFieldAttribute field)
1818
{
1919
ArgumentGuard.NotNull(field, nameof(field));
2020

21-
Fields = field.AsArray();
21+
Fields = ImmutableArray.Create(field);
2222
}
2323

24-
public ResourceFieldChainExpression(IReadOnlyCollection<ResourceFieldAttribute> fields)
24+
public ResourceFieldChainExpression(IImmutableList<ResourceFieldAttribute> fields)
2525
{
2626
ArgumentGuard.NotNullNorEmpty(fields, nameof(fields));
2727

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Linq;
3+
using System.Collections.Immutable;
44
using System.Reflection;
55
using Humanizer;
66
using JetBrains.Annotations;
@@ -158,7 +158,7 @@ protected ComparisonExpression ParseComparison(string operatorName)
158158
OnResolveFieldChain(leftChain.ToString(), FieldChainRequirements.EndsInAttribute);
159159
}
160160

161-
PropertyInfo leftProperty = leftChain.Fields.Last().Property;
161+
PropertyInfo leftProperty = leftChain.Fields[^1].Property;
162162

163163
if (leftProperty.Name == nameof(Identifiable.Id) && rightTerm is LiteralConstantExpression rightConstant)
164164
{
@@ -216,7 +216,7 @@ protected AnyExpression ParseAny()
216216

217217
EatSingleCharacterToken(TokenKind.CloseParen);
218218

219-
PropertyInfo targetAttributeProperty = targetAttribute.Fields.Last().Property;
219+
PropertyInfo targetAttributeProperty = targetAttribute.Fields[^1].Property;
220220

221221
if (targetAttributeProperty.Name == nameof(Identifiable.Id))
222222
{
@@ -243,7 +243,7 @@ protected HasExpression ParseHas()
243243
{
244244
EatSingleCharacterToken(TokenKind.Comma);
245245

246-
filter = ParseFilterInHas((HasManyAttribute)targetCollection.Fields.Last());
246+
filter = ParseFilterInHas((HasManyAttribute)targetCollection.Fields[^1]);
247247
}
248248

249249
EatSingleCharacterToken(TokenKind.CloseParen);
@@ -332,7 +332,7 @@ private string DeObfuscateStringId(Type resourceType, string stringId)
332332
return tempResource.GetTypedId().ToString();
333333
}
334334

335-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
335+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
336336
{
337337
if (chainRequirements == FieldChainRequirements.EndsInToMany)
338338
{

src/JsonApiDotNetCore/Queries/Internal/Parsing/IncludeParser.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 JetBrains.Annotations;
56
using JsonApiDotNetCore.Configuration;
@@ -72,7 +73,7 @@ private static void ValidateMaximumIncludeDepth(int? maximumDepth, IReadOnlyColl
7273
}
7374
}
7475

75-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
76+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
7677
{
7778
return ChainResolver.ResolveRelationshipChain(_resourceContextInScope, path, _validateSingleRelationshipCallback);
7879
}

src/JsonApiDotNetCore/Queries/Internal/Parsing/PaginationParser.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 JetBrains.Annotations;
56
using JsonApiDotNetCore.Configuration;
@@ -105,7 +106,7 @@ protected PaginationElementQueryStringValueExpression ParsePaginationElement()
105106
return null;
106107
}
107108

108-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
109+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
109110
{
110111
return ChainResolver.ResolveToManyChain(_resourceContextInScope, path, _validateSingleFieldCallback);
111112
}

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

Lines changed: 3 additions & 2 deletions
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 JetBrains.Annotations;
45
using JsonApiDotNetCore.Configuration;
@@ -28,7 +29,7 @@ protected QueryExpressionParser(IResourceContextProvider resourceContextProvider
2829
/// <summary>
2930
/// Takes a dotted path and walks the resource graph to produce a chain of fields.
3031
/// </summary>
31-
protected abstract IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements);
32+
protected abstract IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements);
3233

3334
protected virtual void Tokenize(string source)
3435
{
@@ -40,7 +41,7 @@ protected ResourceFieldChainExpression ParseFieldChain(FieldChainRequirements ch
4041
{
4142
if (TokenStack.TryPop(out Token token) && token.Kind == TokenKind.Text)
4243
{
43-
IReadOnlyCollection<ResourceFieldAttribute> chain = OnResolveFieldChain(token.Value, chainRequirements);
44+
IImmutableList<ResourceFieldAttribute> chain = OnResolveFieldChain(token.Value, chainRequirements);
4445

4546
if (chain.Any())
4647
{

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

Lines changed: 2 additions & 2 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 JetBrains.Annotations;
44
using JsonApiDotNetCore.Configuration;
55
using JsonApiDotNetCore.Queries.Expressions;
@@ -60,7 +60,7 @@ protected QueryStringParameterScopeExpression ParseQueryStringParameterScope()
6060
return new QueryStringParameterScopeExpression(name, scope);
6161
}
6262

63-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
63+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
6464
{
6565
if (chainRequirements == FieldChainRequirements.EndsInToMany)
6666
{

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

Lines changed: 25 additions & 25 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 JsonApiDotNetCore.Configuration;
55
using JsonApiDotNetCore.Resources.Annotations;
@@ -23,10 +23,10 @@ public ResourceFieldChainResolver(IResourceContextProvider resourceContextProvid
2323
/// <summary>
2424
/// Resolves a chain of relationships that ends in a to-many relationship, for example: blogs.owner.articles.comments
2525
/// </summary>
26-
public IReadOnlyCollection<ResourceFieldAttribute> ResolveToManyChain(ResourceContext resourceContext, string path,
26+
public IImmutableList<ResourceFieldAttribute> ResolveToManyChain(ResourceContext resourceContext, string path,
2727
Action<ResourceFieldAttribute, ResourceContext, string> validateCallback = null)
2828
{
29-
var chain = new List<ResourceFieldAttribute>();
29+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder = ImmutableArray.CreateBuilder<ResourceFieldAttribute>();
3030

3131
string[] publicNameParts = path.Split(".");
3232
ResourceContext nextResourceContext = resourceContext;
@@ -37,7 +37,7 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToManyChain(ResourceCo
3737

3838
validateCallback?.Invoke(relationship, nextResourceContext, path);
3939

40-
chain.Add(relationship);
40+
chainBuilder.Add(relationship);
4141
nextResourceContext = _resourceContextProvider.GetResourceContext(relationship.RightType);
4242
}
4343

@@ -46,8 +46,8 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToManyChain(ResourceCo
4646

4747
validateCallback?.Invoke(lastToManyRelationship, nextResourceContext, path);
4848

49-
chain.Add(lastToManyRelationship);
50-
return chain;
49+
chainBuilder.Add(lastToManyRelationship);
50+
return chainBuilder.ToImmutable();
5151
}
5252

5353
/// <summary>
@@ -62,10 +62,10 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToManyChain(ResourceCo
6262
/// articles.revisions.author
6363
/// </example>
6464
/// </summary>
65-
public IReadOnlyCollection<ResourceFieldAttribute> ResolveRelationshipChain(ResourceContext resourceContext, string path,
65+
public IImmutableList<ResourceFieldAttribute> ResolveRelationshipChain(ResourceContext resourceContext, string path,
6666
Action<RelationshipAttribute, ResourceContext, string> validateCallback = null)
6767
{
68-
var chain = new List<ResourceFieldAttribute>();
68+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder = ImmutableArray.CreateBuilder<ResourceFieldAttribute>();
6969
ResourceContext nextResourceContext = resourceContext;
7070

7171
foreach (string publicName in path.Split("."))
@@ -74,11 +74,11 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveRelationshipChain(Reso
7474

7575
validateCallback?.Invoke(relationship, nextResourceContext, path);
7676

77-
chain.Add(relationship);
77+
chainBuilder.Add(relationship);
7878
nextResourceContext = _resourceContextProvider.GetResourceContext(relationship.RightType);
7979
}
8080

81-
return chain;
81+
return chainBuilder.ToImmutable();
8282
}
8383

8484
/// <summary>
@@ -88,10 +88,10 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveRelationshipChain(Reso
8888
/// </example>
8989
/// <example>name</example>
9090
/// </summary>
91-
public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttribute(ResourceContext resourceContext, string path,
91+
public IImmutableList<ResourceFieldAttribute> ResolveToOneChainEndingInAttribute(ResourceContext resourceContext, string path,
9292
Action<ResourceFieldAttribute, ResourceContext, string> validateCallback = null)
9393
{
94-
var chain = new List<ResourceFieldAttribute>();
94+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder = ImmutableArray.CreateBuilder<ResourceFieldAttribute>();
9595

9696
string[] publicNameParts = path.Split(".");
9797
ResourceContext nextResourceContext = resourceContext;
@@ -102,7 +102,7 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttr
102102

103103
validateCallback?.Invoke(toOneRelationship, nextResourceContext, path);
104104

105-
chain.Add(toOneRelationship);
105+
chainBuilder.Add(toOneRelationship);
106106
nextResourceContext = _resourceContextProvider.GetResourceContext(toOneRelationship.RightType);
107107
}
108108

@@ -111,8 +111,8 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttr
111111

112112
validateCallback?.Invoke(lastAttribute, nextResourceContext, path);
113113

114-
chain.Add(lastAttribute);
115-
return chain;
114+
chainBuilder.Add(lastAttribute);
115+
return chainBuilder.ToImmutable();
116116
}
117117

118118
/// <summary>
@@ -124,10 +124,10 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttr
124124
/// comments
125125
/// </example>
126126
/// </summary>
127-
public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInToMany(ResourceContext resourceContext, string path,
127+
public IImmutableList<ResourceFieldAttribute> ResolveToOneChainEndingInToMany(ResourceContext resourceContext, string path,
128128
Action<ResourceFieldAttribute, ResourceContext, string> validateCallback = null)
129129
{
130-
var chain = new List<ResourceFieldAttribute>();
130+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder = ImmutableArray.CreateBuilder<ResourceFieldAttribute>();
131131

132132
string[] publicNameParts = path.Split(".");
133133
ResourceContext nextResourceContext = resourceContext;
@@ -138,7 +138,7 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInToMa
138138

139139
validateCallback?.Invoke(toOneRelationship, nextResourceContext, path);
140140

141-
chain.Add(toOneRelationship);
141+
chainBuilder.Add(toOneRelationship);
142142
nextResourceContext = _resourceContextProvider.GetResourceContext(toOneRelationship.RightType);
143143
}
144144

@@ -148,8 +148,8 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInToMa
148148

149149
validateCallback?.Invoke(toManyRelationship, nextResourceContext, path);
150150

151-
chain.Add(toManyRelationship);
152-
return chain;
151+
chainBuilder.Add(toManyRelationship);
152+
return chainBuilder.ToImmutable();
153153
}
154154

155155
/// <summary>
@@ -161,10 +161,10 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInToMa
161161
/// author.address
162162
/// </example>
163163
/// </summary>
164-
public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttributeOrToOne(ResourceContext resourceContext, string path,
164+
public IImmutableList<ResourceFieldAttribute> ResolveToOneChainEndingInAttributeOrToOne(ResourceContext resourceContext, string path,
165165
Action<ResourceFieldAttribute, ResourceContext, string> validateCallback = null)
166166
{
167-
var chain = new List<ResourceFieldAttribute>();
167+
ImmutableArray<ResourceFieldAttribute>.Builder chainBuilder = ImmutableArray.CreateBuilder<ResourceFieldAttribute>();
168168

169169
string[] publicNameParts = path.Split(".");
170170
ResourceContext nextResourceContext = resourceContext;
@@ -175,7 +175,7 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttr
175175

176176
validateCallback?.Invoke(toOneRelationship, nextResourceContext, path);
177177

178-
chain.Add(toOneRelationship);
178+
chainBuilder.Add(toOneRelationship);
179179
nextResourceContext = _resourceContextProvider.GetResourceContext(toOneRelationship.RightType);
180180
}
181181

@@ -191,8 +191,8 @@ public IReadOnlyCollection<ResourceFieldAttribute> ResolveToOneChainEndingInAttr
191191

192192
validateCallback?.Invoke(lastField, nextResourceContext, path);
193193

194-
chain.Add(lastField);
195-
return chain;
194+
chainBuilder.Add(lastField);
195+
return chainBuilder.ToImmutable();
196196
}
197197

198198
private RelationshipAttribute GetRelationship(string publicName, ResourceContext resourceContext, string path)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Collections.Immutable;
43
using System.Linq;
54
using JetBrains.Annotations;
@@ -77,7 +76,7 @@ protected SortElementExpression ParseSortElement()
7776
return new SortElementExpression(targetAttribute, isAscending);
7877
}
7978

80-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
79+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
8180
{
8281
if (chainRequirements == FieldChainRequirements.EndsInToMany)
8382
{

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Collections.Immutable;
43
using System.Linq;
54
using JetBrains.Annotations;
@@ -56,13 +55,13 @@ protected SparseFieldSetExpression ParseSparseFieldSet()
5655
return fieldSetBuilder.Any() ? new SparseFieldSetExpression(fieldSetBuilder.ToImmutable()) : null;
5756
}
5857

59-
protected override IReadOnlyCollection<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
58+
protected override IImmutableList<ResourceFieldAttribute> OnResolveFieldChain(string path, FieldChainRequirements chainRequirements)
6059
{
6160
ResourceFieldAttribute field = ChainResolver.GetField(path, _resourceContext, path);
6261

6362
_validateSingleFieldCallback?.Invoke(field, _resourceContext, path);
6463

65-
return field.AsArray();
64+
return ImmutableArray.Create(field);
6665
}
6766
}
6867
}

0 commit comments

Comments
 (0)