1from typing import Any, Dict
2
3from ...error import GraphQLError
4from ...language import NameNode, OperationDefinitionNode, VisitorAction, SKIP
5from . import ASTValidationContext, ASTValidationRule
6
7__all__ = ["UniqueOperationNamesRule"]
8
9
10class UniqueOperationNamesRule(ASTValidationRule):
11    """Unique operation names
12
13    A GraphQL document is only valid if all defined operations have unique names.
14    """
15
16    def __init__(self, context: ASTValidationContext):
17        super().__init__(context)
18        self.known_operation_names: Dict[str, NameNode] = {}
19
20    def enter_operation_definition(
21        self, node: OperationDefinitionNode, *_args: Any
22    ) -> VisitorAction:
23        operation_name = node.name
24        if operation_name:
25            known_operation_names = self.known_operation_names
26            if operation_name.value in known_operation_names:
27                self.report_error(
28                    GraphQLError(
29                        "There can be only one operation"
30                        f" named '{operation_name.value}'.",
31                        [known_operation_names[operation_name.value], operation_name],
32                    )
33                )
34            else:
35                known_operation_names[operation_name.value] = operation_name
36        return SKIP
37
38    @staticmethod
39    def enter_fragment_definition(*_args: Any) -> VisitorAction:
40        return SKIP
41