Current section

Files

Jump to
mc_vsn_transform src vsn_transform.erl
Raw

src/vsn_transform.erl

-module(vsn_transform).
-export([parse_transform/2]).
-export([vsn/1]).
-ignore_xref(parse_transform/2).
-ignore_xref(vsn/1).
parse_transform(Forms, Options) ->
Command = proplists:get_value(vsn_command, Options, undefined),
parse_transform(Forms, Command, Options).
parse_transform(Forms, undefined, _Options) ->
Forms;
parse_transform(Forms, Command, _Options) ->
Output = os:cmd(Command),
% Strip trailing whitespace.
Vsn = re:replace(Output, "[ \t\n]$", "", [global, {return, list}]),
HasVsn = lists:any(
fun({attribute, _, vsn, _V}) ->
true;
(_) -> false
end, Forms),
% Lie about the line number, so we don't offset everything else.
VsnAttr = {attribute, 1, vsn, Vsn},
apply_vsn(HasVsn, VsnAttr, Forms).
apply_vsn(true, _VsnAttr, Forms) ->
Forms;
apply_vsn(false, VsnAttr,
[{attribute, _, file, _F} = FileAttr,
{attribute, _, module, _M} = ModuleAttr | Rest]) ->
% We know that file and module have to come first; we want to insert
% immediately afterwards, so we can get away with this:
[FileAttr, ModuleAttr, VsnAttr | Rest];
apply_vsn(false, _VsnAttr, _Forms) ->
% Does your source file have a module attribute?
error(no_module_attribute).
vsn(Mod) ->
proplists:get_value(vsn, apply(Mod, module_info, [attributes]), undefined).