Interested in working with us? We are hiring!

See open positions

Introducing Rebar3 TypEr

Mackenzie Morgan Written by Mackenzie Morgan, April 27, 2022
a typewriter
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:

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:

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.