known_directives.ex (1999B)
1 defmodule Absinthe.Phase.Schema.Validation.KnownDirectives do 2 @moduledoc false 3 4 alias Absinthe.{Blueprint, Phase} 5 6 use Absinthe.Phase 7 use Absinthe.Phase.Validation 8 9 @doc """ 10 Run the validation. 11 """ 12 @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t() 13 def run(input, _options \\ []) do 14 result = Blueprint.postwalk(input, &handle_node/1) 15 {:ok, result} 16 end 17 18 defp handle_node(%Blueprint.Directive{schema_node: nil} = node) do 19 node 20 |> put_error(error_unknown(node)) 21 end 22 23 defp handle_node(%Blueprint.Directive{} = node) do 24 node 25 end 26 27 defp handle_node(%{directives: []} = node) do 28 node 29 end 30 31 defp handle_node(%{directives: _} = node) do 32 node 33 |> check_directives 34 |> inherit_invalid(node.directives, :bad_directive) 35 end 36 37 defp handle_node(node) do 38 node 39 end 40 41 defp check_directives(node) do 42 placement = Blueprint.Directive.placement(node) 43 44 directives = 45 for directive <- node.directives do 46 if directive.schema_node do 47 if placement in directive.schema_node.locations do 48 directive 49 else 50 directive 51 |> put_error(error_misplaced(directive, placement)) 52 |> flag_invalid(:bad_placement) 53 end 54 else 55 directive 56 end 57 end 58 59 %{node | directives: directives} 60 end 61 62 # Generate the error for the node 63 @spec error_unknown(Blueprint.node_t()) :: Phase.Error.t() 64 defp error_unknown(node) do 65 %Phase.Error{ 66 phase: __MODULE__, 67 message: "Unknown directive `#{node.name}'.", 68 locations: [node.__reference__.location] 69 } 70 end 71 72 @spec error_misplaced(Blueprint.node_t(), atom) :: Phase.Error.t() 73 defp error_misplaced(node, placement) do 74 placement_name = placement |> to_string |> String.upcase() 75 76 %Phase.Error{ 77 phase: __MODULE__, 78 message: "Directive `#{node.name}' may not be used on #{placement_name}.", 79 locations: [node.__reference__.location] 80 } 81 end 82 end