elint 0.1.0

Erlang code linter
Documentation

elint

crates.io CI License Documentation

An Erlang code linter.

Lint rules assume Erlang/OTP 29.0 or later.

Features

  • Lints both .erl and .hrl files.
  • Accepts multiple files or directories and walks directories recursively.
  • Analyzes every arm of every conditional, including arms the current macro state would not select.
  • Embeds the description of every lint rule in the binary and prints it with --explain.
  • Lets you declare intentional findings with -elint_expect, and reports expectations that never matched a finding.

Run elint --list for the available lint rules and shared explanations; elint --explain <name> prints one.

Example

-module(example).

first(Tuple) ->
    element(1, Tuple).
$ elint --lint element_bif example.erl
error[element_bif]: Disallow `element/2` with a literal index; use pattern matching instead.
 --> example.erl:4:5 (in first/1)
  |
  | first(Tuple) ->
4 |     element(1, Tuple).
  |     ^^^^^^^^^^^^^^^^^
  |
note: run `elint --explain element_bif` for details
Found 1 error(s)

The report shows the rule name in brackets, the location (path:line:col, plus the enclosing function), the offending source line, and a caret over the reported span. The note points to elint --explain element_bif for the rule description. elint exits with status 1 because at least one problem was found.

Installation

Pre-built binaries

Pre-built binaries for Linux and macOS are available from the releases page:

  • x86_64-unknown-linux-musl (Linux x86_64, fully static)
  • aarch64-unknown-linux-musl (Linux arm64, fully static)
  • x86_64-apple-darwin (macOS Intel)
  • aarch64-apple-darwin (macOS Apple Silicon)

For example, download the Linux x86_64 binary from the latest release with the GitHub CLI:

$ gh release download --repo sile/elint \
    --pattern "elint-*.x86_64-unknown-linux-musl"
$ chmod +x elint-*.x86_64-unknown-linux-musl
$ ./elint-*.x86_64-unknown-linux-musl --version

The asset name is elint-<version>.<target>, where <target> is one of the triples above and <version> is the release version without the leading v. To download a specific version, pass its tag name (for example v0.1.0) instead of the latest release:

$ gh release download v0.1.0 --repo sile/elint \
    --pattern "elint-0.1.0.x86_64-unknown-linux-musl"

With Cargo

If you have cargo (the Rust package manager) installed:

$ cargo install elint
$ elint --version

See the Rust documentation to install Cargo itself.

Usage

$ elint [OPTIONS] [PATH]..

With no PATH, elint lints src/ and tests/. You can pass multiple files or directories; directories are walked recursively, and .erl / .hrl files are linted.

$ elint
$ elint src
$ elint src tests
$ elint path/to/module.erl

A path that you specify explicitly must exist; elint reports it as an error otherwise.

For the other command-line options, see the help:

$ elint -h
$ elint --help

Selecting lint rules

-l / --lint <RULE> restricts linting to the named rule and may be repeated:

$ elint --lint element_bif src
$ elint --lint element_bif --lint strict_generator src

Run elint --list for the available rule names.

Explanations

--list lists the available lint rules and shared explanations, and --explain <name> prints one:

$ elint --list
$ elint --explain element_bif
$ elint --explain elint_expect_attr

A normal lint finding points to the description of the rule it violates. elint_expect_attr is a shared explanation referenced from rules with legitimate intentional exceptions and from -elint_expect diagnostics. --explain covers rule descriptions and the shared explanations under docs/explain/; it is not a viewer for every file in docs/.

Documentation

  • Preprocessing: how elint preprocesses Erlang source, including conditional-branch exploration and include resolution policy.
  • Diagnostics: how elint reports problems and why -error / -warning directives are ignored.
  • The -elint_expect attribute: the -elint_expect notation and suppression.

docs/diagnostics.md and docs/preprocessing.md are meant to be read on GitHub; they are not --explain targets.

Suppressing intentional findings

When a finding is intentional, declare it with an -elint_expect attribute so elint suppresses it and reports an expectation that never matched:

$ elint --explain elint_expect_attr

See the -elint_expect attribute for the notation.

Diagnostics and exit status

Findings and analysis errors are written to stderr. elint exits with status 1 when at least one problem is reported, and status 0 when there are none. See docs/diagnostics.md for the output format.