Current section
Files
Jump to
Current section
Files
src/examples@error_messages.erl
-module(examples@error_messages).
-compile([no_auto_import, nowarn_unused_vars]).
-export([main/0]).
-export_type([span/0, error/0]).
-type span() :: {span, integer(), integer(), integer()}.
-type error() :: {error, binary(), binary(), binary(), span()}.
-spec header_doc(binary(), binary()) -> glam@doc:document().
header_doc(Code, Name) ->
_pipe = [<<"["/utf8>>, Code, <<"]:"/utf8>>, Name],
_pipe@1 = gleam@string:join(_pipe, <<" "/utf8>>),
glam@doc:from_string(_pipe@1).
-spec line_prefix(integer()) -> binary().
line_prefix(Line_number) ->
<<(gleam@int:to_string(Line_number + 1))/binary, " | "/utf8>>.
-spec line_doc(binary(), integer()) -> {glam@doc:document(), integer()}.
line_doc(Source_code, Line_number) ->
Source_code_lines = gleam@string:split(Source_code, <<"\n"/utf8>>),
_assert_subject = gleam@list:at(Source_code_lines, Line_number),
{ok, Line} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"examples/error_messages"/utf8>>,
function => <<"line_doc"/utf8>>,
line => 84})
end,
Prefix = line_prefix(Line_number),
Prefix_size = gleam@string:length(Prefix),
{glam@doc:from_string(<<Prefix/binary, Line/binary>>), Prefix_size}.
-spec underlined_pointer(integer()) -> glam@doc:document().
underlined_pointer(Length) ->
_pipe = [glam@doc:from_string(
<<"┬"/utf8,
(gleam@string:repeat(<<"─"/utf8>>, Length - 1))/binary>>
),
{line, 1},
glam@doc:from_string(<<"╰─ "/utf8>>)],
glam@doc:concat(_pipe).
-spec flexible_text(binary()) -> glam@doc:document().
flexible_text(Text) ->
To_flexible_line = fun(Line) ->
_pipe = gleam@string:split(Line, <<" "/utf8>>),
_pipe@1 = gleam@list:map(_pipe, fun glam@doc:from_string/1),
_pipe@2 = glam@doc:join(
_pipe@1,
{flex_break, <<" "/utf8>>, <<""/utf8>>}
),
glam@doc:group(_pipe@2)
end,
_pipe@3 = gleam@string:split(Text, <<"\n"/utf8>>),
_pipe@4 = gleam@list:map(_pipe@3, To_flexible_line),
_pipe@5 = glam@doc:join(_pipe@4, {line, 1}),
glam@doc:group(_pipe@5).
-spec message_doc(binary(), integer()) -> glam@doc:document().
message_doc(Message, Length) ->
_pipe@1 = [underlined_pointer(Length),
begin
_pipe = flexible_text(Message),
glam@doc:nest(_pipe, 3)
end],
glam@doc:concat(_pipe@1).
-spec error_to_doc(binary(), error()) -> glam@doc:document().
error_to_doc(Source_code, Error) ->
Underline_size = (erlang:element(4, erlang:element(5, Error)) - erlang:element(
3,
erlang:element(5, Error)
))
+ 1,
{Line_doc, Prefix_size} = line_doc(
Source_code,
erlang:element(2, erlang:element(5, Error))
),
_pipe@2 = [header_doc(erlang:element(2, Error), erlang:element(3, Error)),
{line, 1},
Line_doc,
begin
_pipe = [{line, 1},
message_doc(erlang:element(4, Error), Underline_size)],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:nest(
_pipe@1,
erlang:element(3, erlang:element(5, Error)) + Prefix_size
)
end],
glam@doc:concat(_pipe@2).
-spec errors_to_doc(binary(), list(error())) -> glam@doc:document().
errors_to_doc(Source_code, Errors) ->
_pipe = gleam@list:map(
Errors,
fun(_capture) -> error_to_doc(Source_code, _capture) end
),
glam@doc:join(_pipe, glam@doc:lines(2)).
-spec main() -> nil.
main() ->
Source_code = <<"fn greet(message: String) -> Nil {\n println(\"Hello\" <> message)\n}"/utf8>>,
Errors = [{error,
<<"E001"/utf8>>,
<<"Unused function"/utf8>>,
<<"This function is unused!\nYou can safely remove it or make it public with the `pub` keyword."/utf8>>,
{span, 0, 3, 7}},
{error,
<<"E011"/utf8>>,
<<"Unknown variable"/utf8>>,
<<"The name `println` is not in scope here.\nDid you mean to use `io.println`?"/utf8>>,
{span, 1, 2, 8}}],
_pipe = errors_to_doc(Source_code, Errors),
_pipe@1 = glam@doc:to_string(_pipe, 30),
gleam@io:println(_pipe@1).