mix dialyzer (dialyzex v1.3.0) View Source
Prepares and runs static analysis of application code via
dialyzer
.
PLT Creation
For efficiency, we construct multiple PLTs: one for Erlang and the runtime system (ERTS), one for Elixir, and one for the transitive dependencies of the project. The rationale here is that the Erlang installation, Elixir installation, and the dependencies of the project have different lifetimes. Erlang and Elixir, for example, would not change across builds of the same project, but a dependency might. Additionally, analyzing the standard library in order to construct a PLT is expensive and should be done infrequently.
By default, Erlang and Elixir PLTs are stored in a hidden subdirectory
of the user's home directory, namely ~/.cache/dialyzer/plts
. The
contents of that directory after building PLTs might look like the
below:
$ ls ~/.cache/dialyzer/plts/
elixir-1.6.1-erlang-20-erts-9.2.plt erlang-20-erts-9.2.plt
You can change where Erlang and Elixir PLTs are stored using
the :dialyzer_cache_directory
config key in the Mix project
configuration. Setting the key to nil
will make dialyzex use
the default directory, so you can easily configure it based
on the Mix.env()
def project do
[
...
dialyzer_cache_directory: dialyzer_cache_directory(Mix.env()),
...
]
end
defp dialyzer_cache_directory(:ci) do
".cache"
end
defp dialyzer_cache_directory(_) do
nil
end
The dependencies PLT is stored in the build directory of the current
Mix.env
, e.g. _build/dev/deps-N0rJXDclQ8d-ibrpSc_emw.plt
.
Warnings
All non-default recommended warnings are turned on, equivalent to these command-line flags to dialyzer:
-Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspecs -Wunknown
Warnings can be customized using the :dialyzer_warnings
config key
in the Mix project configuration.
If warnings are emitted from analysis, the task will exit
non-zero. In some cases, there are particular warning signatures
that are acceptable and should not cause failure of an automated
build. These signatures can be matched and ignored via the
:dialyzer_ignored_warnings
setting. The format of this list are
match patterns of the warning tuples produced by dialyzer:
{tag, {file, line}, {warning_type, arguments}}
The warning tuples coming from your analysis can be printed by turning debug mode on:
$ MIX_DEBUG=1 mix dialyzer --check=false
# [snip]
Running analysis...
Errors:
ct.ex:177: The created fun only terminates with explicit exception
dialyzer.ex:282: The created fun only terminates with explicit exception
IGNORED WARNINGS:
[]
FAILURES:
[{:warn_return_only_exit, {'lib/mix/tasks/ct.ex', 177},
{:no_return, [:only_explicit]}},
{:warn_return_only_exit, {'lib/mix/tasks/dialyzer.ex', 282},
{:no_return, [:only_explicit]}}]
FAILURE: 2 failures.
From those tuples, you can determine how to construct the match pattern. If one wanted to ignore the first failure, the following pattern would work:
{:warn_return_only_exit, {'lib/mix/tasks/ct.ex', :_}, {:no_return, :_}}
For fields of the tuple that aren't important to distinguish, use
:_
to match all patterns in that space. See OTP's documentation on
match patterns and specs for more details.
Running analysis for specific files
You can limit the analysis to just specific files by specifying a :dialyzer_analysed_files
option under your project's mix config. It expects a function of type (-> [String.t])
that returns a list of .beam
files to be analysed.
Please note that this option makes no assumptions about consolidated protocols,
so if you get warnings regarding missing implementations for protocols
you probably need to add that protocol's consolidated .beam
file
(which is usually found under _build/#{env}/consolidated
)
to the list of analysed files.
Options
--check=(true|false)
: enable/disable checking of existing PLTs (default:true
)--compile=(true|false)
: enable/disable compilation of the project (default:true
)
Caveats
If checking an existing PLT fails (e.g. a dependency changed), you must remove the PLT to force a rebuild. This caveat is mitigated for the shared PLTs by naming them after their respective versions, which are assumed to be stable, and the dependency PLT after the hash of the lockfile contents (somewhat). In future versions, we could add or remove information from the PLTs as needed.