Repository: jeremyjh/dialyxir (elixir)

Issue:
Default ignore file?
Thinking of making `.dialyzer_ignore.exs` a default ignore file - if the file exists, we use it for ignores unless a different file is configured as the ignore file. This is something else people trip over. Also should probably update docs to make this more clearly the preferred format.

Pull request description:
Add ignore warnings default file behavior.
Resolves #224 

Also took the opportunity to clean up some things in these files, particularly naming of functions to signify legacy where appropriate. Messages user when using the default. 

Patch:
diff --git a/lib/dialyxir/formatter.ex b/lib/dialyxir/formatter.ex
index 869710a..a2bc17b 100644
--- a/lib/dialyxir/formatter.ex
+++ b/lib/dialyxir/formatter.ex
@@ -187,7 +187,7 @@ defmodule Dialyxir.Formatter do
         |> format_warning(:dialyzer)
         |> List.wrap()
 
-      Enum.empty?(filterer.filter_warnings(formatted_warnings))
+      Enum.empty?(filterer.filter_legacy_warnings(formatted_warnings))
     end)
   end
 end
diff --git a/lib/dialyxir/project.ex b/lib/dialyxir/project.ex
index 59b8816..121d64c 100644
--- a/lib/dialyxir/project.ex
+++ b/lib/dialyxir/project.ex
@@ -7,9 +7,10 @@ defmodule Dialyxir.Project do
     erlang_apps = [:erts, :kernel, :stdlib, :crypto]
 
     core_plts =
-      case exclude_core do
-        true -> []
-        false -> [{elixir_plt(), elixir_apps}, {erlang_plt(), erlang_apps}]
+      if exclude_core do
+        []
+      else
+        [{elixir_plt(), elixir_apps}, {erlang_plt(), erlang_apps}]
       end
 
     if include_project do
@@ -77,35 +78,40 @@ defmodule Dialyxir.Project do
   defp skip?(_, _), do: false
 
   def filter_warning?({file, warning, line, short_description}) do
-    ignore_file = dialyzer_ignore_warnings()
+    cond do
+      legacy_ignore_warnings?() ->
+        false
 
-    if ignore_file == nil or legacy_ignore_warnings?() do
-      false
-    else
-      {ignore, _} =
-        ignore_file
-        |> File.read!()
-        |> Code.eval_string()
+      dialyzer_ignore_warnings() == nil && !File.exists?(default_ignore_warnings()) ->
+        false
+
+      true ->
+        ignore_file = dialyzer_ignore_warnings() || default_ignore_warnings()
 
-      Enum.any?(ignore, &skip?(&1, {file, warning, line, short_description}))
+        {ignore, _} =
+          ignore_file
+          |> File.read!()
+          |> Code.eval_string()
+
+        Enum.any?(ignore, &skip?(&1, {file, warning, line, short_description}))
     end
   end
 
-  def filter_warnings(output) do
+  def filter_legacy_warnings(output) do
     ignore_file = dialyzer_ignore_warnings()
 
-    if ignore_file == nil or !legacy_ignore_warnings?() do
-      output
-    else
+    if legacy_ignore_warnings?() do
       pattern = File.read!(ignore_file)
-      filter_warnings(output, pattern)
+      filter_legacy_warnings(output, pattern)
+    else
+      output
     end
   end
 
-  def filter_warnings(output, nil), do: output
-  def filter_warnings(output, ""), do: output
+  def filter_legacy_warnings(output, nil), do: output
+  def filter_legacy_warnings(output, ""), do: output
 
-  def filter_warnings(output, pattern) do
+  def filter_legacy_warnings(output, pattern) do
     lines = Enum.map(output, &String.trim_trailing/1)
 
     patterns =
@@ -135,6 +141,10 @@ defmodule Dialyxir.Project do
     end
   end
 
+  def default_ignore_warnings() do
+    ".dialyzer_ignore.exs"
+  end
+
   def dialyzer_ignore_warnings() do
     dialyzer_config()[:ignore_warnings]
   end
diff --git a/lib/mix/tasks/dialyzer.ex b/lib/mix/tasks/dialyzer.ex
index 78a3597..c06cb23 100644
--- a/lib/mix/tasks/dialyzer.ex
+++ b/lib/mix/tasks/dialyzer.ex
@@ -160,6 +160,31 @@ defmodule Mix.Tasks.Dialyzer do
           check_plt(force_check?)
         end
 
+      default = Dialyxir.Project.default_ignore_warnings()
+      ignore_warnings = Dialyxir.Project.dialyzer_ignore_warnings()
+
+      cond do
+        !ignore_warnings && File.exists?(default) ->
+          info("""
+          No :ignore_warnings opt specified in mix.exs. Using default: #{default}.
+          """)
+
+        ignore_warnings && File.exists?(ignore_warnings) ->
+          info("""
+          ignore_warnings: #{ignore_warnings}
+          """)
+
+        ignore_warnings ->
+          info("""
+          :ignore_warnings opt specified in mix.exs: #{ignore_warnings}, but file does not exist.
+          """)
+
+        true ->
+          info("""
+          No :ignore_warnings opt specified in mix.exs and default does not exist.
+          """)
+      end
+
       unless opts[:plt], do: run_dialyzer(opts, dargs)
     else
       info("No mix project found - checking core PLTs...")


Test patch:
diff --git a/test/dialyxir/project_test.exs b/test/dialyxir/project_test.exs
index 8aa9236..38771c9 100644
--- a/test/dialyxir/project_test.exs
+++ b/test/dialyxir/project_test.exs
@@ -143,7 +143,7 @@ defmodule Dialyxir.ProjectTest do
       Guard test is_binary(_@4::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
       """
 
-      lines = Project.filter_warnings(output_list, pattern)
+      lines = Project.filter_legacy_warnings(output_list, pattern)
       assert lines == ["project.ex:9 This should still be here"]
     end)
   end