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:
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