Introducing Rebar3 TypEr


Introducing Rebar3 TypEr
Do you have an Erlang codebase that’s a little short on type specs? Maybe you know TypEr exists, but wouldn’t it be nice to:
- incorporate it into your build system?
- configure it only once?
- have it ✨ magically✨ figure out all the command line arguments for you?
Good news
We built that! It’s called rebar3_typer
, and it (as the name implies) plugs into rebar3. With that rebar3 integration comes understanding the rest of your configuration. It’s available on hex.pm.
One of the first things we had to do was refactor the original upstream TypEr a bit. TypEr was always intended to be run from the command line. It didn’t have (or need) an API available from within the BEAM. Well, until now. We needed that. So, we split out a “core” module and sent that upstream. That’ll be in OTP 25.
On that note, contributions welcome. You can file bugs with us, submit improvements to our repo (improvements to the hexdocs especially welcome), or help out upstream.
We have to thank Viacheslav Katsuba for his rebar3_plugin template. It was very helpful for getting us a framework to start from so we could dive in. And of course, thanks to Kostis Sagonas for all his work on Dialyzer and TypEr.
How to use rebar3_typer
For a quick up-and-running, just add this to your rebar.config
(either in your project or globally in ~/.config/rebar3/rebar.config
):
{plugins, [rebar3_typer]}.
Then run…
rebar3 dialyzer
rebar3 typer
…and wait.
Without further configuration, it will:
- look for source files in the usual places
- look for source files wherever they’ve been configured in
rebar.config
for the project in general - look for Dialyzer’s PLT file in the usual place
- look for Dialyzer’s PLT file wherever it’s been configured in
rebar.config
for the project in general - emit a list of all the specs you can add to those modules, based on the types inferred by Dialyzer
Or if you want to take advantage of our enhancement that automatically annotates your source code directly for you, try:
rebar3 dialyzer
rebar3 typer --annotate-in-place
(Yes, this new feature has been sent upstream.)
Options
All options are available on the command line or in the rebar.config
file. The command-line options always override the options in the config file.
The basic config starts out:
{typer, []}.
Choose the files
If source file auto-detection doesn’t work for your situation, you’ll need to specify either a list of files (-f
) or a list of directories (-r
) (or both!) to be analyzed.
rebar3 typer -r d1,d2 -f foo.erl
Or
{typer, [
{recursive, ["d1/", "d2/"]},
{files, ["foo.erl"]}
]}.
Provide the PLT
If rebar3_typer
can’t find your PLT file (and you’re sure it’s already been generated), you can give it some hints.
rebar3 typer --plt myfile.plt
Or
{typer, [
{plt, "/path/to/plt"}
]}.
Show or annotate
Do you want it to only print the type specs to stdout, or do you want it to put its output in files?
If you want them printed to stdout, do you want it for all functions?
rebar3 typer --show
{typer, [
{mode, show}
]}.
Or maybe only for exported (public) functions?
rebar3 typer --show-exported
(--show_exported
is also accepted)
{typer, [
{mode, show_exported}
]}.
If you’d like the results to go to files, use an annotate
option instead of a show
option.
rebar3 typer --annotate
Or
{typer, [
{mode, annotate}
]}.
Do you want to annotate include()
files? (Warning, though: there is an open bug upstream for this feature.)
rebar3 typer --annotate-inc-files
(--annotate_inc_files
is also accepted)
Or
{typer, [
{mode, annotate_inc_files}
]}.
By default, annotations go into separate .ann.erl
files in a typer_ann/
directory. Would you like it to instead put the annotations directly into your code for you? Check out --annotate-in-place
rebar3 typer --annotate-in-place
(--annotate_in_place
is also accepted)
Or
{typer, [
{mode, annotate_in_place}
]}.
By default, only functions with missing specs will be addressed, in any of these modes.
What format to use
By default, rebar3_typer
will use -spec
syntax. If you’d prefer Edoc syntax (@spec
), you can specify that:
rebar3 typer --edoc
Or
{typer, [
{edoc, true}
]}.
How to handle pre-existing type specs
You have some options for what to do when it finds type specs already in place. If you have particular files with specs, and you want those specs to serve as the basis for additional type specs:
rebar3 typer -T f1,f2
Or
{typer, [
{typespec_files, ["f1", "f2"]}
]}.
(This accepts file names or directory names. But another warning: this also has an open bug upstream.)
If you’d rather existing type specs be completely ignored:
rebar3 typer --no_spec
Or
{typer, [
{no_spec, true}
]}.
Finally, TypEr has an option to show Dialyzer’s success typings, which is reachable through this plugin. This is undocumented upstream.
rebar3 typer --show_success_typings
Or --show-success-typings
.
{typer, [
{show_succ, true}
]}.
This project was part of Hack Week, the twice-yearly event where employees get to decide what we build. We learn things, try things out, and get to work with different folks than usual. You can read more about Hack Week.