Current section

Files

Jump to
graded src graded@internal@extract.erl
Raw

src/graded@internal@extract.erl

-module(graded@internal@extract).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/graded/internal/extract.gleam").
-export([build_import_context/1, extract_calls/2]).
-export_type([import_context/0, extract_result/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.
?MODULEDOC(false).
-type import_context() :: {import_context,
gleam@dict:dict(binary(), binary()),
gleam@dict:dict(binary(), graded@internal@types:qualified_name())}.
-type extract_result() :: {extract_result,
list(graded@internal@types:resolved_call()),
list(graded@internal@types:local_call()),
list(graded@internal@types:field_call()),
list(graded@internal@types:resolved_call())}.
-file("src/graded/internal/extract.gleam", 85).
?DOC(false).
-spec is_constructor_name(binary()) -> boolean().
is_constructor_name(Name) ->
case gleam@string:first(Name) of
{ok, Char} ->
(Char =:= string:uppercase(Char)) andalso (Char /= string:lowercase(
Char
));
{error, nil} ->
false
end.
-file("src/graded/internal/extract.gleam", 119).
?DOC(false).
-spec last_segment(binary()) -> binary().
last_segment(Module_path) ->
_pipe = Module_path,
_pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>),
_pipe@2 = gleam@list:last(_pipe@1),
gleam@result:unwrap(_pipe@2, Module_path).
-file("src/graded/internal/extract.gleam", 33).
?DOC(false).
-spec build_import_context(glance:module_()) -> import_context().
build_import_context(Module) ->
{Aliases, Unqualified} = gleam@list:fold(
erlang:element(2, Module),
{maps:new(), maps:new()},
fun(State, Definition) ->
Import_ = erlang:element(3, Definition),
Module_path = erlang:element(3, Import_),
Alias = case erlang:element(4, Import_) of
{some, {named, Name}} ->
Name;
{some, {discarded, _}} ->
last_segment(Module_path);
none ->
last_segment(Module_path)
end,
New_aliases = gleam@dict:insert(
erlang:element(1, State),
Alias,
Module_path
),
New_unqualified = gleam@list:fold(
erlang:element(6, Import_),
erlang:element(2, State),
fun(Unqualified_map, Unqualified_import) ->
Name@1 = case erlang:element(3, Unqualified_import) of
{some, Alias_name} ->
Alias_name;
none ->
erlang:element(2, Unqualified_import)
end,
gleam@dict:insert(
Unqualified_map,
Name@1,
{qualified_name,
Module_path,
erlang:element(2, Unqualified_import)}
)
end
),
{New_aliases, New_unqualified}
end
),
{import_context, Aliases, Unqualified}.
-file("src/graded/internal/extract.gleam", 392).
?DOC(false).
-spec empty() -> extract_result().
empty() ->
{extract_result, [], [], [], []}.
-file("src/graded/internal/extract.gleam", 92).
?DOC(false).
-spec resolve_unqualified_call(binary(), glance:span(), import_context()) -> extract_result().
resolve_unqualified_call(Name, Span, Context) ->
case is_constructor_name(Name) of
true ->
empty();
false ->
case gleam_stdlib:map_get(erlang:element(3, Context), Name) of
{ok, Qualified_name} ->
{extract_result,
[{resolved_call, Qualified_name, Span}],
[],
[],
[]};
{error, nil} ->
{extract_result, [], [{local_call, Name, Span}], [], []}
end
end.
-file("src/graded/internal/extract.gleam", 396).
?DOC(false).
-spec merge(extract_result(), extract_result()) -> extract_result().
merge(Left, Right) ->
{extract_result,
lists:append(erlang:element(2, Left), erlang:element(2, Right)),
lists:append(erlang:element(3, Left), erlang:element(3, Right)),
lists:append(erlang:element(4, Left), erlang:element(4, Right)),
lists:append(erlang:element(5, Left), erlang:element(5, Right))}.
-file("src/graded/internal/extract.gleam", 151).
?DOC(false).
-spec extract_from_expression(glance:expression(), import_context()) -> extract_result().
extract_from_expression(Expression, Context) ->
case Expression of
{call,
Span,
{field_access, _, {variable, _, Alias}, Function_name},
Arguments} ->
Call_result = case gleam_stdlib:map_get(
erlang:element(2, Context),
Alias
) of
{ok, Module_path} ->
{extract_result,
[{resolved_call,
{qualified_name, Module_path, Function_name},
Span}],
[],
[],
[]};
{error, nil} ->
{extract_result,
[],
[],
[{field_call, Alias, Function_name, Span}],
[]}
end,
merge(Call_result, extract_from_arguments(Arguments, Context));
{call, Span@1, {variable, _, Name}, Arguments@1} ->
merge(
resolve_unqualified_call(Name, Span@1, Context),
extract_from_arguments(Arguments@1, Context)
);
{call, _, Function_expression, Arguments@2} ->
merge(
extract_from_expression(Function_expression, Context),
extract_from_arguments(Arguments@2, Context)
);
{binary_operator, _, pipe, Left, Right} ->
merge(
extract_from_expression(Left, Context),
extract_pipe_target(Right, Context)
);
{binary_operator, _, _, Left@1, Right@1} ->
merge(
extract_from_expression(Left@1, Context),
extract_from_expression(Right@1, Context)
);
{fn, _, _, _, Statements} ->
extract_calls(Statements, Context);
{block, _, Statements@1} ->
extract_calls(Statements@1, Context);
{'case', _, Subjects, Clauses} ->
merge(
fold_expressions(Subjects, Context),
gleam@list:fold(
Clauses,
empty(),
fun(Accumulated, Clause) ->
merge(Accumulated, extract_from_clause(Clause, Context))
end
)
);
{tuple, _, Elements} ->
fold_expressions(Elements, Context);
{list, _, Elements@1, Rest} ->
merge_optional(fold_expressions(Elements@1, Context), Rest, Context);
{negate_int, _, Value} ->
extract_from_expression(Value, Context);
{negate_bool, _, Value@1} ->
extract_from_expression(Value@1, Context);
{record_update, _, _, _, Record, _} ->
extract_from_expression(Record, Context);
{field_access, Span@2, {variable, _, Alias@1}, Function_name@1} ->
case gleam_stdlib:map_get(erlang:element(2, Context), Alias@1) of
{ok, Module_path@1} ->
{extract_result,
[],
[],
[],
[{resolved_call,
{qualified_name, Module_path@1, Function_name@1},
Span@2}]};
{error, nil} ->
empty()
end;
{field_access, _, Container, _} ->
extract_from_expression(Container, Context);
{tuple_index, _, Tuple, _} ->
extract_from_expression(Tuple, Context);
{fn_capture,
_,
_,
Function_expression@1,
Arguments_before,
Arguments_after} ->
merge(
extract_from_expression(Function_expression@1, Context),
merge(
extract_from_arguments(Arguments_before, Context),
extract_from_arguments(Arguments_after, Context)
)
);
{echo, _, {some, Inner}, _} ->
extract_from_expression(Inner, Context);
{echo, _, none, _} ->
empty();
{variable, Span@3, Name@1} ->
case gleam_stdlib:map_get(erlang:element(3, Context), Name@1) of
{ok, Qualified_name} ->
{extract_result,
[],
[],
[],
[{resolved_call, Qualified_name, Span@3}]};
{error, nil} ->
empty()
end;
{int, _, _} ->
empty();
{float, _, _} ->
empty();
{string, _, _} ->
empty();
{panic, _, _} ->
empty();
{todo, _, _} ->
empty();
{bit_string, _, _} ->
empty()
end.
-file("src/graded/internal/extract.gleam", 74).
?DOC(false).
-spec extract_calls(list(glance:statement()), import_context()) -> extract_result().
extract_calls(Statements, Context) ->
gleam@list:fold(
Statements,
empty(),
fun(Accumulated, Statement) ->
merge(Accumulated, extract_from_statement(Statement, Context))
end
).
-file("src/graded/internal/extract.gleam", 126).
?DOC(false).
-spec extract_from_statement(glance:statement(), import_context()) -> extract_result().
extract_from_statement(Statement, Context) ->
case Statement of
{expression, Expression} ->
extract_from_expression(Expression, Context);
{assignment, _, _, _, _, Expression@1} ->
extract_from_expression(Expression@1, Context);
{use, _, _, Expression@2} ->
extract_from_expression(Expression@2, Context);
{assert, _, Expression@3, Message} ->
Expression_result = extract_from_expression(Expression@3, Context),
case Message of
{some, Message_expression} ->
merge(
Expression_result,
extract_from_expression(Message_expression, Context)
);
none ->
Expression_result
end
end.
-file("src/graded/internal/extract.gleam", 307).
?DOC(false).
-spec extract_pipe_target(glance:expression(), import_context()) -> extract_result().
extract_pipe_target(Expression, Context) ->
case Expression of
{field_access, Span, {variable, _, Alias}, Function_name} ->
case gleam_stdlib:map_get(erlang:element(2, Context), Alias) of
{ok, Module_path} ->
{extract_result,
[{resolved_call,
{qualified_name, Module_path, Function_name},
Span}],
[],
[],
[]};
{error, nil} ->
{extract_result,
[],
[],
[{field_call, Alias, Function_name, Span}],
[]}
end;
{variable, Span@1, Name} ->
resolve_unqualified_call(Name, Span@1, Context);
_ ->
extract_from_expression(Expression, Context)
end.
-file("src/graded/internal/extract.gleam", 346).
?DOC(false).
-spec extract_from_clause(glance:clause(), import_context()) -> extract_result().
extract_from_clause(Clause, Context) ->
Body_result = extract_from_expression(erlang:element(4, Clause), Context),
case erlang:element(3, Clause) of
{some, Guard} ->
merge(Body_result, extract_from_expression(Guard, Context));
none ->
Body_result
end.
-file("src/graded/internal/extract.gleam", 354).
?DOC(false).
-spec extract_from_arguments(
list(glance:field(glance:expression())),
import_context()
) -> extract_result().
extract_from_arguments(Arguments, Context) ->
gleam@list:fold(
Arguments,
empty(),
fun(Accumulated, Field) ->
Expression = case Field of
{labelled_field, _, _, Item} ->
{some, Item};
{shorthand_field, _, _} ->
none;
{unlabelled_field, Item@1} ->
{some, Item@1}
end,
case Expression of
{some, Inner} ->
merge(Accumulated, extract_from_expression(Inner, Context));
none ->
Accumulated
end
end
).
-file("src/graded/internal/extract.gleam", 371).
?DOC(false).
-spec fold_expressions(list(glance:expression()), import_context()) -> extract_result().
fold_expressions(Expressions, Context) ->
gleam@list:fold(
Expressions,
empty(),
fun(Accumulated, Expression) ->
merge(Accumulated, extract_from_expression(Expression, Context))
end
).
-file("src/graded/internal/extract.gleam", 380).
?DOC(false).
-spec merge_optional(
extract_result(),
gleam@option:option(glance:expression()),
import_context()
) -> extract_result().
merge_optional(Base, Optional_expression, Context) ->
case Optional_expression of
{some, Expression} ->
merge(Base, extract_from_expression(Expression, Context));
none ->
Base
end.