-module(checkmark@internal@code_extractor). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/checkmark/internal/code_extractor.gleam"). -export([load/1, extract_function/2, extract_function_body/2, extract_type/2]). -export_type([extract_error/0, file/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 extract_error() :: {name_not_found, binary()} | span_extraction_failed. -opaque file() :: {source, bitstring(), glance:module_(), splitter:splitter()}. -file("src/checkmark/internal/code_extractor.gleam", 19). ?DOC(false). -spec load(binary()) -> {ok, file()} | {error, nil}. load(Source) -> gleam@result:map( begin _pipe = glance:module(Source), gleam@result:replace_error(_pipe, nil) end, fun(Module) -> Line_ends = splitter:new([<<"\n"/utf8>>, <<"\r\n"/utf8>>]), {source, gleam_stdlib:identity(Source), Module, Line_ends} end ). -file("src/checkmark/internal/code_extractor.gleam", 72). ?DOC(false). -spec indent_amount(binary(), integer()) -> integer(). indent_amount(String, Amount) -> case String of <<" "/utf8, Rest/binary>> -> indent_amount(Rest, Amount + 1); _ -> Amount end. -file("src/checkmark/internal/code_extractor.gleam", 62). ?DOC(false). -spec unindent(list(binary())) -> list(binary()). unindent(Indented) -> Indent_amount = begin _pipe = gleam@list:first(Indented), _pipe@1 = gleam@result:map( _pipe, fun(_capture) -> indent_amount(_capture, 0) end ), gleam@result:unwrap(_pipe@1, 0) end, gleam@list:map( Indented, fun(Line) -> gleam@string:drop_start(Line, Indent_amount) end ). -file("src/checkmark/internal/code_extractor.gleam", 79). ?DOC(false). -spec statement_span(glance:statement()) -> glance:span(). statement_span(Statement) -> case Statement of {expression, Expr} -> erlang:element(2, Expr); {assert, Location, _, _} -> Location; {assignment, Location@1, _, _, _, _} -> Location@1; {use, Location@2, _, _} -> Location@2 end. -file("src/checkmark/internal/code_extractor.gleam", 88). ?DOC(false). -spec find_function(file(), binary()) -> {ok, glance:function_()} | {error, extract_error()}. find_function(File, Name) -> _pipe = erlang:element(6, erlang:element(3, File)), _pipe@1 = gleam@list:map( _pipe, fun(Definition) -> erlang:element(3, Definition) end ), _pipe@2 = gleam@list:find( _pipe@1, fun(F) -> erlang:element(3, F) =:= Name end ), gleam@result:replace_error(_pipe@2, {name_not_found, Name}). -file("src/checkmark/internal/code_extractor.gleam", 98). ?DOC(false). -spec find_type(file(), binary()) -> {ok, glance:custom_type()} | {error, extract_error()}. find_type(File, Name) -> _pipe = erlang:element(3, erlang:element(3, File)), _pipe@1 = gleam@list:map( _pipe, fun(Definition) -> erlang:element(3, Definition) end ), _pipe@2 = gleam@list:find( _pipe@1, fun(F) -> erlang:element(3, F) =:= Name end ), gleam@result:replace_error(_pipe@2, {name_not_found, Name}). -file("src/checkmark/internal/code_extractor.gleam", 119). ?DOC(false). -spec include_leading_space(bitstring(), integer()) -> integer(). include_leading_space(Bits, Position) -> gleam@bool:guard( Position =:= 0, Position, fun() -> Checked = Position - 1, case gleam_stdlib:bit_array_slice(Bits, Checked, 1) of {ok, <<" "/utf8>>} -> include_leading_space(Bits, Checked); _ -> Position end end ). -file("src/checkmark/internal/code_extractor.gleam", 128). ?DOC(false). -spec include_trailing_space(bitstring(), integer()) -> integer(). include_trailing_space(Bits, Position) -> case gleam_stdlib:bit_array_slice(Bits, Position, 1) of {ok, <<" "/utf8>>} -> include_trailing_space(Bits, Position + 1); {ok, <<"\r"/utf8>>} -> include_trailing_space(Bits, Position + 1); {ok, <<"\n"/utf8>>} -> include_trailing_space(Bits, Position + 1); _ -> Position end. -file("src/checkmark/internal/code_extractor.gleam", 108). ?DOC(false). -spec extract_source(file(), glance:span()) -> {ok, list(binary())} | {error, extract_error()}. extract_source(File, Span) -> Start = include_leading_space( erlang:element(2, File), erlang:element(2, Span) ), End = include_trailing_space( erlang:element(2, File), erlang:element(3, Span) ), _pipe = erlang:element(2, File), _pipe@1 = gleam_stdlib:bit_array_slice(_pipe, Start, End - Start), _pipe@2 = gleam@result:'try'(_pipe@1, fun gleam@bit_array:to_string/1), _pipe@3 = gleam@result:map( _pipe@2, fun(_capture) -> checkmark@internal@lines:to_lines( erlang:element(4, File), _capture, [] ) end ), gleam@result:replace_error(_pipe@3, span_extraction_failed). -file("src/checkmark/internal/code_extractor.gleam", 25). ?DOC(false). -spec extract_function(file(), binary()) -> {ok, list(binary())} | {error, extract_error()}. extract_function(File, Name) -> gleam@result:'try'( find_function(File, Name), fun(Function) -> extract_source(File, erlang:element(2, Function)) end ). -file("src/checkmark/internal/code_extractor.gleam", 33). ?DOC(false). -spec extract_function_body(file(), binary()) -> {ok, list(binary())} | {error, extract_error()}. extract_function_body(File, Name) -> gleam@result:'try'( find_function(File, Name), fun(Function) -> Span = begin _pipe = gleam@list:first(erlang:element(7, Function)), gleam@result:map( _pipe, fun(First) -> Last@1 = case gleam@list:last( erlang:element(7, Function) ) of {ok, Last} -> Last; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"checkmark/internal/code_extractor"/utf8>>, function => <<"extract_function_body"/utf8>>, line => 41, value => _assert_fail, start => 1062, 'end' => 1108, pattern_start => 1073, pattern_end => 1081}) end, {span, erlang:element(2, statement_span(First)), erlang:element(3, statement_span(Last@1))} end ) end, gleam@result:'try'(case Span of {error, _} -> {ok, []}; {ok, Span@1} -> extract_source(File, Span@1) end, fun(Indented) -> {ok, unindent(Indented)} end) end ). -file("src/checkmark/internal/code_extractor.gleam", 54). ?DOC(false). -spec extract_type(file(), binary()) -> {ok, list(binary())} | {error, extract_error()}. extract_type(File, Name) -> gleam@result:'try'( find_type(File, Name), fun(Function) -> extract_source(File, erlang:element(2, Function)) end ).