akoutmos / doctor

Ensure that your Elixir project documentation is healthy
MIT License
179 stars 15 forks source link

Reports missing docs when it should not #61

Open flupke opened 1 year ago

flupke commented 1 year ago

The following module is reported as missing a docstring in one of its functions:

defmodule MultiplayerBackend.Ack do
  @moduledoc """
  Functions responsible for creating actions acknowledgements.
  """

  @type action :: :add_node | :remove_node | :update_properties

  @type invalid_payload(action) ::
          %{
            action: action,
            status: :error,
            error: :invalid_payload
          }

  @type forbidden(action) ::
          %{
            action: action,
            status: :error,
            error: :forbidden,
            action_id: String.t()
          }

  @type add_node ::
          %{
            action: :add_node,
            status: :ok,
            action_id: String.t(),
            node: map(),
            edits_count: integer()
          }

  @type add_node_action_already_applied ::
          %{
            action: :add_node,
            status: :error,
            error: :action_already_applied,
            action_id: String.t(),
            node_id: String.t(),
            node: map() | nil,
            edits_count: integer()
          }

  @type add_node_node_already_exists ::
          %{
            action: :add_node,
            status: :error,
            error: :node_already_exists,
            action_id: String.t(),
            node_id: String.t(),
            node: map() | nil,
            edits_count: integer()
          }

  @type add_node_unknown_parent ::
          %{
            action: :add_node,
            status: :error,
            error: :unknown_parent,
            action_id: String.t(),
            node_id: String.t(),
            edits_count: integer()
          }

  @type add_node_acknowledgement ::
          add_node()
          | add_node_action_already_applied()
          | add_node_node_already_exists()
          | add_node_unknown_parent()
          | invalid_payload(:add_node)
          | forbidden(:add_node)

  @type remove_node :: %{
          action: :remove_node,
          status: :ok,
          action_id: String.t(),
          node_id: String.t(),
          removed_nodes_ids: [String.t()],
          edits_count: integer()
        }

  @type remove_node_action_already_applied ::
          %{
            action: :remove_node,
            status: :error,
            error: :action_already_applied,
            action_id: String.t(),
            node_id: String.t(),
            removed_nodes_ids: [String.t()],
            edits_count: integer()
          }

  @type remove_node_node_not_found ::
          %{
            action: :remove_node,
            status: :error,
            error: :node_not_found,
            action_id: String.t(),
            node_id: String.t(),
            edits_count: integer()
          }

  @type remove_node_acknowledgement ::
          remove_node()
          | remove_node_action_already_applied()
          | remove_node_node_not_found()
          | invalid_payload(:remove_node)
          | forbidden(:remove_node)

  @type update_properties ::
          %{
            action: :update_properties,
            status: :ok,
            action_id: String.t(),
            node_id: String.t(),
            properties: map(),
            edits_count: integer()
          }

  @type update_properties_action_already_applied ::
          %{
            action: :update_properties,
            status: :error,
            error: :action_already_applied,
            action_id: String.t(),
            node_id: String.t(),
            properties: map(),
            edits_count: integer()
          }

  @type update_properties_node_not_found ::
          %{
            action: :update_properties,
            status: :error,
            error: :node_not_found,
            action_id: String.t(),
            node_id: String.t(),
            edits_count: integer()
          }

  @type update_properties_cannot_move_under_itself ::
          %{
            action: :update_properties,
            status: :error,
            error: :cannot_move_under_itself,
            action_id: String.t(),
            node_id: String.t(),
            properties: map(),
            edits_count: integer()
          }

  @type update_properties_acknowledgement ::
          update_properties()
          | update_properties_action_already_applied()
          | update_properties_node_not_found()
          | update_properties_cannot_move_under_itself()
          | invalid_payload(:update_properties)
          | forbidden(:update_properties)

  @type action_acknowledgement ::
          add_node_acknowledgement()
          | remove_node_acknowledgement()
          | update_properties_acknowledgement()

  @doc false
  @spec invalid_payload(action :: action()) :: invalid_payload(action)
  def invalid_payload(action) do
    %{
      action: action,
      status: :error,
      error: :invalid_payload
    }
  end

  @doc false
  @spec forbidden(action :: action(), action_id :: String.t()) :: forbidden(action)
  def forbidden(action, action_id) do
    %{
      action: action,
      status: :error,
      error: :forbidden,
      action_id: action_id
    }
  end

  @doc false
  @spec add_node(action_id :: String.t(), node :: map(), edits_count :: integer()) :: add_node()
  def add_node(action_id, node, edits_count) do
    %{
      status: :ok,
      action: :add_node,
      action_id: action_id,
      node: node,
      edits_count: edits_count
    }
  end

  @doc false
  @spec add_node_error(
          error :: :action_already_applied,
          action_id :: String.t(),
          node_id :: String.t(),
          node :: map() | nil,
          edits_count :: integer()
        ) :: add_node_action_already_applied()
  def add_node_error(:action_already_applied, action_id, node_id, node, edits_count) do
    add_node_error_base(:action_already_applied, action_id, node_id, node, edits_count)
  end

  @doc false
  @spec add_node_error(
          error :: :node_already_exists,
          action_id :: String.t(),
          node_id :: String.t(),
          node :: map() | nil,
          edits_count :: integer()
        ) :: add_node_node_already_exists()
  def add_node_error(:node_already_exists, action_id, node_id, node, edits_count) do
    add_node_error_base(:node_already_exists, action_id, node_id, node, edits_count)
  end

  @doc false
  @spec add_node_error(
          error :: :unknown_parent,
          action_id :: String.t(),
          node_id :: String.t(),
          edits_count :: integer()
        ) :: add_node_unknown_parent()
  def add_node_error(:unknown_parent, action_id, node_id, edits_count) do
    %{
      action: :add_node,
      status: :error,
      error: :unknown_parent,
      action_id: action_id,
      node_id: node_id,
      edits_count: edits_count
    }
  end

  defp add_node_error_base(error, action_id, node_id, node, edits_count) do
    %{
      action: :add_node,
      status: :error,
      error: error,
      action_id: action_id,
      node: node,
      node_id: node_id,
      edits_count: edits_count
    }
  end

  @doc false
  @spec remove_node(
          action_id :: String.t(),
          node_id :: String.t(),
          removed_nodes_ids :: [String.t()],
          edits_count :: integer()
        ) :: remove_node()
  def remove_node(action_id, node_id, removed_nodes_ids, edits_count) do
    %{
      status: :ok,
      action: :remove_node,
      action_id: action_id,
      node_id: node_id,
      removed_nodes_ids: removed_nodes_ids,
      edits_count: edits_count
    }
  end

  @doc false
  @spec remove_node_error(
          error :: :action_already_applied,
          action_id :: String.t(),
          node_id :: String.t(),
          removed_nodes_ids :: [String.t()],
          edits_count :: integer()
        ) :: remove_node_action_already_applied()
  def remove_node_error(
        :action_already_applied,
        action_id,
        node_id,
        removed_nodes_ids,
        edits_count
      ) do
    %{
      action: :remove_node,
      status: :error,
      error: :action_already_applied,
      action_id: action_id,
      node_id: node_id,
      removed_nodes_ids: removed_nodes_ids,
      edits_count: edits_count
    }
  end

  @doc false
  @spec remove_node_error(
          error :: :node_not_found,
          action_id :: String.t(),
          node_id :: String.t(),
          edits_count :: integer()
        ) :: remove_node_node_not_found()
  def remove_node_error(:node_not_found, action_id, node_id, edits_count) do
    %{
      action: :remove_node,
      status: :error,
      error: :node_not_found,
      action_id: action_id,
      node_id: node_id,
      edits_count: edits_count
    }
  end

  @doc false
  @spec update_properties(
          action_id :: String.t(),
          node_id :: String.t(),
          properties :: map(),
          edits_count :: integer()
        ) :: update_properties()
  def update_properties(action_id, node_id, properties, edits_count) do
    %{
      status: :ok,
      action: :update_properties,
      action_id: action_id,
      node_id: node_id,
      properties: properties,
      edits_count: edits_count
    }
  end

  @doc false
  @spec update_properties_error(
          error :: :action_already_applied,
          action_id :: String.t(),
          node_id :: String.t(),
          properties :: map(),
          edits_count :: integer()
        ) :: update_properties_action_already_applied()
  def update_properties_error(
        :action_already_applied,
        action_id,
        node_id,
        properties,
        edits_count
      ) do
    %{
      action: :update_properties,
      status: :error,
      error: :action_already_applied,
      action_id: action_id,
      node_id: node_id,
      properties: properties,
      edits_count: edits_count
    }
  end

  @doc false
  @spec update_properties_error(
          error :: :cannot_move_under_itself,
          action_id :: String.t(),
          node_id :: String.t(),
          properties :: map(),
          edits_count :: integer()
        ) :: update_properties_cannot_move_under_itself()
  def update_properties_error(
        :cannot_move_under_itself,
        action_id,
        node_id,
        properties,
        edits_count
      ) do
    %{
      action: :update_properties,
      status: :error,
      error: :cannot_move_under_itself,
      action_id: action_id,
      node_id: node_id,
      properties: properties,
      edits_count: edits_count
    }
  end

  @doc false
  @spec update_properties_error(
          error :: :node_not_found,
          action_id :: String.t(),
          node_id :: String.t(),
          edits_count :: integer()
        ) :: update_properties_node_not_found()
  def update_properties_error(:node_not_found, action_id, node_id, edits_count) do
    %{
      status: :error,
      action: :update_properties,
      action_id: action_id,
      error: :node_not_found,
      node_id: node_id,
      edits_count: edits_count
    }
  end
end

Here is doctor.explain output:

$ mix doctor.explain MultiplayerBackend.Ack                                                                       (06-22 17:47)
Doctor file found. Loading configuration.

Function                    @doc  @spec
---------------------------------------
update_properties_error/4   ✓     ✓
update_properties_error/5   ✓     ✓
update_properties/4         ✓     ✓
remove_node_error/4         ✓     ✓
remove_node_error/5         ✓     ✓
remove_node/4               ✓     ✓
add_node_error/4            ✓     ✓
add_node_error/5            ✓     ✓
add_node/3                  ✓     ✓
forbidden/2                 ✓     ✓
invalid_payload/1           ✓     ✓

Module Results:
  Doc Coverage:    90.9%  --> Your config has a 'min_module_doc_coverage' value of 100
  Spec Coverage:   100.0%
  Has Module Doc:  ✓
  Has Struct Spec: N/A