defmodule TypeCheck.TypeError.Formatter do
@moduledoc """
Behaviour to format your own type errors
"""
@typedoc """
A `problem tuple` contains four fields:
1. the module of the type for which a check did not pass
2. an atom describing the exact error;
for many types there are multiple checks
3. a map with fields containing extra information about the error.
in the cases of a compound type, this often contains information
about the deeper problem that happened as well.
4. the datastructure that did not pass the check
See the module documentation of all `TypeCheck.Builtin.*` modules
for more information about the checks that they perform and the problem tuples they might return.
"""
# @type problem_tuple :: {module(), atom(), map(), any()}
# use TypeCheck
# type problem_tuple :: {module, atom, map, any}
use TypeCheck
# Note that `Lazy` is missing here.
# This is because `lazy` does not have its own problem tuple,
# rather it will always return the problem tuple of the contained type.
@type! problem_tuple ::
TypeCheck.Builtin.Any.problem_tuple()
| TypeCheck.Builtin.Atom.problem_tuple()
| TypeCheck.Builtin.Binary.problem_tuple()
| TypeCheck.Builtin.Bitstring.problem_tuple()
| TypeCheck.Builtin.Boolean.problem_tuple()
| TypeCheck.Builtin.FixedList.problem_tuple()
| TypeCheck.Builtin.FixedMap.problem_tuple()
| TypeCheck.Builtin.CompoundFixedMap.problem_tuple()
| TypeCheck.Builtin.FixedTuple.problem_tuple()
| TypeCheck.Builtin.Float.problem_tuple()
| TypeCheck.Builtin.Integer.problem_tuple()
| TypeCheck.Builtin.List.problem_tuple()
| TypeCheck.Builtin.MaybeImproperList.problem_tuple()
| TypeCheck.Builtin.Literal.problem_tuple()
| TypeCheck.Builtin.Map.problem_tuple()
| TypeCheck.Builtin.NamedType.problem_tuple()
| TypeCheck.Builtin.NegInteger.problem_tuple()
| TypeCheck.Builtin.NonNegInteger.problem_tuple()
| TypeCheck.Builtin.None.problem_tuple()
| TypeCheck.Builtin.Number.problem_tuple()
| TypeCheck.Builtin.OneOf.problem_tuple()
| TypeCheck.Builtin.PosInteger.problem_tuple()
| TypeCheck.Builtin.PID.problem_tuple()
| TypeCheck.Builtin.Port.problem_tuple()
| TypeCheck.Builtin.Reference.problem_tuple()
| TypeCheck.Builtin.Range.problem_tuple()
| TypeCheck.Builtin.Tuple.problem_tuple()
| TypeCheck.Spec.problem_tuple()
@doc """
A formatter is expected to turn a `problem_tuple` into a string
that can be used as `:message` of the TypeCheck.TypeError exception.
"""
@callback format(problem_tuple, TypeCheck.TypeError.location()) :: String.t()
end