-module(builder@inspect). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/builder/inspect.gleam"). -export([find_type_definition/3, is_prelude_type/3, find_attribute/2, filter_attributes/2]). -export_type([type_definition/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 type_definition() :: {type_alias, glance:definition(glance:type_alias()), builder@module:module_()} | {custom_type, glance:definition(glance:custom_type()), builder@module:module_()}. -file("src/builder/inspect.gleam", 64). -spec find_type_definition_in_import( builder@context:build_context(), binary(), gleam@option:option(binary()), builder@module:module_() ) -> {ok, type_definition()} | {error, nil}. find_type_definition_in_import(Ctx, Type_name, Type_module_name, Module) -> Import_ = begin _pipe = erlang:element(5, Module), gleam@list:find_map(_pipe, fun(X) -> case Type_module_name of {some, Name} -> Module_name@1 = case erlang:element( 4, erlang:element(3, X) ) of {some, Module_name} -> case Module_name of {named, Name@1} -> Name@1; {discarded, Name@2} -> Name@2 end; _ -> filepath:base_name( erlang:element(3, erlang:element(3, X)) ) end, case Module_name@1 =:= Name of true -> {ok, {erlang:element(3, erlang:element(3, X)), Type_name}}; _ -> {error, nil} end; none -> case begin _pipe@1 = erlang:element(5, erlang:element(3, X)), gleam@list:find( _pipe@1, fun(X@1) -> case erlang:element(3, X@1) of {some, Name@3} -> Name@3 =:= Type_name; _ -> erlang:element(2, X@1) =:= Type_name end end ) end of {ok, Unqualified_type} -> {ok, {erlang:element(3, erlang:element(3, X)), erlang:element(2, Unqualified_type)}}; _ -> {error, nil} end end end) end, case Import_ of {ok, Import_@1} -> case gleam_stdlib:map_get( builder@context:modules(Ctx), erlang:element(1, Import_@1) ) of {ok, Module@1} -> find_type_definition_do( Ctx, {named_type, {span, 0, 0}, erlang:element(2, Import_@1), none, []}, Module@1, false ); {error, _} -> {error, nil} end; {error, _} -> {error, nil} end. -file("src/builder/inspect.gleam", 25). -spec find_type_definition_do( builder@context:build_context(), glance:type(), builder@module:module_(), boolean() ) -> {ok, type_definition()} | {error, nil}. find_type_definition_do(Ctx, Type_, Module, Inspect_imports) -> case Type_ of {named_type, _, Name, Module_name, _} -> case Module_name of {some, _} -> case Inspect_imports of true -> find_type_definition_in_import( Ctx, Name, Module_name, Module ); _ -> {error, nil} end; _ -> Custom_type = begin _pipe = erlang:element(6, Module), gleam@list:find( _pipe, fun(X) -> erlang:element(3, erlang:element(3, X)) =:= Name end ) end, Type_alias = begin _pipe@1 = erlang:element(7, Module), gleam@list:find( _pipe@1, fun(X@1) -> erlang:element(3, erlang:element(3, X@1)) =:= Name end ) end, case {Custom_type, Type_alias} of {{ok, Custom_type@1}, _} -> {ok, {custom_type, Custom_type@1, Module}}; {_, {ok, Type_alias@1}} -> {ok, {type_alias, Type_alias@1, Module}}; {_, _} -> case Inspect_imports of true -> find_type_definition_in_import( Ctx, Name, none, Module ); _ -> {error, nil} end end end; _ -> {error, nil} end. -file("src/builder/inspect.gleam", 17). ?DOC( " Searches for the type definition in the current module and follows imports\n" " to resolve qualified and unqualified type references.\n" ). -spec find_type_definition( builder@context:build_context(), glance:type(), builder@module:module_() ) -> {ok, type_definition()} | {error, nil}. find_type_definition(Ctx, Type_, Module) -> find_type_definition_do(Ctx, Type_, Module, true). -file("src/builder/inspect.gleam", 134). ?DOC( " Check if a type is a Gleam prelude type (built-in type)\n" "\n" " Returns True for types like Int, Float, Bool, String, Nil, BitArray, List,\n" " Result, tuples, and functions that don't have custom definitions.\n" ). -spec is_prelude_type( builder@context:build_context(), glance:type(), builder@module:module_() ) -> boolean(). is_prelude_type(Ctx, Type_, Current_module) -> case find_type_definition(Ctx, Type_, Current_module) of {ok, _} -> false; _ -> Check = fun(Name) -> case Name of <<"Bool"/utf8>> -> true; <<"Int"/utf8>> -> true; <<"Float"/utf8>> -> true; <<"String"/utf8>> -> true; <<"Nil"/utf8>> -> true; <<"BitArray"/utf8>> -> true; <<"List"/utf8>> -> true; <<"Result"/utf8>> -> true; _ -> false end end, case Type_ of {tuple_type, _, _} -> true; {function_type, _, _, _} -> true; {named_type, _, Name@1, Module, _} -> case Module of {some, _} -> false; _ -> Check(Name@1) end; {variable_type, _, Name@2} -> Check(Name@2); {hole_type, _, Name@3} -> Check(Name@3) end end. -file("src/builder/inspect.gleam", 174). ?DOC( " Find a specific attribute by name in a definition\n" "\n" " Returns the attribute along with the definition it belongs to.\n" ). -spec find_attribute(glance:definition(OCV), binary()) -> {ok, {glance:attribute(), OCV}} | {error, nil}. find_attribute(Definition, Attribute_name) -> gleam@list:find_map( erlang:element(2, Definition), fun(Attribute) -> case erlang:element(2, Attribute) =:= Attribute_name of true -> {ok, {Attribute, erlang:element(3, Definition)}}; false -> {error, nil} end end ). -file("src/builder/inspect.gleam", 189). ?DOC( " Filter a list of definitions to only those with a specific attribute\n" "\n" " Returns pairs of the matching attribute and its definition.\n" ). -spec filter_attributes(list(glance:definition(OCZ)), binary()) -> list({glance:attribute(), OCZ}). filter_attributes(Definitions, Attribute_name) -> gleam@list:filter_map( Definitions, fun(_capture) -> find_attribute(_capture, Attribute_name) end ).