exercism / elixir-analyzer

GNU Affero General Public License v3.0
30 stars 32 forks source link

Take-A-Number-Deluxe @impl required #316

Closed louis-cl closed 2 years ago

louis-cl commented 2 years ago

Seems that the analysis requires the @impl annotation for all methods. Where I see recommendation to only mark the first method of each kind

My solution

defmodule TakeANumberDeluxe do
  # Client API

  @spec start_link(keyword()) :: {:ok, pid()} | {:error, atom()}
  def start_link(init_arg) do
    GenServer.start_link(__MODULE__, init_arg)
  end

  @spec report_state(pid()) :: TakeANumberDeluxe.State.t()
  def report_state(machine) do
    GenServer.call(machine, :get_state)
  end

  @spec queue_new_number(pid()) :: {:ok, integer()} | {:error, atom()}
  def queue_new_number(machine) do
    GenServer.call(machine, :new_number)
  end

  @spec serve_next_queued_number(pid(), integer() | nil) :: {:ok, integer()} | {:error, atom()}
  def serve_next_queued_number(machine, priority_number \\ nil) do
    GenServer.call(machine, {:serve, priority_number})
  end

  @spec reset_state(pid()) :: :ok
  def reset_state(machine) do
    GenServer.cast(machine, :reset)
  end

  # Server callbacks
  use GenServer

  @impl GenServer
  def init(opts) do
    timeout = Keyword.get(opts, :auto_shutdown_timeout, :infinity)

    case TakeANumberDeluxe.State.new(opts[:min_number], opts[:max_number], timeout) do
      {:ok, state} -> {:ok, state, timeout}
      {:error, reason} -> {:stop, reason}
    end
  end

  @impl GenServer
  def handle_call(:get_state, _, state) do
    {:reply, state, state, state.auto_shutdown_timeout}
  end

  def handle_call(:new_number, _, state) do
    case TakeANumberDeluxe.State.queue_new_number(state) do
      {:ok, new_number, new_state} ->
        {:reply, {:ok, new_number}, new_state, state.auto_shutdown_timeout}

      err ->
        {:reply, err, state, state.auto_shutdown_timeout}
    end
  end

  def handle_call({:serve, priority_number}, _, state) do
    case TakeANumberDeluxe.State.serve_next_queued_number(state, priority_number) do
      {:ok, next_number, new_state} ->
        {:reply, {:ok, next_number}, new_state, state.auto_shutdown_timeout}

      err ->
        {:reply, err, state, state.auto_shutdown_timeout}
    end
  end

  @impl GenServer
  def handle_cast(:reset, state) do
    {:ok, new_state} =
      TakeANumberDeluxe.State.new(state.min_number, state.max_number, state.auto_shutdown_timeout)

    {:noreply, new_state, state.auto_shutdown_timeout}
  end

  @impl GenServer
  def handle_info(:timeout, state) do
    {:stop, :normal, state}
  end

  def handle_info(_, state) do
    {:noreply, state, state.auto_shutdown_timeout}
  end
end
angelikatyborska commented 2 years ago

Thank you! I opened a PR with a fix, now it needs to wait for a review from another maintainer 🙂