Current section
Files
Jump to
Current section
Files
src/pedantic@report.erl
-module(pedantic@report).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pedantic/report.gleam").
-export([dynamic_from/1, default_message/1, make_error/3, new/0, add_error/2, add_warning/2, merge/2, prefix_path/2, path_to_string/1, to_dict/1]).
-export_type([path_segment/0, error_kind/0, error/0, warning_kind/0, warning/0, report/0, type_graph/0, metadata/0, type_field/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type path_segment() :: {field, binary()} | {index, integer()}.
-type error_kind() :: {wrong_type, binary(), binary()} |
missing_field |
{unknown_field, binary()} |
{too_small, integer()} |
{too_large, integer()} |
{too_short, integer()} |
{too_long, integer()} |
{invalid_enum, list(binary())} |
{invalid_format, binary()} |
{custom, binary()}.
-type error() :: {error,
list(path_segment()),
binary(),
error_kind(),
gleam@dynamic:dynamic_()}.
-type warning_kind() :: {discarded_unknown_field, binary()}.
-type warning() :: {warning, list(path_segment()), warning_kind()}.
-type report() :: {report, list(error()), list(warning())}.
-type type_graph() :: primitive_int |
primitive_string |
primitive_bool |
primitive_float |
{list, type_graph()} |
{option, type_graph()} |
{object, binary(), list(type_field())} |
{dict, type_graph()} |
{annotated, type_graph(), metadata()} |
{union, list(type_graph())}.
-type metadata() :: {metadata,
gleam@option:option(binary()),
gleam@option:option(binary()),
gleam@option:option(gleam@dynamic:dynamic_())}.
-type type_field() :: {type_field, binary(), type_graph()}.
-file("src/pedantic/report.gleam", 23).
-spec dynamic_from(any()) -> gleam@dynamic:dynamic_().
dynamic_from(A) ->
gleam_stdlib:identity(A).
-file("src/pedantic/report.gleam", 130).
?DOC(" Returns a human-readable default message for any ErrorKind.\n").
-spec default_message(error_kind()) -> binary().
default_message(Kind) ->
case Kind of
{wrong_type, Expected, Actual} ->
<<<<<<"Expected "/utf8, Expected/binary>>/binary, ", got "/utf8>>/binary,
Actual/binary>>;
missing_field ->
<<"Field is required"/utf8>>;
{unknown_field, Name} ->
<<"Unknown field: "/utf8, Name/binary>>;
{too_small, Limit} ->
<<"Value must be at least "/utf8,
(erlang:integer_to_binary(Limit))/binary>>;
{too_large, Limit@1} ->
<<"Value must be at most "/utf8,
(erlang:integer_to_binary(Limit@1))/binary>>;
{too_short, Limit@2} ->
<<"Length must be at least "/utf8,
(erlang:integer_to_binary(Limit@2))/binary>>;
{too_long, Limit@3} ->
<<"Length must be at most "/utf8,
(erlang:integer_to_binary(Limit@3))/binary>>;
{invalid_enum, Options} ->
<<"Value must be one of: "/utf8,
(gleam@string:join(Options, <<", "/utf8>>))/binary>>;
{invalid_format, Expected@1} ->
<<"Invalid format: expected "/utf8, Expected@1/binary>>;
{custom, Msg} ->
Msg
end.
-file("src/pedantic/report.gleam", 147).
?DOC(" Constructs a ValidationIssue/Error with a default message.\n").
-spec make_error(list(path_segment()), error_kind(), gleam@dynamic:dynamic_()) -> error().
make_error(Path, Kind, Actual) ->
{error, Path, default_message(Kind), Kind, Actual}.
-file("src/pedantic/report.gleam", 156).
?DOC(" Creates a new, empty report.\n").
-spec new() -> report().
new() ->
{report, [], []}.
-file("src/pedantic/report.gleam", 161).
?DOC(" Adds an error to a report.\n").
-spec add_error(report(), error()) -> report().
add_error(Report, Error) ->
{report,
lists:append(erlang:element(2, Report), [Error]),
erlang:element(3, Report)}.
-file("src/pedantic/report.gleam", 166).
?DOC(" Adds a warning to a report.\n").
-spec add_warning(report(), warning()) -> report().
add_warning(Report, Warning) ->
{report,
erlang:element(2, Report),
lists:append(erlang:element(3, Report), [Warning])}.
-file("src/pedantic/report.gleam", 171).
?DOC(" Merges two reports together.\n").
-spec merge(report(), report()) -> report().
merge(A, B) ->
{report,
lists:append(erlang:element(2, A), erlang:element(2, B)),
lists:append(erlang:element(3, A), erlang:element(3, B))}.
-file("src/pedantic/report.gleam", 179).
?DOC(" Prefixes the path of all errors and warnings in a report with a segment.\n").
-spec prefix_path(report(), path_segment()) -> report().
prefix_path(Report, Segment) ->
Errors = gleam@list:map(
erlang:element(2, Report),
fun(E) ->
{error,
[Segment | erlang:element(2, E)],
erlang:element(3, E),
erlang:element(4, E),
erlang:element(5, E)}
end
),
Warnings = gleam@list:map(
erlang:element(3, Report),
fun(W) ->
{warning, [Segment | erlang:element(2, W)], erlang:element(3, W)}
end
),
{report, Errors, Warnings}.
-file("src/pedantic/report.gleam", 188).
?DOC(" Converts a path to a dotted string representation.\n").
-spec path_to_string(list(path_segment())) -> binary().
path_to_string(Path) ->
_pipe = gleam@list:map(Path, fun(Segment) -> case Segment of
{field, Name} ->
Name;
{index, Idx} ->
erlang:integer_to_binary(Idx)
end end),
gleam@string:join(_pipe, <<"."/utf8>>).
-file("src/pedantic/report.gleam", 199).
?DOC(" Converts a report into a dictionary mapping dotted paths to lists of human-readable error messages.\n").
-spec to_dict(report()) -> gleam@dict:dict(binary(), list(binary())).
to_dict(Report) ->
gleam@list:fold(
erlang:element(2, Report),
maps:new(),
fun(Acc, Err) ->
Path_str = path_to_string(erlang:element(2, Err)),
Existing = begin
_pipe = gleam_stdlib:map_get(Acc, Path_str),
gleam@result:unwrap(_pipe, [])
end,
gleam@dict:insert(
Acc,
Path_str,
lists:append(Existing, [erlang:element(3, Err)])
)
end
).