Current section

Files

Jump to
caffeine_lang src caffeine_lang@frontend@formatter.erl
Raw

src/caffeine_lang@frontend@formatter.erl

-module(caffeine_lang@frontend@formatter).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/frontend/formatter.gleam").
-export([format/1]).
-export_type([field_context/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 field_context() :: type_fields | literal_fields.
-file("src/caffeine_lang/frontend/formatter.gleam", 124).
-spec format_comments(list(caffeine_lang@frontend@ast:comment()), binary()) -> binary().
format_comments(Comments, Indent) ->
case Comments of
[] ->
<<""/utf8>>;
_ ->
_pipe = Comments,
_pipe@1 = gleam@list:map(_pipe, fun(C) -> case C of
{line_comment, Text} ->
<<<<<<Indent/binary, "#"/utf8>>/binary,
Text/binary>>/binary,
"\n"/utf8>>;
{section_comment, Text@1} ->
<<<<<<Indent/binary, "##"/utf8>>/binary,
Text@1/binary>>/binary,
"\n"/utf8>>;
{doc_comment, Text@2} ->
<<<<<<Indent/binary, "###"/utf8>>/binary,
Text@2/binary>>/binary,
"\n"/utf8>>
end end),
erlang:list_to_binary(_pipe@1)
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 346).
-spec needs_string_quoting(caffeine_lang@types:parsed_type()) -> boolean().
needs_string_quoting(T) ->
case T of
{parsed_primitive, string} ->
true;
{parsed_primitive, {semantic_type, _}} ->
true;
{parsed_refinement, {one_of, Inner, _}} ->
needs_string_quoting(Inner);
{parsed_refinement, {inclusive_range, Inner@1, _, _}} ->
needs_string_quoting(Inner@1);
{parsed_record, _} ->
false;
_ ->
false
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 358).
?DOC(" A default value needs quoting if it isn't a number, boolean, or percentage literal.\n").
-spec value_needs_quoting(binary()) -> boolean().
value_needs_quoting(Val) ->
case Val of
<<"true"/utf8>> ->
false;
<<"false"/utf8>> ->
false;
_ ->
Cleaned = case gleam_stdlib:string_ends_with(Val, <<"%"/utf8>>) of
true ->
gleam@string:drop_end(Val, 1);
false ->
Val
end,
case gleam_stdlib:parse_int(Cleaned) of
{ok, _} ->
false;
{error, _} ->
case gleam_stdlib:parse_float(Cleaned) of
{ok, _} ->
false;
{error, _} ->
true
end
end
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 335).
-spec quote_if_string_type(caffeine_lang@types:parsed_type(), binary()) -> binary().
quote_if_string_type(Inner, Val) ->
Quote = case Inner of
{parsed_type_alias_ref, _} ->
value_needs_quoting(Val);
_ ->
needs_string_quoting(Inner)
end,
gleam@bool:guard(
Quote,
<<<<"\""/utf8, Val/binary>>/binary, "\""/utf8>>,
fun() -> Val end
).
-file("src/caffeine_lang/frontend/formatter.gleam", 289).
-spec format_primitive_type(caffeine_lang@types:primitive_types()) -> binary().
format_primitive_type(P) ->
case P of
boolean ->
<<"Boolean"/utf8>>;
string ->
<<"String"/utf8>>;
{numeric_type, N} ->
case N of
integer ->
<<"Integer"/utf8>>;
float ->
<<"Float"/utf8>>;
percentage ->
<<"Percentage"/utf8>>
end;
{semantic_type, S} ->
case S of
u_r_l ->
<<"URL"/utf8>>
end
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 314).
-spec format_record_type(
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> binary().
format_record_type(Fields) ->
Field_strs = begin
_pipe = Fields,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:map(
_pipe@2,
fun(Pair) ->
<<<<(erlang:element(1, Pair))/binary, ": "/utf8>>/binary,
(format_type(erlang:element(2, Pair)))/binary>>
end
)
end,
<<<<"{ "/utf8, (gleam@string:join(Field_strs, <<", "/utf8>>))/binary>>/binary,
" }"/utf8>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 379).
-spec format_refinement_type(
caffeine_lang@types:refinement_types(caffeine_lang@types:parsed_type())
) -> binary().
format_refinement_type(R) ->
case R of
{one_of, Inner, Values} ->
Quote = needs_string_quoting(Inner),
Sorted_vals = begin
_pipe = Values,
_pipe@1 = gleam@set:to_list(_pipe),
_pipe@2 = gleam@list:sort(_pipe@1, fun gleam@string:compare/2),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(V) ->
gleam@bool:guard(
Quote,
<<<<"\""/utf8, V/binary>>/binary, "\""/utf8>>,
fun() -> V end
)
end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end,
<<<<<<(format_type(Inner))/binary, " { x | x in { "/utf8>>/binary,
Sorted_vals/binary>>/binary,
" } }"/utf8>>;
{inclusive_range, Inner@1, Low, High} ->
<<<<<<<<<<(format_type(Inner@1))/binary, " { x | x in ( "/utf8>>/binary,
Low/binary>>/binary,
".."/utf8>>/binary,
High/binary>>/binary,
" ) }"/utf8>>
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 323).
-spec format_modifier_type(
caffeine_lang@types:modifier_types(caffeine_lang@types:parsed_type())
) -> binary().
format_modifier_type(M) ->
case M of
{optional, Inner} ->
<<<<"Optional("/utf8, (format_type(Inner))/binary>>/binary,
")"/utf8>>;
{defaulted, Inner@1, Default_val} ->
<<<<<<<<"Defaulted("/utf8, (format_type(Inner@1))/binary>>/binary,
", "/utf8>>/binary,
(quote_if_string_type(Inner@1, Default_val))/binary>>/binary,
")"/utf8>>
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 306).
-spec format_collection_type(
caffeine_lang@types:collection_types(caffeine_lang@types:parsed_type())
) -> binary().
format_collection_type(C) ->
case C of
{list, Inner} ->
<<<<"List("/utf8, (format_type(Inner))/binary>>/binary, ")"/utf8>>;
{dict, Key, Value} ->
<<<<<<<<"Dict("/utf8, (format_type(Key))/binary>>/binary,
", "/utf8>>/binary,
(format_type(Value))/binary>>/binary,
")"/utf8>>
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 278).
-spec format_type(caffeine_lang@types:parsed_type()) -> binary().
format_type(T) ->
case T of
{parsed_primitive, P} ->
format_primitive_type(P);
{parsed_collection, C} ->
format_collection_type(C);
{parsed_modifier, M} ->
format_modifier_type(M);
{parsed_refinement, R} ->
format_refinement_type(R);
{parsed_type_alias_ref, Name} ->
Name;
{parsed_record, Fields} ->
format_record_type(Fields)
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 417).
-spec format_literal_list(
list(caffeine_lang@frontend@ast:literal()),
integer(),
field_context()
) -> binary().
format_literal_list(Elements, Indent, Context) ->
Element_strs = begin
_pipe = Elements,
gleam@list:map(_pipe, fun(E) -> format_literal(E, Indent, Context) end)
end,
<<<<"["/utf8, (gleam@string:join(Element_strs, <<", "/utf8>>))/binary>>/binary,
"]"/utf8>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 399).
-spec format_literal(
caffeine_lang@frontend@ast:literal(),
integer(),
field_context()
) -> binary().
format_literal(L, Indent, Context) ->
case L of
{literal_string, S} ->
<<<<"\""/utf8, S/binary>>/binary, "\""/utf8>>;
{literal_integer, I} ->
erlang:integer_to_binary(I);
{literal_float, F} ->
gleam_stdlib:float_to_string(F);
{literal_percentage, F@1} ->
<<(gleam_stdlib:float_to_string(F@1))/binary, "%"/utf8>>;
literal_true ->
<<"true"/utf8>>;
literal_false ->
<<"false"/utf8>>;
{literal_list, Elements} ->
format_literal_list(Elements, Indent, Context);
{literal_struct, Fields, Trailing_comments} ->
format_struct({struct, Fields, Trailing_comments}, Indent, Context)
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 271).
-spec format_field(
caffeine_lang@frontend@ast:field(),
integer(),
field_context()
) -> binary().
format_field(F, Indent, Context) ->
case erlang:element(3, F) of
{type_value, T} ->
<<<<(erlang:element(2, F))/binary, ": "/utf8>>/binary,
(format_type(T))/binary>>;
{literal_value, L} ->
<<<<(erlang:element(2, F))/binary, ": "/utf8>>/binary,
(format_literal(L, Indent, Context))/binary>>
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 248).
-spec format_struct_multiline(
caffeine_lang@frontend@ast:struct(),
integer(),
field_context()
) -> binary().
format_struct_multiline(S, Indent, Context) ->
Indent_str = gleam@string:repeat(<<" "/utf8>>, Indent),
Field_lines = begin
_pipe = erlang:element(2, S),
gleam@list:map(
_pipe,
fun(F) ->
Comments = format_comments(erlang:element(4, F), Indent_str),
<<<<Comments/binary, Indent_str/binary>>/binary,
(format_field(F, Indent, Context))/binary>>
end
)
end,
Trailing = format_comments(erlang:element(3, S), Indent_str),
<<<<<<<<<<"{\n"/utf8,
(gleam@string:join(Field_lines, <<",\n"/utf8>>))/binary>>/binary,
"\n"/utf8>>/binary,
Trailing/binary>>/binary,
(gleam@string:repeat(<<" "/utf8>>, Indent - 2))/binary>>/binary,
"}"/utf8>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 241).
-spec format_struct_inline(
list(caffeine_lang@frontend@ast:field()),
field_context()
) -> binary().
format_struct_inline(Fields, Context) ->
Field_strs = begin
_pipe = Fields,
gleam@list:map(_pipe, fun(F) -> format_field(F, 0, Context) end)
end,
<<<<"{ "/utf8, (gleam@string:join(Field_strs, <<", "/utf8>>))/binary>>/binary,
" }"/utf8>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 208).
-spec format_struct(
caffeine_lang@frontend@ast:struct(),
integer(),
field_context()
) -> binary().
format_struct(S, Indent, Context) ->
Has_field_comments = gleam@list:any(
erlang:element(2, S),
fun(F) -> erlang:element(4, F) /= [] end
),
Has_trailing_comments = erlang:element(3, S) /= [],
Has_any_comments = Has_field_comments orelse Has_trailing_comments,
case erlang:element(2, S) of
[] ->
case Has_trailing_comments of
true ->
<<<<<<"{\n"/utf8,
(format_comments(
erlang:element(3, S),
gleam@string:repeat(
<<" "/utf8>>,
Indent + 2
)
))/binary>>/binary,
(gleam@string:repeat(<<" "/utf8>>, Indent))/binary>>/binary,
"}"/utf8>>;
false ->
<<"{ }"/utf8>>
end;
Fields ->
gleam@bool:guard(
Has_any_comments,
format_struct_multiline(S, Indent + 2, Context),
fun() ->
Inline = format_struct_inline(Fields, Context),
Prefix_len = Indent + 10,
gleam@bool:guard(
(string:length(Inline) + Prefix_len) < 80,
Inline,
fun() ->
format_struct_multiline(S, Indent + 2, Context)
end
)
end
)
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 201).
-spec format_extends(list(binary())) -> binary().
format_extends(Extends) ->
case Extends of
[] ->
<<""/utf8>>;
Names ->
<<<<" extends ["/utf8,
(gleam@string:join(Names, <<", "/utf8>>))/binary>>/binary,
"]"/utf8>>
end.
-file("src/caffeine_lang/frontend/formatter.gleam", 179).
-spec format_measurement_item(caffeine_lang@frontend@ast:measurement_item()) -> binary().
format_measurement_item(Item) ->
Comments = format_comments(erlang:element(6, Item), <<""/utf8>>),
Name_line = <<<<<<<<"\""/utf8, (erlang:element(2, Item))/binary>>/binary,
"\""/utf8>>/binary,
(format_extends(erlang:element(3, Item)))/binary>>/binary,
":"/utf8>>,
Requires = <<" Requires "/utf8,
(format_struct(erlang:element(4, Item), 2, type_fields))/binary>>,
Provides = <<" Provides "/utf8,
(format_struct(erlang:element(5, Item), 2, literal_fields))/binary>>,
<<<<<<<<<<Comments/binary, Name_line/binary>>/binary, "\n"/utf8>>/binary,
Requires/binary>>/binary,
"\n"/utf8>>/binary,
Provides/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 147).
-spec format_extendable(caffeine_lang@frontend@ast:extendable()) -> binary().
format_extendable(Ext) ->
Kind_str = case erlang:element(3, Ext) of
extendable_requires ->
<<"Requires"/utf8>>;
extendable_provides ->
<<"Provides"/utf8>>
end,
Context = case erlang:element(3, Ext) of
extendable_requires ->
type_fields;
extendable_provides ->
literal_fields
end,
<<<<<<<<<<(format_comments(erlang:element(5, Ext), <<""/utf8>>))/binary,
(erlang:element(2, Ext))/binary>>/binary,
" ("/utf8>>/binary,
Kind_str/binary>>/binary,
"): "/utf8>>/binary,
(format_struct(erlang:element(4, Ext), 0, Context))/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 140).
-spec format_type_alias(caffeine_lang@frontend@ast:type_alias()) -> binary().
format_type_alias(Alias) ->
<<<<<<(format_comments(erlang:element(4, Alias), <<""/utf8>>))/binary,
(erlang:element(2, Alias))/binary>>/binary,
" (Type): "/utf8>>/binary,
(format_type(erlang:element(3, Alias)))/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 71).
-spec format_measurements_file(
caffeine_lang@frontend@ast:measurements_file(caffeine_lang@frontend@ast:parsed())
) -> binary().
format_measurements_file(File) ->
Sections = [],
Sections@1 = case erlang:element(2, File) of
[] ->
Sections;
Aliases ->
lists:append(
Sections,
[begin
_pipe = gleam@list:map(Aliases, fun format_type_alias/1),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end]
)
end,
Sections@2 = case erlang:element(3, File) of
[] ->
Sections@1;
Extendables ->
lists:append(
Sections@1,
[begin
_pipe@1 = gleam@list:map(
Extendables,
fun format_extendable/1
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end]
)
end,
Sections@3 = case erlang:element(4, File) of
[] ->
Sections@2;
Items ->
lists:append(
Sections@2,
[begin
_pipe@2 = gleam@list:map(
Items,
fun format_measurement_item/1
),
gleam@string:join(_pipe@2, <<"\n\n"/utf8>>)
end]
)
end,
Trailing = format_comments(erlang:element(5, File), <<""/utf8>>),
<<<<(gleam@string:join(Sections@3, <<"\n\n"/utf8>>))/binary, "\n"/utf8>>/binary,
Trailing/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 190).
-spec format_expect_item(caffeine_lang@frontend@ast:expect_item()) -> binary().
format_expect_item(Item) ->
Comments = format_comments(erlang:element(5, Item), <<" "/utf8>>),
Name_line = <<<<<<<<" * \""/utf8, (erlang:element(2, Item))/binary>>/binary,
"\""/utf8>>/binary,
(format_extends(erlang:element(3, Item)))/binary>>/binary,
":"/utf8>>,
Provides = <<" Provides "/utf8,
(format_struct(erlang:element(4, Item), 4, literal_fields))/binary>>,
<<<<<<Comments/binary, Name_line/binary>>/binary, "\n"/utf8>>/binary,
Provides/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 164).
-spec format_expects_block(caffeine_lang@frontend@ast:expects_block()) -> binary().
format_expects_block(Block) ->
Comments = format_comments(erlang:element(4, Block), <<""/utf8>>),
Header = case erlang:element(2, Block) of
{some, Name} ->
<<<<"Expectations measured by \""/utf8, Name/binary>>/binary,
"\""/utf8>>;
none ->
<<"Unmeasured Expectations"/utf8>>
end,
Items = begin
_pipe = erlang:element(3, Block),
_pipe@1 = gleam@list:map(_pipe, fun format_expect_item/1),
gleam@string:join(_pipe@1, <<"\n\n"/utf8>>)
end,
<<<<<<Comments/binary, Header/binary>>/binary, "\n"/utf8>>/binary,
Items/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 103).
-spec format_expects_file(
caffeine_lang@frontend@ast:expects_file(caffeine_lang@frontend@ast:parsed())
) -> binary().
format_expects_file(File) ->
Sections = [],
Sections@1 = case erlang:element(2, File) of
[] ->
Sections;
Extendables ->
lists:append(
Sections,
[begin
_pipe = gleam@list:map(
Extendables,
fun format_extendable/1
),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end]
)
end,
Sections@2 = case erlang:element(3, File) of
[] ->
Sections@1;
Blocks ->
lists:append(
Sections@1,
gleam@list:map(Blocks, fun format_expects_block/1)
)
end,
Trailing = format_comments(erlang:element(4, File), <<""/utf8>>),
<<<<(gleam@string:join(Sections@2, <<"\n\n"/utf8>>))/binary, "\n"/utf8>>/binary,
Trailing/binary>>.
-file("src/caffeine_lang/frontend/formatter.gleam", 39).
?DOC(
" Format a Caffeine source file. Auto-detects whether it's a measurements or expectations file.\n"
" Expectations files are detected by the presence of the Expectations keyword;\n"
" all other files are treated as measurements files.\n"
).
-spec format(binary()) -> {ok, binary()} | {error, binary()}.
format(Source) ->
gleam@result:'try'(
begin
_pipe = caffeine_lang@frontend@tokenizer:tokenize(Source),
gleam@result:map_error(
_pipe,
fun(_) -> <<"Tokenization error"/utf8>> end
)
end,
fun(Tokens) ->
Has_expectations = gleam@list:any(Tokens, fun(Ptok) -> case Ptok of
{positioned_token, keyword_expectations, _, _} ->
true;
_ ->
false
end end),
case Has_expectations of
true ->
gleam@result:'try'(
begin
_pipe@1 = caffeine_lang@frontend@parser:parse_expects_file(
Source
),
gleam@result:map_error(
_pipe@1,
fun(Err) ->
<<"Parse error: "/utf8,
(gleam@string:inspect(Err))/binary>>
end
)
end,
fun(Parsed) -> {ok, format_expects_file(Parsed)} end
);
false ->
gleam@result:'try'(
begin
_pipe@2 = caffeine_lang@frontend@parser:parse_measurements_file(
Source
),
gleam@result:map_error(
_pipe@2,
fun(Err@1) ->
<<"Parse error: "/utf8,
(gleam@string:inspect(Err@1))/binary>>
end
)
end,
fun(Parsed@1) ->
{ok, format_measurements_file(Parsed@1)}
end
)
end
end
).