Internal, unstable programmatic API. The supported public interfaces are the Mix task, its configuration, and its JSON findings file.
Compares @spec declarations with the signatures the Elixir compiler
infers for the same functions.
The compiler stores an inferred signature for every function in the
ExCk chunk of the BEAM file. SpecLint translates each spec clause into
the compiler's types (SpecLint.Typespec), applies the inferred
signature to the spec's argument types with the compiler's own rule
(apply_infer/2), and compares the returns:
return_conflict(error): the inferred return is disjoint from the spec return, so no value the function returns satisfies the spec;domain_rejected(error): no inferred clause accepts the spec's arguments, so the compiler would warn on every conforming call;clause_conflict(warning): a clause that accepts only spec-conforming arguments returns a value disjoint from the spec return. A warning, not an error: the compiler keeps clauses that can never match (def f(:b = x) when is_integer(x)), so a stored clause is not proof of reachable behaviour;missing_return(warning): the inferred return has a literal shape the spec does not declare, such as an{:error, _}tuple, an atom or a struct the spec never mentions;unexpected_return(warning): the spec saysno_return()and the compiler infers a concrete return.
Nothing else is reported: inference is deliberately conservative, so an inferred type wider than the spec is normal and silent.
Summary
Types
One reported problem.
An ignore entry: a module, a {module, function} pair, a
{module, function, arity} triple, or a regex matched against
"Module.function/arity".
Functions
Whether finding matches one of the ignore entries.
"Module.function/arity" of a finding.
Analyses every Elixir.*.beam file in the ebins directories.
Types
@type finding() :: %{ severity: :error | :warning, check: atom(), module: module(), function: atom(), arity: arity(), file: String.t() | nil, line: pos_integer() | nil, message: String.t(), spec: [String.t()], inferred: [String.t()] }
One reported problem.
An ignore entry: a module, a {module, function} pair, a
{module, function, arity} triple, or a regex matched against
"Module.function/arity".
Functions
Whether finding matches one of the ignore entries.
"Module.function/arity" of a finding.
@spec run([Path.t()], keyword()) :: %{ findings: [finding()], specs: non_neg_integer(), skipped: [{module(), atom(), arity(), term()}] }
Analyses every Elixir.*.beam file in the ebins directories.
Options: :ignore, a list of ignore/0 entries whose findings are
dropped; :modules, a list of modules to restrict the analysis to.
Returns the findings, the number of spec clauses compared and the spec
clauses skipped because a type could not be translated, with the reason.