Emit list item errors once
This commit is contained in:
		| @@ -14,6 +14,12 @@ and this project adheres to | |||||||
| ### Fixed | ### Fixed | ||||||
| - Parser now accepts empty lists and objects. | - Parser now accepts empty lists and objects. | ||||||
| - Parser now accepts all directive locations. | - Parser now accepts all directive locations. | ||||||
|  | - `valuesOfCorrectTypeRule` doesn't check list items recursively since the | ||||||
|  |   validation traverser calls it on all list items. | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | - `AST.Document.Value.List` and `AST.Document.ConstValue.ConstList` contain | ||||||
|  |   location information for each list item. | ||||||
|  |  | ||||||
| ## [0.11.1.0] - 2021-02-07 | ## [0.11.1.0] - 2021-02-07 | ||||||
| ### Added | ### Added | ||||||
|   | |||||||
| @@ -1540,7 +1540,7 @@ valuesOfCorrectTypeRule = ValueRule go constGo | |||||||
|     go (Just inputType) value |     go (Just inputType) value | ||||||
|         | Just constValue <- toConstNode value = |         | Just constValue <- toConstNode value = | ||||||
|             lift $ check inputType constValue |             lift $ check inputType constValue | ||||||
|     go _ _ = lift mempty |     go _ _ = lift mempty -- This rule checks only literals. | ||||||
|     toConstNode Full.Node{..} = flip Full.Node location <$> toConst node |     toConstNode Full.Node{..} = flip Full.Node location <$> toConst node | ||||||
|     toConst (Full.Variable _) = Nothing |     toConst (Full.Variable _) = Nothing | ||||||
|     toConst (Full.Int integer) = Just $ Full.ConstInt integer |     toConst (Full.Int integer) = Just $ Full.ConstInt integer | ||||||
| @@ -1586,8 +1586,8 @@ valuesOfCorrectTypeRule = ValueRule go constGo | |||||||
|         , Full.ConstObject valueFields <- node = |         , Full.ConstObject valueFields <- node = | ||||||
|             foldMap (checkObjectField typeFields) valueFields |             foldMap (checkObjectField typeFields) valueFields | ||||||
|     check (In.ListBaseType listType) constValue@Full.Node{ .. } |     check (In.ListBaseType listType) constValue@Full.Node{ .. } | ||||||
|         | Full.ConstList listValues <- node = |         -- Skip, lists are checked recursively by the validation traverser. | ||||||
|             foldMap (check listType) listValues |         | Full.ConstList _ <- node = mempty | ||||||
|         | otherwise = check listType constValue |         | otherwise = check listType constValue | ||||||
|     check inputType Full.Node{ .. } = pure $ Error |     check inputType Full.Node{ .. } = pure $ Error | ||||||
|         { message = concat |         { message = concat | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| resolver: lts-17.3 | resolver: lts-17.6 | ||||||
|  |  | ||||||
| packages: | packages: | ||||||
| - . | - . | ||||||
|   | |||||||
| @@ -49,16 +49,18 @@ catType :: ObjectType IO | |||||||
| catType = ObjectType "Cat" Nothing [petType] $ HashMap.fromList | catType = ObjectType "Cat" Nothing [petType] $ HashMap.fromList | ||||||
|     [ ("name", nameResolver) |     [ ("name", nameResolver) | ||||||
|     , ("nickname", nicknameResolver) |     , ("nickname", nicknameResolver) | ||||||
|     , ("doesKnowCommand", doesKnowCommandResolver) |     , ("doesKnowCommands", doesKnowCommandsResolver) | ||||||
|     , ("meowVolume", meowVolumeResolver) |     , ("meowVolume", meowVolumeResolver) | ||||||
|     ] |     ] | ||||||
|   where |   where | ||||||
|     meowVolumeField = Field Nothing (Out.NamedScalarType int) mempty |     meowVolumeField = Field Nothing (Out.NamedScalarType int) mempty | ||||||
|     meowVolumeResolver = ValueResolver meowVolumeField $ pure $ Int 3 |     meowVolumeResolver = ValueResolver meowVolumeField $ pure $ Int 3 | ||||||
|     doesKnowCommandField = Field Nothing (Out.NonNullScalarType boolean) |     doesKnowCommandsType = In.NonNullListType | ||||||
|         $ HashMap.singleton "catCommand" |         $ In.NonNullEnumType catCommandType | ||||||
|         $ In.Argument Nothing (In.NonNullEnumType catCommandType) Nothing |     doesKnowCommandsField = Field Nothing (Out.NonNullScalarType boolean) | ||||||
|     doesKnowCommandResolver = ValueResolver doesKnowCommandField |         $ HashMap.singleton "catCommands" | ||||||
|  |         $ In.Argument Nothing doesKnowCommandsType Nothing | ||||||
|  |     doesKnowCommandsResolver = ValueResolver doesKnowCommandsField | ||||||
|         $ pure $ Boolean True |         $ pure $ Boolean True | ||||||
|  |  | ||||||
| nameResolver :: Resolver IO | nameResolver :: Resolver IO | ||||||
| @@ -866,17 +868,17 @@ spec = | |||||||
|         context "variablesInAllowedPositionRule" $ do |         context "variablesInAllowedPositionRule" $ do | ||||||
|             it "rejects wrongly typed variable arguments" $ |             it "rejects wrongly typed variable arguments" $ | ||||||
|                 let queryString = [r| |                 let queryString = [r| | ||||||
|                   query catCommandArgQuery($catCommandArg: CatCommand) { |                   query dogCommandArgQuery($dogCommandArg: DogCommand) { | ||||||
|                     cat { |                     dog { | ||||||
|                       doesKnowCommand(catCommand: $catCommandArg) |                       doesKnowCommand(dogCommand: $dogCommandArg) | ||||||
|                     } |                     } | ||||||
|                   } |                   } | ||||||
|                 |] |                 |] | ||||||
|                     expected = Error |                     expected = Error | ||||||
|                         { message = |                         { message = | ||||||
|                             "Variable \"$catCommandArg\" of type \ |                             "Variable \"$dogCommandArg\" of type \ | ||||||
|                             \\"CatCommand\" used in position expecting type \ |                             \\"DogCommand\" used in position expecting type \ | ||||||
|                             \\"!CatCommand\"." |                             \\"!DogCommand\"." | ||||||
|                         , locations = [AST.Location 2 44] |                         , locations = [AST.Location 2 44] | ||||||
|                         } |                         } | ||||||
|                  in validate queryString `shouldBe` [expected] |                  in validate queryString `shouldBe` [expected] | ||||||
| @@ -897,7 +899,7 @@ spec = | |||||||
|                         } |                         } | ||||||
|                  in validate queryString `shouldBe` [expected] |                  in validate queryString `shouldBe` [expected] | ||||||
|  |  | ||||||
|         context "valuesOfCorrectTypeRule" $ |         context "valuesOfCorrectTypeRule" $ do | ||||||
|             it "rejects values of incorrect types" $ |             it "rejects values of incorrect types" $ | ||||||
|                 let queryString = [r| |                 let queryString = [r| | ||||||
|                   { |                   { | ||||||
| @@ -912,3 +914,18 @@ spec = | |||||||
|                         , locations = [AST.Location 4 52] |                         , locations = [AST.Location 4 52] | ||||||
|                         } |                         } | ||||||
|                  in validate queryString `shouldBe` [expected] |                  in validate queryString `shouldBe` [expected] | ||||||
|  |  | ||||||
|  |             it "uses the location of a single list value" $ | ||||||
|  |                 let queryString = [r| | ||||||
|  |                   { | ||||||
|  |                     cat { | ||||||
|  |                       doesKnowCommands(catCommands: [3]) | ||||||
|  |                     } | ||||||
|  |                   } | ||||||
|  |                 |] | ||||||
|  |                     expected = Error | ||||||
|  |                         { message = | ||||||
|  |                             "Value 3 cannot be coerced to type \"!CatCommand\"." | ||||||
|  |                         , locations = [AST.Location 4 54] | ||||||
|  |                         } | ||||||
|  |                  in validate queryString `shouldBe` [expected] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user