Skip to content

Commit

Permalink
Build type __reference__ values for SDL-generated types (#635)
Browse files Browse the repository at this point in the history
* Basic ref handling

* Build __reference__ from SDL :path source location
  • Loading branch information
bruce authored Nov 15, 2018
1 parent bac0c7c commit 8b7bcee
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 22 deletions.
5 changes: 1 addition & 4 deletions lib/absinthe/language/input_value_definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ defmodule Absinthe.Language.InputValueDefinition do
identifier: Macro.underscore(node.name) |> String.to_atom(),
default_value: Blueprint.Draft.convert(node.default_value, doc),
directives: Blueprint.Draft.convert(node.directives, doc),
source_location: source_location(node),
__reference__: %{
location: source_location(node) |> Map.put(:file, "TODO")
}
source_location: source_location(node)
}
end

Expand Down
20 changes: 12 additions & 8 deletions lib/absinthe/schema/notation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1150,12 +1150,14 @@ defmodule Absinthe.Schema.Notation do
"""
@spec import_sdl([import_sdl_option(), ...]) :: Macro.t()
defmacro import_sdl(opts) when is_list(opts) do
do_import_sdl(nil, opts)
__CALLER__
|> do_import_sdl(nil, opts)
end

@spec import_sdl(String.t() | Macro.t(), [import_sdl_option()]) :: Macro.t()
defmacro import_sdl(sdl, opts \\ []) do
do_import_sdl(sdl, opts)
__CALLER__
|> do_import_sdl(sdl, opts)
end

defmacro values(values) do
Expand Down Expand Up @@ -1471,19 +1473,20 @@ defmodule Absinthe.Schema.Notation do
[]
end

@spec do_import_sdl(nil, [import_sdl_option()]) :: Macro.t()
defp do_import_sdl(nil, opts) do
@spec do_import_sdl(Macro.Env.t(), nil, [import_sdl_option()]) :: Macro.t()
defp do_import_sdl(env, nil, opts) do
case Keyword.fetch(opts, :path) do
{:ok, path} ->
[
quote do
@__absinthe_import_sdl_path__ unquote(path)
end,
do_import_sdl(
env,
quote do
File.read!(@__absinthe_import_sdl_path__)
end,
Keyword.delete(opts, :path)
opts
),
quote do
@external_resource @__absinthe_import_sdl_path__
Expand All @@ -1495,10 +1498,11 @@ defmodule Absinthe.Schema.Notation do
end
end

@spec do_import_sdl(String.t() | Macro.t(), Keyword.t()) :: Macro.t()
defp do_import_sdl(sdl, _opts) do
@spec do_import_sdl(Macro.Env.t(), String.t() | Macro.t(), Keyword.t()) :: Macro.t()
defp do_import_sdl(env, sdl, opts) do
ref = build_reference(env)
quote do
with {:ok, definitions} <- unquote(__MODULE__).SDL.parse(unquote(sdl), __MODULE__) do
with {:ok, definitions} <- unquote(__MODULE__).SDL.parse(unquote(sdl), __MODULE__, unquote(Macro.escape(ref)), unquote(Macro.escape(opts))) do
@__absinthe_sdl_definitions__ definitions ++
(Module.get_attribute(
__MODULE__,
Expand Down
32 changes: 30 additions & 2 deletions lib/absinthe/schema/notation/sdl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ defmodule Absinthe.Schema.Notation.SDL do
@doc """
Parse definitions from SDL source
"""
@spec parse(sdl :: String.t(), Module.t()) ::
@spec parse(sdl :: String.t(), Module.t(), map(), Keyword.t()) ::
{:ok, [Absinthe.Blueprint.Schema.type_t()]} | {:error, String.t()}
def parse(sdl, module) do
def parse(sdl, module, ref, opts) do
with {:ok, doc} <- Absinthe.Phase.Parse.run(sdl) do
definitions =
doc.input.definitions
|> Enum.map(&Absinthe.Blueprint.Draft.convert(&1, doc))
|> Enum.map(&put_ref(&1, ref, opts))
|> Enum.map(fn type -> %{type | module: module} end)

{:ok, definitions}
Expand All @@ -27,4 +28,31 @@ defmodule Absinthe.Schema.Notation.SDL do
other
end
end

defp put_ref(%{fields: fields} = node, ref, opts) do
%{node | fields: Enum.map(fields, &put_ref(&1, ref, opts))}
|> do_put_ref(ref, opts)
end
defp put_ref(%{arguments: args} = node, ref, opts) do
%{node | arguments: Enum.map(args, &put_ref(&1, ref, opts))}
|> do_put_ref(ref, opts)
end
defp put_ref(%{directives: dirs} = node, ref, opts) do
%{node | directives: Enum.map(dirs, &put_ref(&1, ref, opts))}
|> do_put_ref(ref, opts)
end
defp put_ref(node, ref, opts), do: do_put_ref(node, ref, opts)

defp do_put_ref(%{__reference__: nil} = node, ref, opts) do
ref =
case opts[:path] do
nil ->
ref
path ->
put_in(ref.location, %{file: path, line: node.source_location.line})
end
%{node | __reference__: ref}
end
defp do_put_ref(node, _ref, _opts), do: node

end
8 changes: 0 additions & 8 deletions test/absinthe/language/field_definition_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@ defmodule Absinthe.Language.FieldDefinitionTest do
},
arguments: [
%Blueprint.Schema.InputValueDefinition{
__reference__: %{
location: %{
__struct__: Absinthe.Blueprint.SourceLocation,
column: 10,
file: "TODO",
line: 4
}
},
name: "limit",
identifier: :limit,
type: %Blueprint.TypeReference.Name{name: "Int"},
Expand Down

0 comments on commit 8b7bcee

Please sign in to comment.