no_unused_fragments.ex (1438B)
1 defmodule Absinthe.Phase.Document.Validation.NoUnusedFragments do 2 @moduledoc false 3 4 # Validates document to ensure that all named fragments are used. 5 6 alias Absinthe.{Blueprint, Phase} 7 8 use Absinthe.Phase 9 use Absinthe.Phase.Validation 10 11 @doc """ 12 Run the validation. 13 """ 14 @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t() 15 def run(input, _options \\ []) do 16 result = Blueprint.prewalk(input, &handle_node(&1, input.operations)) 17 {:ok, result} 18 end 19 20 def handle_node(%Blueprint.Document.Fragment.Named{} = node, operations) do 21 if uses?(node, operations) do 22 node 23 else 24 node 25 |> flag_invalid(:not_used) 26 |> put_error(error(node)) 27 end 28 end 29 30 def handle_node(node, _) do 31 node 32 end 33 34 @spec uses?(Blueprint.Document.Fragment.Named.t(), [Blueprint.Document.Operation.t()]) :: 35 boolean 36 defp uses?(node, operations) do 37 Enum.any?(operations, &Blueprint.Document.Operation.uses?(&1, node)) 38 end 39 40 # Generate the error for the node 41 @spec error(Blueprint.Document.Fragment.Named.t()) :: Phase.Error.t() 42 defp error(node) do 43 %Phase.Error{ 44 phase: __MODULE__, 45 message: error_message(node.name), 46 locations: [node.source_location] 47 } 48 end 49 50 @doc """ 51 Generate an error message for an unused fragment. 52 """ 53 @spec error_message(String.t()) :: String.t() 54 def error_message(name) do 55 ~s(Fragment "#{name}" is never used.) 56 end 57 end