mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Make static hooks analyzer working again
This commit is contained in:
parent
2aa181658a
commit
7a03a125aa
@ -12,69 +12,49 @@
|
|||||||
|
|
||||||
main([Dir]) ->
|
main([Dir]) ->
|
||||||
State =
|
State =
|
||||||
filelib:fold_files(
|
fold_beams(
|
||||||
Dir, ".+\.[eh]rl\$", false,
|
fun(File0, Tree, Acc0) ->
|
||||||
fun(FileIn, Res) ->
|
BareName = filename:rootname(filename:basename(File0)),
|
||||||
case get_forms(FileIn) of
|
Mod = list_to_atom(BareName),
|
||||||
{ok, Forms} ->
|
File = BareName ++ ".erl",
|
||||||
Tree = erl_syntax:form_list(Forms),
|
Acc1 = Acc0#state{file = File, module = Mod},
|
||||||
Mod = list_to_atom(filename:rootname(filename:basename(FileIn))),
|
erl_syntax_lib:fold(
|
||||||
Acc0 = analyze_form(Tree, Res#state{module = Mod, file = FileIn}),
|
fun(Form, Acc) ->
|
||||||
erl_syntax_lib:fold(
|
case erl_syntax:type(Form) of
|
||||||
fun(Form, Acc) ->
|
application ->
|
||||||
case erl_syntax:type(Form) of
|
case erl_syntax_lib:analyze_application(Form) of
|
||||||
application ->
|
{ejabberd_hooks, {run, N}}
|
||||||
case erl_syntax_lib:analyze_application(Form) of
|
when N == 2; N == 3 ->
|
||||||
{ejabberd_hooks, {run, N}}
|
analyze_run_hook(Form, Acc);
|
||||||
when N == 2; N == 3 ->
|
{ejabberd_hooks, {run_fold, N}}
|
||||||
analyze_run_hook(Form, Acc);
|
when N == 3; N == 4 ->
|
||||||
{ejabberd_hooks, {run_fold, N}}
|
analyze_run_fold_hook(Form, Acc);
|
||||||
when N == 3; N == 4 ->
|
{ejabberd_hooks, {add, N}}
|
||||||
analyze_run_fold_hook(Form, Acc);
|
when N == 4; N == 5 ->
|
||||||
{ejabberd_hooks, {add, N}}
|
analyze_run_fun(Form, Acc);
|
||||||
when N == 4; N == 5 ->
|
{gen_iq_handler, {add_iq_handler, N}}
|
||||||
analyze_run_fun(Form, Acc);
|
when N == 5; N == 6 ->
|
||||||
{gen_iq_handler, {add_iq_handler, N}}
|
analyze_iq_handler(Form, Acc);
|
||||||
when N == 5; N == 6 ->
|
|
||||||
analyze_iq_handler(Form, Acc);
|
|
||||||
_ ->
|
|
||||||
Acc
|
|
||||||
end;
|
|
||||||
attribute ->
|
|
||||||
case catch erl_syntax_lib:analyze_attribute(Form) of
|
|
||||||
{spec, _} ->
|
|
||||||
analyze_type_spec(Form, Acc);
|
|
||||||
_ ->
|
|
||||||
Acc
|
|
||||||
end;
|
|
||||||
_ ->
|
_ ->
|
||||||
Acc
|
Acc
|
||||||
end
|
end;
|
||||||
end, Acc0, Tree);
|
attribute ->
|
||||||
_Err ->
|
case catch erl_syntax_lib:analyze_attribute(Form) of
|
||||||
Res
|
{spec, _} ->
|
||||||
end
|
analyze_type_spec(Form, Acc);
|
||||||
end, #state{}),
|
_ ->
|
||||||
|
Acc
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, Acc1, Tree)
|
||||||
|
end, #state{}, Dir),
|
||||||
report_orphaned_funs(State),
|
report_orphaned_funs(State),
|
||||||
RunDeps = build_deps(State#state.run_hooks, State#state.hooked_funs),
|
RunDeps = build_deps(State#state.run_hooks, State#state.hooked_funs),
|
||||||
RunFoldDeps = build_deps(State#state.run_fold_hooks, State#state.hooked_funs),
|
RunFoldDeps = build_deps(State#state.run_fold_hooks, State#state.hooked_funs),
|
||||||
emit_module(RunDeps, RunFoldDeps, State#state.specs, Dir, hooks_type_test).
|
emit_module(RunDeps, RunFoldDeps, State#state.specs, Dir, hooks_type_test).
|
||||||
|
|
||||||
analyze_form(_Form, State) ->
|
|
||||||
%% case catch erl_syntax_lib:analyze_forms(Form) of
|
|
||||||
%% Props when is_list(Props) ->
|
|
||||||
%% M = State#state.module,
|
|
||||||
%% MFAs = lists:foldl(
|
|
||||||
%% fun({F, A}, Acc) ->
|
|
||||||
%% dict:append({M, F}, A, Acc)
|
|
||||||
%% end, State#state.mfas,
|
|
||||||
%% proplists:get_value(functions, Props, [])),
|
|
||||||
%% State#state{mfas = MFAs};
|
|
||||||
%% _ ->
|
|
||||||
%% State
|
|
||||||
%% end.
|
|
||||||
State.
|
|
||||||
|
|
||||||
analyze_run_hook(Form, State) ->
|
analyze_run_hook(Form, State) ->
|
||||||
[Hook|Tail] = erl_syntax:application_arguments(Form),
|
[Hook|Tail] = erl_syntax:application_arguments(Form),
|
||||||
case atom_value(Hook, State) of
|
case atom_value(Hook, State) of
|
||||||
@ -145,7 +125,7 @@ analyze_iq_handler(Form, State) ->
|
|||||||
code:ensure_loaded(Mod),
|
code:ensure_loaded(Mod),
|
||||||
case erlang:function_exported(Mod, Fun, 1) of
|
case erlang:function_exported(Mod, Fun, 1) of
|
||||||
false ->
|
false ->
|
||||||
log("~s:~p: Error: function ~s:~s/1 is registered "
|
err("~s:~p: Error: function ~s:~s/1 is registered "
|
||||||
"as iq handler, but is not exported~n",
|
"as iq handler, but is not exported~n",
|
||||||
[State#state.file, erl_syntax:get_pos(Form),
|
[State#state.file, erl_syntax:get_pos(Form),
|
||||||
Mod, Fun]);
|
Mod, Fun]);
|
||||||
@ -179,7 +159,7 @@ build_deps(Hooks, Hooked) ->
|
|||||||
code:ensure_loaded(M),
|
code:ensure_loaded(M),
|
||||||
case erlang:function_exported(M, F, Arity) of
|
case erlang:function_exported(M, F, Arity) of
|
||||||
false ->
|
false ->
|
||||||
log("~s:~p: Error: function ~s:~s/~p "
|
err("~s:~p: Error: function ~s:~s/~p "
|
||||||
"is hooked on ~s/~p, but is not "
|
"is hooked on ~s/~p, but is not "
|
||||||
"exported~n",
|
"exported~n",
|
||||||
[FunFile, FunLineNo, M, F,
|
[FunFile, FunLineNo, M, F,
|
||||||
@ -204,7 +184,7 @@ report_orphaned_funs(State) ->
|
|||||||
fun({M, F, _, {File, Line}}) ->
|
fun({M, F, _, {File, Line}}) ->
|
||||||
case get_fun_arities(M, F, State) of
|
case get_fun_arities(M, F, State) of
|
||||||
[] ->
|
[] ->
|
||||||
log("~s:~p: Error: function ~s:~s is "
|
err("~s:~p: Error: function ~s:~s is "
|
||||||
"hooked on hook ~s, but is not exported~n",
|
"hooked on hook ~s, but is not exported~n",
|
||||||
[File, Line, M, F, Hook]);
|
[File, Line, M, F, Hook]);
|
||||||
Arities ->
|
Arities ->
|
||||||
@ -219,7 +199,7 @@ report_orphaned_funs(State) ->
|
|||||||
end, Arities) of
|
end, Arities) of
|
||||||
false ->
|
false ->
|
||||||
Arity = hd(Arities),
|
Arity = hd(Arities),
|
||||||
log("~s:~p: Error: function ~s:~s/~p is hooked"
|
err("~s:~p: Error: function ~s:~s/~p is hooked"
|
||||||
" on non-existent hook ~s/~p~n",
|
" on non-existent hook ~s/~p~n",
|
||||||
[File, Line, M, F, Arity, Hook, Arity]);
|
[File, Line, M, F, Arity, Hook, Arity]);
|
||||||
true ->
|
true ->
|
||||||
@ -277,7 +257,7 @@ emit_module(RunDeps, RunFoldDeps, Specs, Dir, Module) ->
|
|||||||
file:close(Fd),
|
file:close(Fd),
|
||||||
log("Module written to file ~s~n", [File])
|
log("Module written to file ~s~n", [File])
|
||||||
catch _:{badmatch, {error, Reason}} ->
|
catch _:{badmatch, {error, Reason}} ->
|
||||||
log("writing to ~s failed: ~s", [File, file:format_error(Reason)])
|
err("writing to ~s failed: ~s", [File, file:format_error(Reason)])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
emit_run_hooks(Fd, Deps, Specs) ->
|
emit_run_hooks(Fd, Deps, Specs) ->
|
||||||
@ -352,41 +332,32 @@ emit_specs(Fd, Funs, Specs) ->
|
|||||||
end
|
end
|
||||||
end, lists:keysort(2, Funs)).
|
end, lists:keysort(2, Funs)).
|
||||||
|
|
||||||
get_forms(Path) ->
|
fold_beams(Fun, State, Dir) ->
|
||||||
case file:open(Path, [read]) of
|
filelib:fold_files(
|
||||||
{ok, Fd} ->
|
Dir, ".+\.beam\$", false,
|
||||||
parse(Path, Fd, 1, []);
|
fun(File, Acc) ->
|
||||||
Err ->
|
AbsCode = get_code_from_beam(File),
|
||||||
Err
|
lists:foldl(
|
||||||
end.
|
fun(Form, Acc1) ->
|
||||||
|
Fun(File, Form, Acc1)
|
||||||
|
end, Acc, AbsCode)
|
||||||
|
end, State).
|
||||||
|
|
||||||
parse(Path, Fd, Line, Acc) ->
|
get_code_from_beam(File) ->
|
||||||
{ok, Pos} = file:position(Fd, cur),
|
try
|
||||||
case epp_dodger:parse_form(Fd, Line) of
|
{ok, {_, List}} = beam_lib:chunks(File, [abstract_code]),
|
||||||
{ok, Form, NewLine} ->
|
{_, {raw_abstract_v1, Forms}} = lists:keyfind(abstract_code, 1, List),
|
||||||
{ok, NewPos} = file:position(Fd, cur),
|
Forms
|
||||||
{ok, RawForm} = file:pread(Fd, Pos, NewPos - Pos),
|
catch _:{badmatch, _} ->
|
||||||
file:position(Fd, {bof, NewPos}),
|
err("no abstract code found in ~s~n", [File])
|
||||||
AnnForm = erl_syntax:set_ann(Form, RawForm),
|
|
||||||
parse(Path, Fd, NewLine, [AnnForm|Acc]);
|
|
||||||
{eof, _} ->
|
|
||||||
{ok, NewPos} = file:position(Fd, cur),
|
|
||||||
if NewPos > Pos ->
|
|
||||||
{ok, RawForm} = file:pread(Fd, Pos, NewPos - Pos),
|
|
||||||
Form = erl_syntax:text(""),
|
|
||||||
AnnForm = erl_syntax:set_ann(Form, RawForm),
|
|
||||||
{ok, lists:reverse([AnnForm|Acc])};
|
|
||||||
true ->
|
|
||||||
{ok, lists:reverse(Acc)}
|
|
||||||
end;
|
|
||||||
{error, {_, _, ErrDesc}, LineNo} = Err ->
|
|
||||||
log("~s:~p: Error: ~s~n",
|
|
||||||
[Path, LineNo, erl_parse:format_error(ErrDesc)]),
|
|
||||||
Err
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
log(Format, Args) ->
|
log(Format, Args) ->
|
||||||
io:format(standard_io, Format, Args).
|
io:format(standard_io, Format, Args).
|
||||||
|
|
||||||
|
err(Format, Args) ->
|
||||||
|
io:format(standard_error, "Error: " ++ Format, Args),
|
||||||
|
halt(1).
|
||||||
|
|
||||||
write(Fd, Format, Args) ->
|
write(Fd, Format, Args) ->
|
||||||
file:write(Fd, io_lib:format(Format, Args)).
|
file:write(Fd, io_lib:format(Format, Args)).
|
||||||
|
Loading…
Reference in New Issue
Block a user