 defmodule Credo.Check.Warning.MapGetUnsafePass do
   @moduledoc """
-  `Map.get/2` can lead into runtime errors if the result is passed into a pipe without a proper default value.
-  This happens when the next function in the pipe cannot handle `nil` values correctly.
+  `Map.get/2` can lead into runtime errors if the result is passed into a pipe
+  without a proper default value. This happens when the next function in the
+  pipe cannot handle `nil` values correctly.
 
   Example:
 

        |> Map.get(:baz)
        |> Enum.each(&IO.puts/1)


  This will cause a `Protocol.UndefinedError`, since `nil` isn't `Enumerable`. Often times while
  iterating over enumerables zero iterations is preferrable to being forced to deal with an exception.
  Had there been a `[]` default parameter this could have been averted.

  Encourage use of `Map.get/3` instead to provide safer default values.
  """

  @explanation [check: @moduledoc]
  @call_string "Map.get/2"

  use Credo.Check, base_priority: :normal


    {ast, issues}
  end

  defp unsafe_expr?({expr, idx}) do
    required_length =
      case idx do
        0 -> 3
        _ -> 2
      end

    case expr do
      {{{:., _, [{_, _, [:Map]}, :get]}, _, args}, _} ->
        length(args) != required_length
      _ ->
        false
    end
  end

  defp issue_for(issue_meta, line_no, trigger) do
    format_issue issue_meta,
      message: "Map.get with no default return value is potentially unsafe
                in pipes, use Map.get/3 instead",
      trigger: trigger,
      line_no: line_no
  end
