@@ -11,6 +11,8 @@ namespace JsonApiDotNetCore.Queries.Internal.Parsing;
11
11
[ PublicAPI ]
12
12
public class IncludeParser : QueryExpressionParser
13
13
{
14
+ private static readonly ResourceFieldChainErrorFormatter ErrorFormatter = new ( ) ;
15
+
14
16
public IncludeExpression Parse ( string source , ResourceType resourceTypeInScope , int ? maximumDepth )
15
17
{
16
18
ArgumentGuard . NotNull ( resourceTypeInScope , nameof ( resourceTypeInScope ) ) ;
@@ -98,7 +100,7 @@ private ICollection<IncludeTreeNode> LookupRelationshipName(string relationshipN
98
100
{
99
101
// Depending on the left side of the include chain, we may match relationships anywhere in the resource type hierarchy.
100
102
// This is compensated for when rendering the response, which substitutes relationships on base types with the derived ones.
101
- ISet < RelationshipAttribute > relationships = GetRelationshipsInTypeOrDerived ( parent . Relationship . RightType , relationshipName ) ;
103
+ IReadOnlySet < RelationshipAttribute > relationships = parent . Relationship . RightType . GetRelationshipsInTypeOrDerived ( relationshipName ) ;
102
104
103
105
if ( relationships . Any ( ) )
104
106
{
@@ -116,61 +118,22 @@ private ICollection<IncludeTreeNode> LookupRelationshipName(string relationshipN
116
118
return children ;
117
119
}
118
120
119
- private ISet < RelationshipAttribute > GetRelationshipsInTypeOrDerived ( ResourceType resourceType , string relationshipName )
120
- {
121
- RelationshipAttribute ? relationship = resourceType . FindRelationshipByPublicName ( relationshipName ) ;
122
-
123
- if ( relationship != null )
124
- {
125
- return relationship . AsHashSet ( ) ;
126
- }
127
-
128
- // Hiding base members using the 'new' keyword instead of 'override' (effectively breaking inheritance) is currently not supported.
129
- // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords
130
- HashSet < RelationshipAttribute > relationshipsInDerivedTypes = new ( ) ;
131
-
132
- foreach ( ResourceType derivedType in resourceType . DirectlyDerivedTypes )
133
- {
134
- ISet < RelationshipAttribute > relationshipsInDerivedType = GetRelationshipsInTypeOrDerived ( derivedType , relationshipName ) ;
135
- relationshipsInDerivedTypes . AddRange ( relationshipsInDerivedType ) ;
136
- }
137
-
138
- return relationshipsInDerivedTypes ;
139
- }
140
-
141
121
private static void AssertRelationshipsFound ( ISet < RelationshipAttribute > relationshipsFound , string relationshipName , ICollection < IncludeTreeNode > parents )
142
122
{
143
123
if ( relationshipsFound . Any ( ) )
144
124
{
145
125
return ;
146
126
}
147
127
148
- var messageBuilder = new StringBuilder ( ) ;
149
- messageBuilder . Append ( $ "Relationship '{ relationshipName } '") ;
150
-
151
128
string [ ] parentPaths = parents . Select ( parent => parent . Path ) . Distinct ( ) . Where ( path => path != string . Empty ) . ToArray ( ) ;
152
-
153
- if ( parentPaths . Length > 0 )
154
- {
155
- messageBuilder . Append ( $ " in '{ parentPaths [ 0 ] } .{ relationshipName } '") ;
156
- }
129
+ string path = parentPaths . Length > 0 ? $ "{ parentPaths [ 0 ] } .{ relationshipName } " : relationshipName ;
157
130
158
131
ResourceType [ ] parentResourceTypes = parents . Select ( parent => parent . Relationship . RightType ) . Distinct ( ) . ToArray ( ) ;
159
132
160
- if ( parentResourceTypes . Length == 1 )
161
- {
162
- messageBuilder . Append ( $ " does not exist on resource type '{ parentResourceTypes [ 0 ] . PublicName } '") ;
163
- }
164
- else
165
- {
166
- string typeNames = string . Join ( ", " , parentResourceTypes . Select ( type => $ "'{ type . PublicName } '") ) ;
167
- messageBuilder . Append ( $ " does not exist on any of the resource types { typeNames } ") ;
168
- }
169
-
170
- bool hasDerived = parents . Any ( parent => parent . Relationship . RightType . DirectlyDerivedTypes . Count > 0 ) ;
171
- messageBuilder . Append ( hasDerived ? " or any of its derived types." : "." ) ;
133
+ bool hasDerivedTypes = parents . Any ( parent => parent . Relationship . RightType . DirectlyDerivedTypes . Count > 0 ) ;
172
134
173
- throw new QueryParseException ( messageBuilder . ToString ( ) ) ;
135
+ string message = ErrorFormatter . GetForNoneFound ( ResourceFieldCategory . Relationship , relationshipName , path , parentResourceTypes , hasDerivedTypes ) ;
136
+ throw new QueryParseException ( message ) ;
174
137
}
175
138
176
139
private static void AssertAtLeastOneCanBeIncluded ( ISet < RelationshipAttribute > relationshipsFound , string relationshipName ,
0 commit comments