sdl.ex (2445B)
1 defmodule Absinthe.Schema.Notation.SDL do 2 @moduledoc false 3 4 @doc """ 5 Parse definitions from SDL source 6 """ 7 8 alias Absinthe.{Blueprint, Language.Source} 9 10 @spec parse(sdl :: Source.t() | Blueprint.t(), module(), map(), Keyword.t()) :: 11 {:ok, [Blueprint.Schema.t()]} | {:error, String.t()} 12 def parse(sdl, module, ref, opts) do 13 with {:ok, doc} <- Absinthe.Phase.Parse.run(sdl) do 14 definitions = 15 doc.input.definitions 16 |> Enum.map(&Absinthe.Blueprint.Draft.convert(&1, doc)) 17 |> Enum.map(&put_ref(&1, ref, opts)) 18 |> Enum.map(fn type -> %{type | module: module} end) 19 20 {:ok, definitions} 21 else 22 {:error, %Blueprint{execution: %{validation_errors: [_ | _] = errors}}} -> 23 error = 24 errors 25 |> Enum.map(&"#{&1.message} (#{inspect(&1.locations)})") 26 |> Enum.join("\n") 27 28 {:error, error} 29 30 other -> 31 other 32 end 33 end 34 35 defp put_ref(%{fields: fields, directives: directives} = node, ref, opts) do 36 %{ 37 node 38 | fields: Enum.map(fields, &put_ref(&1, ref, opts)), 39 directives: Enum.map(directives, &put_ref(&1, ref, opts)) 40 } 41 |> do_put_ref(ref, opts) 42 end 43 44 defp put_ref(%{fields: fields} = node, ref, opts) do 45 %{node | fields: Enum.map(fields, &put_ref(&1, ref, opts))} 46 |> do_put_ref(ref, opts) 47 end 48 49 defp put_ref(%{arguments: args, directives: directives} = node, ref, opts) do 50 %{ 51 node 52 | arguments: Enum.map(args, &put_ref(&1, ref, opts)), 53 directives: Enum.map(directives, &put_ref(&1, ref, opts)) 54 } 55 |> do_put_ref(ref, opts) 56 end 57 58 defp put_ref(%{arguments: args} = node, ref, opts) do 59 %{node | arguments: Enum.map(args, &put_ref(&1, ref, opts))} 60 |> do_put_ref(ref, opts) 61 end 62 63 defp put_ref(%{directives: directives} = node, ref, opts) do 64 %{node | directives: Enum.map(directives, &put_ref(&1, ref, opts))} 65 |> do_put_ref(ref, opts) 66 end 67 68 defp put_ref(node, ref, opts), do: do_put_ref(node, ref, opts) 69 70 defp do_put_ref(%{__reference__: nil} = node, ref, opts) do 71 ref = 72 case opts[:path] do 73 nil -> 74 ref 75 76 path -> 77 put_in(ref.location, %{ 78 file: {:unquote, [], [path]}, 79 line: node.source_location.line, 80 column: node.source_location.column 81 }) 82 end 83 84 %{node | __reference__: ref} 85 end 86 87 defp do_put_ref(node, _ref, _opts), do: node 88 end