forked from STI/Astroport.ONE
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
from typing import Any, List, Set
|
|
|
|
from ...error import GraphQLError
|
|
from ...language import OperationDefinitionNode, VariableDefinitionNode
|
|
from . import ValidationContext, ValidationRule
|
|
|
|
__all__ = ["NoUnusedVariablesRule"]
|
|
|
|
|
|
class NoUnusedVariablesRule(ValidationRule):
|
|
"""No unused variables
|
|
|
|
A GraphQL operation is only valid if all variables defined by an operation are used,
|
|
either directly or within a spread fragment.
|
|
|
|
See https://spec.graphql.org/draft/#sec-All-Variables-Used
|
|
"""
|
|
|
|
def __init__(self, context: ValidationContext):
|
|
super().__init__(context)
|
|
self.variable_defs: List[VariableDefinitionNode] = []
|
|
|
|
def enter_operation_definition(self, *_args: Any) -> None:
|
|
self.variable_defs.clear()
|
|
|
|
def leave_operation_definition(
|
|
self, operation: OperationDefinitionNode, *_args: Any
|
|
) -> None:
|
|
variable_name_used: Set[str] = set()
|
|
usages = self.context.get_recursive_variable_usages(operation)
|
|
|
|
for usage in usages:
|
|
variable_name_used.add(usage.node.name.value)
|
|
|
|
for variable_def in self.variable_defs:
|
|
variable_name = variable_def.variable.name.value
|
|
if variable_name not in variable_name_used:
|
|
self.report_error(
|
|
GraphQLError(
|
|
f"Variable '${variable_name}' is never used"
|
|
f" in operation '{operation.name.value}'."
|
|
if operation.name
|
|
else f"Variable '${variable_name}' is never used.",
|
|
variable_def,
|
|
)
|
|
)
|
|
|
|
def enter_variable_definition(
|
|
self, definition: VariableDefinitionNode, *_args: Any
|
|
) -> None:
|
|
self.variable_defs.append(definition)
|