summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2020-09-22 04:42:25 +0200
committerEugen Wissner <belka@caraus.de>2020-09-22 04:42:25 +0200
commite9a94147fb5cf6b871268a373fc211cfa50da2fc (patch)
tree8a0c947ec379c56766656c64b5f840eb7064940a /src
parent3e393004ae03a717218a805043d9237ca29ac947 (diff)
downloadgraphql-e9a94147fb5cf6b871268a373fc211cfa50da2fc.tar.gz
Validate variables are used
Diffstat (limited to 'src')
-rw-r--r--src/Language/GraphQL/Validate/Rules.hs40
1 files changed, 35 insertions, 5 deletions
diff --git a/src/Language/GraphQL/Validate/Rules.hs b/src/Language/GraphQL/Validate/Rules.hs
index 9b38b6d..c123017 100644
--- a/src/Language/GraphQL/Validate/Rules.hs
+++ b/src/Language/GraphQL/Validate/Rules.hs
@@ -17,6 +17,7 @@ module Language.GraphQL.Validate.Rules
, noFragmentCyclesRule
, noUndefinedVariablesRule
, noUnusedFragmentsRule
+ , noUnusedVariablesRule
, singleFieldSubscriptionsRule
, specifiedRules
, uniqueArgumentNamesRule
@@ -76,6 +77,7 @@ specifiedRules =
, uniqueVariableNamesRule
, variablesAreInputTypesRule
, noUndefinedVariablesRule
+ , noUnusedVariablesRule
]
-- | Definition must be OperationDefinition or FragmentDefinition.
@@ -560,7 +562,27 @@ variablesAreInputTypesRule = VariablesRule
-- used within the context of an operation must be defined at the top level of
-- that operation.
noUndefinedVariablesRule :: forall m. Rule m
-noUndefinedVariablesRule = OperationDefinitionRule $ \case
+noUndefinedVariablesRule =
+ variableUsageDifference (flip HashMap.difference) errorMessage
+ where
+ errorMessage Nothing variableName = concat
+ [ "Variable \"$"
+ , Text.unpack variableName
+ , "\" is not defined."
+ ]
+ errorMessage (Just operationName) variableName = concat
+ [ "Variable \"$"
+ , Text.unpack variableName
+ , "\" is not defined by operation \""
+ , Text.unpack operationName
+ , "\"."
+ ]
+
+variableUsageDifference :: forall m
+ . (HashMap Name [Location] -> HashMap Name [Location] -> HashMap Name [Location])
+ -> (Maybe Name -> Name -> String)
+ -> Rule m
+variableUsageDifference difference errorMessage = OperationDefinitionRule $ \case
SelectionSet _ _ -> lift mempty
OperationDefinition _ operationName variables _ selections _ ->
let variableNames = HashMap.fromList $ getVariableName <$> variables
@@ -572,10 +594,11 @@ noUndefinedVariablesRule = OperationDefinitionRule $ \case
readerMapper operationName variableNames' = Seq.fromList
. fmap (makeError operationName)
. HashMap.toList
- . flip HashMap.difference variableNames'
+ . difference variableNames'
. HashMap.fromListWith (++)
. toList
- getVariableName (VariableDefinition variableName _ _ _) = (variableName, [])
+ getVariableName (VariableDefinition variableName _ _ location) =
+ (variableName, [location])
filterSelections' :: Foldable t
=> t Selection
-> ValidationState m (Name, [Location])
@@ -609,15 +632,22 @@ noUndefinedVariablesRule = OperationDefinitionRule $ \case
{ message = errorMessage operationName variableName
, locations = locations'
}
+
+-- | All variables defined by an operation must be used in that operation or a
+-- fragment transitively included by that operation. Unused variables cause a
+-- validation error.
+noUnusedVariablesRule :: forall m. Rule m
+noUnusedVariablesRule = variableUsageDifference HashMap.difference errorMessage
+ where
errorMessage Nothing variableName = concat
[ "Variable \"$"
, Text.unpack variableName
- , "\" is not defined."
+ , "\" is never used."
]
errorMessage (Just operationName) variableName = concat
[ "Variable \"$"
, Text.unpack variableName
- , "\" is not defined by operation \""
+ , "\" is never used in operation \""
, Text.unpack operationName
, "\"."
]