Current section

Files

Jump to
glacier src glacier.erl
Raw

src/glacier.erl

-module(glacier).
-compile(no_auto_import).
-export([main/0]).
-export_type([target/0, module_kind/0, parse_mode/0]).
-type target() :: erlang_target | java_script_target.
-type module_kind() :: src_module_kind | test_module_kind.
-type parse_mode() :: parse_mode_in_comment |
parse_mode_in_string |
parse_mode_search.
-spec main() -> nil.
main() ->
Start_args = start_args(),
Is_incremental = gleam@list:contains(Start_args, <<"--glacier"/utf8>>),
Is_empty_args = Start_args =:= [],
case {Is_empty_args, Is_incremental} of
{true, _@1} ->
gleeunit2:main();
{_@2, true} ->
_pipe = <<"🏔 Glacier is watching for changes…"/utf8>>,
_pipe@2 = shellout:style(
_pipe,
begin
_pipe@1 = shellout:display([<<"italic"/utf8>>]),
gleam@map:merge(
_pipe@1,
shellout:color([<<"lightblue"/utf8>>])
)
end,
[{[<<"color"/utf8>>, <<"background"/utf8>>],
[{<<"lightblue"/utf8>>,
[<<"156"/utf8>>, <<"231"/utf8>>, <<"255"/utf8>>]}]}]
),
gleam@io:println(_pipe@2),
start_file_change_watcher(
fun(Modules) -> execute_tests(Modules) end
);
{_@3, _@4} ->
gleeunit2:run(Start_args)
end.
-spec execute_tests(list({module_kind(), binary()})) -> nil.
execute_tests(Modules) ->
Test_modules@1 = begin
_pipe@2 = gleam@list:fold(
Modules,
[],
fun(Test_modules_acc, Module) ->
Module_kind = erlang:element(1, Module),
Full_module_path = erlang:element(2, Module),
Test_modules = case Module_kind of
src_module_kind ->
_pipe = detect_distinct_import_module_dependency_chain(
[file_name_to_module_name(
Full_module_path,
src_module_kind
)],
[]
),
_pipe@1 = derive_test_modules_from_src_import_dependencies(
_pipe
),
gleam@list:map(
_pipe@1,
fun(Test_module) ->
<<<<"test/"/utf8, Test_module/binary>>/binary,
".gleam"/utf8>>
end
);
test_module_kind ->
[to_relative_path(Full_module_path)]
end,
gleam@list:append(Test_modules_acc, Test_modules)
end
),
gleam@list:unique(_pipe@2)
end,
case Test_modules@1 of
[] ->
_pipe@3 = <<"🏔 Did not detect any matching test modules!"/utf8>>,
_pipe@5 = shellout:style(
_pipe@3,
begin
_pipe@4 = shellout:display([<<"bold"/utf8>>]),
gleam@map:merge(
_pipe@4,
shellout:color([<<"lightblue"/utf8>>])
)
end,
[{[<<"color"/utf8>>, <<"background"/utf8>>],
[{<<"lightblue"/utf8>>,
[<<"156"/utf8>>, <<"231"/utf8>>, <<"255"/utf8>>]}]}]
),
gleam@io:println(_pipe@5),
nil;
Test_modules@2 ->
_pipe@6 = <<"🏔 Detected test modules:"/utf8>>,
_pipe@8 = shellout:style(
_pipe@6,
begin
_pipe@7 = shellout:display([<<"bold"/utf8>>]),
gleam@map:merge(
_pipe@7,
shellout:color([<<"lightblue"/utf8>>])
)
end,
[{[<<"color"/utf8>>, <<"background"/utf8>>],
[{<<"lightblue"/utf8>>,
[<<"156"/utf8>>, <<"231"/utf8>>, <<"255"/utf8>>]}]}]
),
gleam@io:println(_pipe@8),
_pipe@9 = gleam@list:map(
Test_modules@2,
fun(Test_module@1) ->
<<" ❄ "/utf8, Test_module@1/binary>>
end
),
_pipe@10 = gleam@string:join(_pipe@9, <<"\n"/utf8>>),
_pipe@11 = shellout:style(
_pipe@10,
shellout:color([<<"lightblue"/utf8>>]),
[{[<<"color"/utf8>>, <<"background"/utf8>>],
[{<<"lightblue"/utf8>>,
[<<"156"/utf8>>, <<"231"/utf8>>, <<"255"/utf8>>]}]}]
),
gleam@io:println(_pipe@11),
Args = [<<"test"/utf8>>, <<"--target"/utf8>>, case target() of
erlang_target ->
<<"erlang"/utf8>>;
java_script_target ->
<<"javascript"/utf8>>
end, <<"--"/utf8>> | Test_modules@2],
case shellout:command(
<<"gleam"/utf8>>,
Args,
<<"."/utf8>>,
[let_be_stderr]
) of
{ok, Msg} ->
gleam@io:print(Msg),
nil;
{error, _@1} ->
nil
end
end.
-spec start_file_change_watcher(fun((list({module_kind(), binary()})) -> nil)) -> nil.
start_file_change_watcher(File_change_handler) ->
glacier_ffi:start_file_change_watcher(File_change_handler),
nil.
-spec detect_distinct_import_module_dependency_chain(
list(binary()),
list(binary())
) -> list(binary()).
detect_distinct_import_module_dependency_chain(
Module_names,
Processed_module_names
) ->
case Module_names of
[] ->
Processed_module_names;
[Module_name | Rest_module_names] ->
case gleam@list:contains(Processed_module_names, Module_name) of
true ->
detect_distinct_import_module_dependency_chain(
Rest_module_names,
Processed_module_names
);
false ->
Unchecked_module_names = begin
_pipe = Module_name,
_pipe@1 = module_name_to_file_name(
_pipe,
src_module_kind
),
_pipe@2 = parse_module_for_imports(_pipe@1),
_pipe@3 = gleam@list:append(_pipe@2, Module_names),
gleam@list:filter(
_pipe@3,
fun(Module_name@1) ->
(gleam@list:contains(
Processed_module_names,
Module_name@1
)
=:= false)
andalso file_exists(
module_name_to_file_name(
Module_name@1,
src_module_kind
)
)
end
)
end,
detect_distinct_import_module_dependency_chain(
gleam@list:append(
Rest_module_names,
Unchecked_module_names
),
gleam@list:append(Processed_module_names, [Module_name])
)
end
end.
-spec parse_module_for_imports(binary()) -> list(binary()).
parse_module_for_imports(Module_file_name) ->
_pipe = Module_file_name,
_pipe@1 = read_module_file(_pipe),
(fun(Result) -> case Result of
{ok, Text} ->
_pipe@2 = Text,
_pipe@3 = gleam@string:to_graphemes(_pipe@2),
_pipe@4 = parse_module_string(
_pipe@3,
[],
parse_mode_search,
<<""/utf8>>
),
gleam@list:unique(_pipe@4);
{error, nil} ->
[]
end end)(_pipe@1).
-spec parse_module_string(
list(binary()),
list(binary()),
parse_mode(),
binary()
) -> list(binary()).
parse_module_string(Chars, Imports, Context, Collected) ->
case Chars of
[] ->
Imports;
[Char | Rest_chars] ->
case {Context, Collected, Char} of
{parse_mode_search, <<""/utf8>>, <<"/"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<"/"/utf8>>
);
{parse_mode_search, <<"/"/utf8>>, <<"/"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_comment,
<<""/utf8>>
);
{parse_mode_search, _@1, <<"\""/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_string,
<<""/utf8>>
);
{parse_mode_search, Collected@1, Char@1} when ((((((Collected@1 =:= <<""/utf8>>) andalso (Char@1 =:= <<"i"/utf8>>)) orelse ((Collected@1 =:= <<"i"/utf8>>) andalso (Char@1 =:= <<"m"/utf8>>))) orelse ((Collected@1 =:= <<"im"/utf8>>) andalso (Char@1 =:= <<"p"/utf8>>))) orelse ((Collected@1 =:= <<"imp"/utf8>>) andalso (Char@1 =:= <<"o"/utf8>>))) orelse ((Collected@1 =:= <<"impo"/utf8>>) andalso (Char@1 =:= <<"r"/utf8>>))) orelse ((Collected@1 =:= <<"impor"/utf8>>) andalso (Char@1 =:= <<"t"/utf8>>)) ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<Collected@1/binary, Char@1/binary>>
);
{parse_mode_search, <<"import"/utf8>>, Char@2} when (((Char@2 =:= <<" "/utf8>>) orelse (Char@2 =:= <<"\t"/utf8>>)) orelse (Char@2 =:= <<"\n"/utf8>>)) orelse (Char@2 =:= <<"\r\n"/utf8>>) ->
{Rest_chars@1, New_import} = parse_import_chars(
Rest_chars,
gleam@string_builder:new()
),
New_import@1 = gleam@string_builder:to_string(New_import),
Updated_imports = [New_import@1 | Imports],
parse_module_string(
Rest_chars@1,
Updated_imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_search, <<"import\r"/utf8>>, <<"\n"/utf8>>} ->
{Rest_chars@2, New_import@2} = parse_import_chars(
Rest_chars,
gleam@string_builder:new()
),
Imports@1 = [gleam@string_builder:to_string(New_import@2) |
Imports],
parse_module_string(
Rest_chars@2,
Imports@1,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_search, _@2, _@3} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_in_comment, _@4, <<"\n"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_in_comment, _@5, <<"\r"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_in_comment, _@6, <<"\r\n"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_in_comment, _@7, _@8} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_comment,
<<""/utf8>>
);
{parse_mode_in_string, <<"\\"/utf8>>, _@9} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_string,
<<""/utf8>>
);
{parse_mode_in_string, _@10, <<"\""/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_search,
<<""/utf8>>
);
{parse_mode_in_string, _@11, <<"\\"/utf8>>} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_string,
<<"\\"/utf8>>
);
{parse_mode_in_string, _@12, _@13} ->
parse_module_string(
Rest_chars,
Imports,
parse_mode_in_string,
<<""/utf8>>
)
end
end.
-spec parse_import_chars(list(binary()), gleam@string_builder:string_builder()) -> {list(binary()),
gleam@string_builder:string_builder()}.
parse_import_chars(Chars, Import_module) ->
case Chars of
[] ->
{[], Import_module};
[<<"."/utf8>> | Rest_chars] ->
{Rest_chars, Import_module};
[<<" "/utf8>> | Rest_chars@1] ->
{Rest_chars@1, Import_module};
[<<"\r\n"/utf8>> | Rest_chars@2] ->
{Rest_chars@2, Import_module};
[<<"\n"/utf8>> | Rest_chars@3] ->
{Rest_chars@3, Import_module};
[Char | Rest_chars@4] when (((Char =:= <<"\t"/utf8>>) orelse (Char =:= <<"\r"/utf8>>)) orelse (Char =:= <<"\n"/utf8>>)) orelse (Char =:= <<"\r\n"/utf8>>) ->
parse_import_chars(Rest_chars@4, Import_module);
[Char@1 | Rest_chars@5] ->
parse_import_chars(
Rest_chars@5,
gleam@string_builder:append(Import_module, Char@1)
)
end.
-spec derive_test_modules_from_src_import_dependencies(list(binary())) -> list(binary()).
derive_test_modules_from_src_import_dependencies(Src_modules) ->
Project_test_files = find_project_files(<<"test"/utf8>>),
All_test_modules = begin
_pipe = Project_test_files,
gleam@list:map(
_pipe,
fun(Module_name_dot_gleam) ->
{ok, {Module_name@1, _@2}} = case gleam@string:split_once(
Module_name_dot_gleam,
<<".gleam"/utf8>>
) of
{ok, {Module_name, _@1}} -> {ok, {Module_name, _@1}};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"glacier"/utf8>>,
function => <<"derive_test_modules_from_src_import_dependencies"/utf8>>,
line => 315})
end,
Module_name@1
end
)
end,
Dirty_test_modules = begin
_pipe@1 = All_test_modules,
gleam@list:filter(
_pipe@1,
fun(Test_module) ->
Test_module_imports = derive_src_imports_off_test_module(
Test_module
),
gleam@list:any(
Src_modules,
fun(Src_module) ->
_pipe@2 = Test_module_imports,
gleam@list:contains(_pipe@2, Src_module)
end
)
end
)
end,
Dirty_test_modules.
-spec derive_src_imports_off_test_module(binary()) -> list(binary()).
derive_src_imports_off_test_module(Test_module_name) ->
_pipe = Test_module_name,
_pipe@1 = module_name_to_file_name(_pipe, test_module_kind),
parse_module_for_imports(_pipe@1).
-spec module_name_to_file_name(binary(), module_kind()) -> binary().
module_name_to_file_name(Module_name, Module_kind) ->
case Module_kind of
src_module_kind ->
<<<<<<(get_src_dir())/binary, "/"/utf8>>/binary,
Module_name/binary>>/binary,
".gleam"/utf8>>;
test_module_kind ->
<<<<<<(get_test_dir())/binary, "/"/utf8>>/binary,
Module_name/binary>>/binary,
".gleam"/utf8>>
end.
-spec file_name_to_module_name(binary(), module_kind()) -> binary().
file_name_to_module_name(Module_name, Module_kind) ->
{ok, {_@2, Module_name_dot_gleam@1}} = case case Module_kind of
src_module_kind ->
gleam@string:split_once(
Module_name,
<<(get_src_dir())/binary, "/"/utf8>>
);
test_module_kind ->
gleam@string:split_once(
Module_name,
<<(get_test_dir())/binary, "/"/utf8>>
)
end of
{ok, {_@1, Module_name_dot_gleam}} -> {ok, {_@1, Module_name_dot_gleam}};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"glacier"/utf8>>,
function => <<"file_name_to_module_name"/utf8>>,
line => 357})
end,
case gleam@string:ends_with(Module_name, <<".erl"/utf8>>) of
true ->
{ok, {Module_name@2, _@4}} = case gleam@string:split_once(
Module_name_dot_gleam@1,
<<".erl"/utf8>>
) of
{ok, {Module_name@1, _@3}} -> {ok, {Module_name@1, _@3}};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"glacier"/utf8>>,
function => <<"file_name_to_module_name"/utf8>>,
line => 363})
end,
Module_name@2;
false ->
{ok, {Module_name@4, _@6}} = case gleam@string:split_once(
Module_name_dot_gleam@1,
<<".gleam"/utf8>>
) of
{ok, {Module_name@3, _@5}} -> {ok, {Module_name@3, _@5}};
_try@2 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@2,
module => <<"glacier"/utf8>>,
function => <<"file_name_to_module_name"/utf8>>,
line => 368})
end,
Module_name@4
end.
-spec file_exists(binary()) -> boolean().
file_exists(Absolute_file_name) ->
filelib:is_regular(Absolute_file_name).
-spec find_project_files(binary()) -> list(binary()).
find_project_files(Sub_directory) ->
do_find_project_files(Sub_directory).
-spec target() -> target().
target() ->
do_target().
-spec start_args() -> list(binary()).
start_args() ->
do_start_args().
-spec get_cwd() -> binary().
get_cwd() ->
glacier_ffi:get_cwd_as_binary().
-spec get_src_dir() -> binary().
get_src_dir() ->
<<(get_cwd())/binary, "/src"/utf8>>.
-spec get_test_dir() -> binary().
get_test_dir() ->
<<(get_cwd())/binary, "/test"/utf8>>.
-spec to_relative_path(binary()) -> binary().
to_relative_path(Path) ->
{ok, {_@2, Relative_file_name@1}} = case gleam@string:split_once(
Path,
<<(get_cwd())/binary, "/"/utf8>>
) of
{ok, {_@1, Relative_file_name}} -> {ok, {_@1, Relative_file_name}};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"glacier"/utf8>>,
function => <<"to_relative_path"/utf8>>,
line => 420})
end,
Relative_file_name@1.
-spec do_target() -> target().
do_target() ->
erlang_target.
-spec do_start_args() -> list(binary()).
do_start_args() ->
gleam@erlang:start_arguments().
-spec read_module_file(binary()) -> {ok, binary()} | {error, nil}.
read_module_file(Module_path) ->
case gleam@erlang@file:read(Module_path) of
{ok, Text} ->
{ok, Text};
{error, _@1} ->
{error, nil}
end.
-spec do_find_project_files(binary()) -> list(binary()).
do_find_project_files(In) ->
glacier_ffi:find_files_recursive(In, <<"**/*.{gleam}"/utf8>>).