@@ -37,8 +37,9 @@ func ValuesOfCorrectTypeRule(context: ValidationContext) -> Visitor {
3737 return . break // Don't traverse further.
3838 }
3939 // Ensure every required field exists.
40- let fieldNodeMap = Dictionary ( grouping: object. fields) { field in
41- field. name. value
40+ var fieldNodeMap = [ String: ObjectField] ( )
41+ for field in object. fields {
42+ fieldNodeMap [ field. name. value] = field
4243 }
4344 for (fieldName, fieldDef) in type. fields {
4445 if fieldNodeMap [ fieldName] == nil , isRequiredInputField ( fieldDef) {
@@ -52,7 +53,15 @@ func ValuesOfCorrectTypeRule(context: ValidationContext) -> Visitor {
5253 }
5354 }
5455
55- // TODO: Add oneOf support
56+ if type. isOneOf {
57+ validateOneOfInputObject (
58+ context: context,
59+ node: object,
60+ type: type,
61+ fieldNodeMap: fieldNodeMap,
62+ variableDefinitions: variableDefinitions
63+ )
64+ }
5665 return . continue
5766 }
5867 if let field = node as? ObjectField {
@@ -172,3 +181,55 @@ func isValidValueNode(_ context: ValidationContext, _ node: Value) {
172181 }
173182 }
174183}
184+
185+ func validateOneOfInputObject(
186+ context: ValidationContext ,
187+ node: ObjectValue ,
188+ type: GraphQLInputObjectType ,
189+ fieldNodeMap: [ String : ObjectField ] ,
190+ variableDefinitions: [ String : VariableDefinition ]
191+ ) {
192+ let keys = Array ( fieldNodeMap. keys)
193+ let isNotExactlyOneField = keys. count != 1
194+
195+ if isNotExactlyOneField {
196+ context. report (
197+ error: GraphQLError (
198+ message: " OneOf Input Object \" \( type. name) \" must specify exactly one key. " ,
199+ nodes: [ node]
200+ )
201+ )
202+ return
203+ }
204+
205+ let value = fieldNodeMap [ keys [ 0 ] ] ? . value
206+ let isNullLiteral = value == nil || value? . kind == . nullValue
207+
208+ if isNullLiteral {
209+ context. report (
210+ error: GraphQLError (
211+ message: " Field \" \( type. name) . \( keys [ 0 ] ) \" must be non-null. " ,
212+ nodes: [ node]
213+ )
214+ )
215+ return
216+ }
217+
218+ if let value = value, value. kind == . variable {
219+ let variable = value as! Variable // Force unwrap is safe because of variable definition
220+ let variableName = variable. name. value
221+
222+ if
223+ let definition = variableDefinitions [ variableName] ,
224+ definition. type. kind != . nonNullType
225+ {
226+ context. report (
227+ error: GraphQLError (
228+ message: " Variable \" \( variableName) \" must be non-nullable to be used for OneOf Input Object \" \( type. name) \" . " ,
229+ nodes: [ node]
230+ )
231+ )
232+ return
233+ }
234+ }
235+ }
0 commit comments