unique_variable_names.ex (2125B)
1 defmodule Absinthe.Phase.Document.Validation.UniqueVariableNames do 2 @moduledoc false 3 4 # Validates document to ensure that all variable definitions for an operation 5 # have unique names. 6 7 alias Absinthe.{Blueprint, Phase} 8 9 use Absinthe.Phase 10 use Absinthe.Phase.Validation 11 12 @doc """ 13 Run the validation. 14 """ 15 @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t() 16 def run(input, _options \\ []) do 17 operations = 18 for operation <- input.operations do 19 variable_definitions = 20 for variable <- operation.variable_definitions do 21 process(variable, operation.variable_definitions) 22 end 23 24 %{operation | variable_definitions: variable_definitions} 25 end 26 27 result = %{input | operations: operations} 28 {:ok, result} 29 end 30 31 @spec process(Blueprint.Document.VariableDefinition.t(), [ 32 Blueprint.Document.VariableDefinition.t() 33 ]) :: Blueprint.Document.VariableDefinition.t() 34 defp process(variable_definition, variable_definitions) do 35 if duplicate?(variable_definitions, variable_definition) do 36 variable_definition 37 |> flag_invalid(:duplicate_name) 38 |> put_error(error(variable_definition)) 39 else 40 variable_definition 41 end 42 end 43 44 # Whether a duplicate variable_definition is present 45 @spec duplicate?( 46 [Blueprint.Document.VariableDefinition.t()], 47 Blueprint.Document.VariableDefinition.t() 48 ) :: boolean 49 defp duplicate?(variable_definitions, variable_definition) do 50 Enum.count(variable_definitions, &(&1.name == variable_definition.name)) > 1 51 end 52 53 # Generate an error for a duplicate variable_definition. 54 @spec error(Blueprint.Document.VariableDefinition.t()) :: Phase.Error.t() 55 defp error(node) do 56 %Phase.Error{ 57 phase: __MODULE__, 58 message: error_message(node.name), 59 locations: [node.source_location] 60 } 61 end 62 63 @doc """ 64 Generate an error message for a duplicate variable definition. 65 """ 66 @spec error_message(String.t()) :: String.t() 67 def error_message(name) do 68 ~s(There can only be one variable named "#{name}".) 69 end 70 end