Skip to content

Commit

Permalink
Support ignoring whole modules in xref results
Browse files Browse the repository at this point in the history
  - Added support to rebar_prv_xref for filtering out whole module. A
  module may now be added to the list of xref_ignores in rebar.config or
  via -ignore_xref() module attribute
  - Added unit test for whole module filtering support to xref CT suite
  • Loading branch information
Bryan Paxton committed Dec 2, 2018
1 parent 73bf5b4 commit 4deb643
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 9 deletions.
1 change: 1 addition & 0 deletions THANKS
Expand Up @@ -141,3 +141,4 @@ Roberto Aloi
Andrew McRobb
Drew Varner
Niklas Johansson
Bryan Paxton
6 changes: 4 additions & 2 deletions src/rebar_prv_xref.erl
Expand Up @@ -160,7 +160,8 @@ get_xref_ignorelist(Mod, XrefCheck) ->
%% And create a flat {M,F,A} list
lists:foldl(
fun({F, A}, Acc) -> [{Mod,F,A} | Acc];
({M, F, A}, Acc) -> [{M,F,A} | Acc]
({M, F, A}, Acc) -> [{M,F,A} | Acc];
(M, Acc) when is_atom(M) -> [M | Acc]
end, [], lists:flatten([IgnoreXref, BehaviourCallbacks])).

keyall(Key, List) ->
Expand Down Expand Up @@ -195,7 +196,8 @@ filter_xref_results(XrefCheck, XrefIgnores, XrefResults) ->
end, SearchModules),

[Result || Result <- XrefResults,
not lists:member(parse_xref_result(Result), Ignores)].
not lists:member(element(1, Result), Ignores)
andalso not lists:member(parse_xref_result(Result), Ignores)].

display_results(XrefResults, QueryResults) ->
[lists:map(fun display_xref_results_for_type/1, XrefResults),
Expand Down
41 changes: 34 additions & 7 deletions test/rebar_xref_SUITE.erl
Expand Up @@ -46,9 +46,11 @@ init_per_testcase(Case, Config) ->
Name = rebar_test_utils:create_random_name("xrefapp_"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_empty_app(AppDir, Name, Vsn, [kernel, stdlib]),
AppModules = [behaviour1, behaviour2, mymod, othermod],
AppModules = [behaviour1, behaviour2, mymod, othermod, ignoremod, ignoremod2],
[write_src_file(AppDir, Name, Module, ignore_xref(Case)) || Module <- AppModules],
IgnoreMod = list_to_atom(Name ++ "_" ++ "ignoremod"),
RebarConfig = [{erl_opts, [debug_info]},
{xref_ignores, [IgnoreMod]},
{xref_checks, [deprecated_function_calls,deprecated_functions,
undefined_function_calls,undefined_functions,
exports_not_used,locals_not_used]}],
Expand Down Expand Up @@ -95,7 +97,6 @@ xref_undef_behaviour(Config) ->
Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]),
verify_results(xref_undef_behaviour, Name, Result).


%% ===================================================================
%% Helper functions
%% ===================================================================
Expand Down Expand Up @@ -162,15 +163,18 @@ verify_test_results(xref_undef_behaviour, AppName, XrefResults, _QueryResults) -
?assertNot(lists:member({MyMod, bh2_b, 1}, ExportsNotUsed)),
ok;
verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) ->
AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod"],
[_Behaviour1Mod, _Behaviour2Mod, _MyMod, _OtherMod, SomeMod] =
AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod",
"ignoremod", "ignoremod2"],
[_Behaviour1Mod, _Behaviour2Mod, _MyMod, _OtherMod, SomeMod, IgnoreMod, IgnoreMod2] =
[list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules],
UndefFuns = proplists:get_value(undefined_functions, XrefResults),
?assertNot(lists:keymember(undefined_function_calls, 1, XrefResults)),
?assertNot(lists:keymember(locals_not_used, 1, XrefResults)),
?assertNot(lists:keymember(exports_not_used, 1, XrefResults)),
?assertNot(lists:keymember(deprecated_functions, 1, XrefResults)),
?assertNot(lists:keymember(deprecated_function_calls, 1, XrefResults)),
?assertNot(lists:member({IgnoreMod, notavailable, 1}, UndefFuns)),
?assertNot(lists:member({IgnoreMod2, notavailable, 1}, UndefFuns)),
?assert(lists:member({SomeMod, notavailable, 1}, UndefFuns)),
ok.

Expand All @@ -189,13 +193,15 @@ module_name(AppName, Module) ->
get_module_body(behaviour1, AppName, IgnoreXref) ->
["-module(", AppName, "_behaviour1).\n",
"-export([behaviour_info/1]).\n",
["-ignore_xref({behaviour_info,1}).\n" || X <- [IgnoreXref], X =:= true],
["-ignore_xref([ignoremod,{behaviour_info,1}]).\n"
|| X <- [IgnoreXref], X =:= true],
"behaviour_info(callbacks) -> [{bh1_a,1},{bh1_b,1}];\n",
"behaviour_info(_Other) -> undefined.\n"];
get_module_body(behaviour2, AppName, IgnoreXref) ->
["-module(", AppName, "_behaviour2).\n",
"-export([behaviour_info/1]).\n",
["-ignore_xref({behaviour_info,1}).\n" || X <- [IgnoreXref], X =:= true],
["-ignore_xref({behaviour_info,1}).\n"
|| X <- [IgnoreXref], X =:= true],
"behaviour_info(callbacks) -> [{bh2_a,1},{bh2_b,1}];\n",
"behaviour_info(_Other) -> undefined.\n"];
get_module_body(mymod, AppName, IgnoreXref) ->
Expand All @@ -217,6 +223,26 @@ get_module_body(mymod, AppName, IgnoreXref) ->
"localfunc2() -> ok.\n", % unused local
"fdeprecated() -> ok.\n" % deprecated function
];
get_module_body(ignoremod, AppName, IgnoreXref) ->
["-module(", AppName, "_ignoremod).\n",
"-export([]).\n",
[["-ignore_xref(", AppName, "_ignoremod).\n"]
|| X <- [IgnoreXref], X =:= true],
"localfunc1(A, B) -> {A, B}.\n", % used local
"localfunc2() -> ok.\n", % unused local
"fdeprecated() -> ok.\n" % deprecated function

];
get_module_body(ignoremod2, AppName, IgnoreXref) ->
["-module(", AppName, "_ignoremod2).\n",
"-export([]).\n",
[["-ignore_xref(", AppName, "_ignoremod2).\n"]
|| X <- [IgnoreXref], X =:= true],
"localfunc1(A, B) -> {A, B}.\n", % used local
"localfunc2() -> ok.\n", % unused local
"fdeprecated() -> ok.\n" % deprecated function

];
get_module_body(othermod, AppName, IgnoreXref) ->
["-module(", AppName, "_othermod).\n",
"-export([somefunc/0]).\n",
Expand All @@ -226,4 +252,5 @@ get_module_body(othermod, AppName, IgnoreXref) ->
"somefunc() ->\n",
" ", AppName, "_mymod:other1(arg),\n",
" ", AppName, "_somemod:notavailable(arg),\n",
" ", AppName, "_mymod:fdeprecated().\n"].
" ", AppName, "_mymod:fdeprecated(),\n",
" ", AppName, "_ignoremod:notavailable().\n"].

0 comments on commit 4deb643

Please sign in to comment.