Mix tasks to simplify use of Dialyzer in Elixir projects.
Elixir
Latest commit 7fadb12 Jul 4, 2016 @jeremyjh committed on GitHub Merge pull request #49 from gmile/fix-1.4-warnings
Fix Elixir 1.4 warnings

README.md

Dialyxir

Mix tasks to simplify use of Dialyzer in Elixir projects.

Quickstart

If you are planning to use Dialyzer with an application built with the Phoenix Framework, check out the Quickstart wiki.

Installation

Dialyxir is available on hex.pm.

You can either add it as a dependency in your mix.exs, or install it globally as an archive task.

To add it to a mix project, just add a line like this in your deps function in mix.exs:

defp deps do
  [{:dialyxir, "~> 0.3.5", only: [:dev]}]
end
mix deps.get
mix deps.compile

To install globally as an archive:

git clone https://github.com/jeremyjh/dialyxir
cd dialyxir
mix archive.build
mix archive.install

Usage

The first time you use Dialyxir, or each time that you upgrade your Erlang or Elixir version you will need to rebuild the PLT.

mix dialyzer.plt

Use it from directory of the mix project you want to analyze; the project will be automatically compiled if needed (pass --no-compile to disable this).

mix dialyzer

With Explaining Stuff

Dialyzer is a static analysis tool for Erlang and other languages that compile to BEAM bytecode for the Erlang VM. It can analyze the BEAM files and provide warnings about problems in your code including type mismatches and other issues that are commonly detected by static language compilers. The analysis can be improved by inclusion of type hints (called specs) but it can be useful even without those. For more information I highly recommend the Success Typings paper that describes the theory behind the tool.

Usage is straightforward but you should be aware of the available configuration settings you may wish to add to your mix.exs file.

PLT

The Persistent Lookup Table (PLT) is basically a cached output of the analysis. This is important because you'd probably stab yourself in the eye with a fork if you had to wait for Dialyzer to analyze all the standard library and OTP modules you are using everytime you ran it. Running the mix task dialyzer.plt builds a PLT in HOME/.dialyxir_core_[OTP Version]_[Elixir Version].plt.

If you don't want all your projects to share a PLT you can specify a :plt_file key with a string containing the filename you want e.g. dialyzer: plt_file: ".local.plt".

The default PLT includes a basic set of OTP applications, as well as all of the Elixir standard libraries. This may well meet your needs, but if you are using additional OTP applications in your project you'll want to add those as well. The apps included by default are [ :erts, :kernel, :stdlib, :crypto, :public_key]. If you need additional ones, add them to a dialyzer: plt_add_apps: key in your mix.exs (you can also add individual project dependencies this way):

def project do
 [ app: :my_app,
   version: "0.0.1",
   deps: deps,
   dialyzer: [plt_add_apps: [:mnesia, :ecto]]
 ]
end

If you don't want to include the default apps you can specify a :plt_apps key and list there only the apps you want in the PLT.

Dependencies

There is also a :plt_add_deps option you can set to automatically add dependencies to the PLT. You can set this key to either :project (or true) - which adds only your project's direct dependencies - or :transitive - which will pull in the project's full dependency tree.

def project do
 [ app: :my_app,
   version: "0.0.1",
   deps: deps,
   dialyzer: [plt_add_deps: :transitive]
 ]
end

You can re-run the dialyzer.plt task at any time. It will check all the libraries to see if they need to be updated in the PLT, and it will add any new apps you've added to your project config. It will only rebuild the PLT if you delete it or if you upgrade your Erlang or Elixir version.

Warning Flags

There are a number of warning flags used to enable or disable certain kinds of analysis features. You may find yourself reaching a point where one of these warnings is bothering you much more than it is helping you. In that case you can remove that warning by adjusting your flags. The default flags are "-Wunmatched_returns", "-Werror_handling", "-Wrace_conditions", "-Wunderspecs". You can specify the full list in the flags key:

def project do
 [ app: :my_app,
   version: "0.0.1",
   deps: deps,
   dialyzer: [plt_apps: [:erts, :kernel, :stdlib, :mnesia],
             flags: ["-Wunmatched_returns","-Werror_handling","-Wrace_conditions", "-Wno_opaque"]]
 ]
end

Paths

By default only the ebin in the _build directory for the current mix environment of your project is included in paths to search for BEAM files to perform analysis on. You may well want to add your deps to the analysis, but I would recommend trying them one at a time. Also as the deps can significantly slow down your analysis you may want to add them to your PLT.

def project do
 [ app: :my_app,
   version: "0.0.1",
   deps: deps,
   dialyzer: [plt_apps: ["erts","kernel", "stdlib", "crypto", "public_key", "mnesia"],
             flags: ["-Wunmatched_returns","-Werror_handling","-Wrace_conditions", "-Wno_opaque"],
             paths: ["_build/dev/lib/my_app/ebin", "_build/dev/lib/foo/ebin"]]
 ]
end