Dialyzer is a static-analysis tool for Erlang and Elixir. It’s very useful for catching errors having to do with type-checking, but it can be a pain to use. The analysis is notoriously slow, so programmers typically use a tool like Dialyxir to maintain a PLT file (“Persistent Lookup Table”) with the saved analysis of files that change infrequently, such as core Elixir libraries or project dependencies. Once a PLT file is generated, Dialyzer’s analysis can be acceptably fast.

But even with tools like Dialyxir, using Dialyzer isn’t as fast or easy as it could be. For example, you need to determine which core Erlang or Elixir libraries such as :ets or Mix to include when you build your PLT. If you forget to include them, Dialyzer can’t give you useful analysis when you use them in your code. Dialyzer also re-analyzes all the modules in your project every time, even if no modules they reference have changed.

I took a stab at addressing these shortcomings, and ElixirLS 0.2 includes an experimental, incremental Dialyzer server that runs after each successful build. It uses undocumented, internal Dialyzer APIs, and it’s only compatible with Erlang/OTP 20. Future Erlang changes might break it, but so far it seems pretty reliable when used with OTP 20. You can set elixirLS.dialyzerEnabled to false to disable it if it breaks.

The server keeps a manifest similar to a PLT file in .elixir_ls . After each build, it looks for modules that changed and only re-analyzes modules when necessary. It also looks at the abstract code in your compiled beam files to determine which core Erlang or Elixir modules you use. If it sees that you’re referencing a library that isn’t already analyzed, it includes it in the analysis automatically. That way, you never get “unknown module” warnings and you don’t have to manually specify which applications you reference. It just works, and after the initial analysis, it’s quite fast.

You can change the setting elixirLS.dialyzerWarnOpts to control which warnings are shown, though Dialyzer’s defaults are good for most projects. You can also set the module attribute @dialyzer to show or hide warnings at a module or function level.

I’m hoping that fast and easy static analysis can smooth over the problems that come from dynamic typing. Getting immediate feedback when you pass an argument of the wrong type or write an incorrect pattern-match can take a lot of the guesswork out of writing correct code.

Installing Elixir 1.6, Erlang/OTP 20, and ElixirLS

To take advantage of these new features, you’ll need Elixir 1.6 and Erlang OTP/20. Since Elixir 1.6 isn’t released yet, you’ll need to install a pre-release version. I highly recommend installing both Elixir and Erlang from source using the tools kiex and kerl, respectively. That’ll let you use go-to-definition to jump from your code to the source code for core Elixir and Erlang modules. To install the latest pre-release Elixir with kiex, run kiex install master . To install ElixirLS, search “elixirls” in the extensions pane in VS Code. It’ll automatically use whatever Elixir and Erlang installations are the default in your shell.

Feedback is very welcome. Happy coding!