diff --git a/lib/ham/type_checker.ex b/lib/ham/type_checker.ex index 7ffcc1e..099a591 100644 --- a/lib/ham/type_checker.ex +++ b/lib/ham/type_checker.ex @@ -86,15 +86,21 @@ defmodule Ham.TypeChecker do end defp fetch_typespecs(module, function_name, arity) do - with {:ok, specs} <- fetch_specs(module) do + with {:ok, specs} <- fetch_specs(module, :specs, &Code.Typespec.fetch_specs/1) do {:ok, Map.get(specs, {function_name, arity}, [])} end end - defp fetch_specs(module) do - case Cache.get({:specs, module}) do + defp fetch_callback_typespecs(module, function_name, arity) do + with {:ok, specs} <- fetch_specs(module, :callbacks, &Code.Typespec.fetch_callbacks/1) do + {:ok, Map.get(specs, {function_name, arity}, [])} + end + end + + defp fetch_specs(module, key, fetcher) do + case Cache.get({key, module}) do nil -> - case Code.Typespec.fetch_specs(module) do + case fetcher.(module) do {:ok, specs} -> specs = specs @@ -107,7 +113,7 @@ defmodule Ham.TypeChecker do {{function_name, arity}, typespecs} end) - Cache.put({:specs, module}, specs) + Cache.put({key, module}, specs) {:ok, specs} :error -> @@ -119,36 +125,6 @@ defmodule Ham.TypeChecker do end end - defp fetch_callback_typespecs(module, function_name, arity) do - cache_key = {:callback_typespecs, {module, function_name, arity}} - - case Cache.get(cache_key) do - nil -> - with {:ok, typespecs} <- do_fetch_callback_typespecs(module, function_name, arity) do - Cache.put(cache_key, typespecs) - {:ok, typespecs} - end - - typespecs -> - {:ok, typespecs} - end - end - - defp do_fetch_callback_typespecs(module, function_name, arity) do - with {:ok, callbacks} <- fetch_callbacks(module) do - callbacks = - callbacks - |> Enum.find_value([], fn - {{^function_name, ^arity}, typespecs} -> typespecs - _ -> false - end) - |> Enum.map(&guards_to_annotated_types(&1)) - |> Enum.map(&Utils.replace_user_types(&1, module)) - - {:ok, callbacks} - end - end - defp guards_to_annotated_types({:type, _, :fun, _} = typespec), do: typespec defp guards_to_annotated_types( @@ -185,23 +161,6 @@ defmodule Ham.TypeChecker do end) end - defp fetch_callbacks(behaviour_module) do - case Cache.get({:callbacks, behaviour_module}) do - nil -> - case Code.Typespec.fetch_callbacks(behaviour_module) do - {:ok, callbacks} -> - Cache.put({:callbacks, behaviour_module}, callbacks) - {:ok, callbacks} - - :error -> - {:error, {:module_fetch_failure, behaviour_module}} - end - - callbacks -> - {:ok, callbacks} - end - end - defp fetch_behaviours_typespecs(behaviours, function_name, arity) do Enum.reduce_while(behaviours, {:ok, []}, fn behaviour, {:ok, acc} -> case fetch_callback_typespecs(behaviour, function_name, arity) do