src/hank_context.erl

%%% @doc rebar3 contextual data turned into a type that we can also manually build, if needed
-module(hank_context).

-type apps_dirs() :: #{atom() => file:filename()}.

-opaque t() :: #{app_dirs := apps_dirs(), project_apps := [atom()]}.

-export_type([t/0, apps_dirs/0]).

-export([from_rebar_state/1, new/2]).
-export([app_dir/2, project_apps/1]).

%% @doc Build a context from a rebar3 state.
-spec from_rebar_state(rebar_state:t()) -> t().
from_rebar_state(State) ->
    AppDirs =
        [{binary_to_atom(rebar_app_info:name(App), utf8), rebar_app_info:dir(App)}
         || App <- rebar_state:project_apps(State)],
    ProjectApps = proplists:get_keys(AppDirs),
    new(maps:from_list(AppDirs), ProjectApps).

%% @doc Build a context from scratch.
-spec new(apps_dirs(), [atom()]) -> t().
new(AppDirs, ProjectApps) ->
    #{app_dirs => AppDirs, project_apps => ProjectApps}.

%% @doc Return the root folder for an app.
-spec app_dir(atom(), t()) -> undefined | file:filename().
app_dir(App, #{app_dirs := AppDirs}) ->
    maps:get(App, AppDirs, undefined).

%% @doc OTP applications included in the project.
-spec project_apps(t()) -> [atom()].
project_apps(#{project_apps := ProjectApps}) ->
    ProjectApps.