Permalink
Browse files

Merge pull request #99 from tuncer/fixes-and-updates

Fixes and updates
  • Loading branch information...
2 parents be8b022 + 09cd4e9 commit 00164b280aa3710027089611ebfbaa5730f0f995 @dizzyd dizzyd committed Jun 25, 2013
Showing with 125 additions and 87 deletions.
  1. +0 −7 .hgignore
  2. +0 −1 .hgtags
  3. +1 −0 Makefile
  4. +11 −0 THANKS
  5. +3 −1 rebar.config.sample
  6. +22 −16 src/rebar_core.erl
  7. +10 −4 src/rebar_ct.erl
  8. +78 −58 src/rebar_xref.erl
View
@@ -1,7 +0,0 @@
-\.beam
-^rebar$
-.~
-\.orig
-\.swp
-rt.work/*
-^.gitignore$
View
@@ -1 +0,0 @@
-e8747041ef63f1b394d3b156c72c5bc12e92ecc4 RELEASE-1
View
@@ -10,6 +10,7 @@ clean:
@rm -rf rebar ebin/*.beam inttest/rt.work rt.work .eunit
distclean: clean
+ @rm -f dialyzer_warnings
@rm -rf deps
debug:
View
11 THANKS
@@ -109,3 +109,14 @@ Daniel White
Martin Schut
Serge Aleynikov
Magnus Henoch
+Artem Teslenko
+Jeremie Lasalle Ratelle
+Jose Valim
+Krzysztof Rutka
+Mats Cronqvist
+Matthew Conway
+Giacomo Olgeni
+Pedram Nimreezi
+Sylvain Benner
+Oliver Ferrigni
+Dave Thomas
View
@@ -209,7 +209,9 @@
{xref_warnings, false}.
%% xref checks to run
-{xref_checks, [exports_not_used, undefined_function_calls]}.
+{xref_checks, [undefined_function_calls, undefined_functions,
+ locals_not_used, exports_not_used,
+ deprecated_function_calls, deprecated_functions]}.
%% Optional custom xref queries (xref manual has details) specified as
%% {xref_queries, [{query_string(), expected_query_result()},...]}
View
@@ -533,21 +533,7 @@ plugin_modules(Config, PredirsAssoc, FoundModules, MissingModules) ->
load_plugin_modules(Config, PredirsAssoc, Modules) ->
Cwd = rebar_utils:get_cwd(),
- PluginDirs = case rebar_config:get_local(Config, plugin_dir, undefined) of
- undefined ->
- % Plugin can be in the project's "plugins" folder
- [filename:join(Cwd, "plugins")];
- Dir ->
- [Dir]
- end ++
- % We also want to include this case:
- % Plugin can be in "plugins" directory of the plugin base directory. For
- % example, Cwd depends on Plugin, and deps/Plugin/plugins/Plugin.erl is the
- % plugin.
- [
- filename:join(Dir, "plugins") ||
- Dir <- get_plugin_base_dirs(Cwd, PredirsAssoc)
- ],
+ PluginDirs = get_all_plugin_dirs(Config, Cwd, PredirsAssoc),
%% Find relevant sources in base_dir and plugin_dir
Erls = string:join([atom_to_list(M)++"\\.erl" || M <- Modules], "|"),
@@ -562,12 +548,32 @@ load_plugin_modules(Config, PredirsAssoc, Modules) ->
NotLoaded = [V || V <- Modules, FilterMissing(V)],
{Loaded, NotLoaded}.
+get_all_plugin_dirs(Config, Cwd, PredirsAssoc) ->
+ get_plugin_dir(Config, Cwd) ++ get_base_plugin_dirs(Cwd, PredirsAssoc).
+
+get_plugin_dir(Config, Cwd) ->
+ case rebar_config:get_local(Config, plugin_dir, undefined) of
+ undefined ->
+ %% Plugin can be in the project's "plugins" folder
+ [filename:join(Cwd, "plugins")];
+ Dir ->
+ [Dir]
+ end.
+
+%% We also want to include this case:
+%% Plugin can be in "plugins" directory of the plugin base directory.
+%% For example, Cwd depends on Plugin, and deps/Plugin/plugins/Plugin.erl
+%% is the plugin.
+get_base_plugin_dirs(Cwd, PredirsAssoc) ->
+ [filename:join(Dir, "plugins") ||
+ Dir <- get_plugin_base_dirs(Cwd, PredirsAssoc)].
+
%% @doc PredirsAssoc is a dictionary of plugindir -> 'parent' pairs
%% 'parent' in this case depends on plugin; therefore we have to give
%% all plugins that Cwd ('parent' in this case) depends on.
get_plugin_base_dirs(Cwd, PredirsAssoc) ->
[PluginDir || {PluginDir, Master} <- dict:to_list(PredirsAssoc),
- Master =:= Cwd].
+ Master =:= Cwd].
is_missing_plugin(Loaded) ->
fun(Mod) -> not lists:member(Mod, Loaded) end.
View
@@ -108,7 +108,8 @@ run_test(TestDir, LogDir, Config, _File) ->
" 2>&1 | tee -a " ++ RawLog
end,
- case rebar_utils:sh(Cmd ++ Output, [{env,[{"TESTDIR", TestDir}]}, return_on_error]) of
+ ShOpts = [{env,[{"TESTDIR", TestDir}]}, return_on_error],
+ case rebar_utils:sh(Cmd ++ Output, ShOpts) of
{ok,_} ->
%% in older versions of ct_run, this could have been a failure
%% that returned a non-0 code. Check for that!
@@ -135,11 +136,16 @@ clear_log(LogDir, RawLog) ->
check_success_log(Config, RawLog) ->
check_log(Config, RawLog, fun(Msg) -> ?CONSOLE("DONE.\n~s\n", [Msg]) end).
-check_fail_log(Config, RawLog, Command, {Rc, Output}) ->
- check_log(Config, RawLog, fun(_Msg) ->
+-type err_handler() :: fun((string()) -> no_return()).
+-spec failure_logger(string(), {integer(), string()}) -> err_handler().
+failure_logger(Command, {Rc, Output}) ->
+ fun(_Msg) ->
?ABORT("~s failed with error: ~w and output:~n~s~n",
[Command, Rc, Output])
- end).
+ end.
+
+check_fail_log(Config, RawLog, Command, Result) ->
+ check_log(Config, RawLog, failure_logger(Command, Result)).
check_log(Config,RawLog,Fun) ->
{ok, Msg} =
View
@@ -37,6 +37,9 @@
-export([xref/2]).
+%% for internal use only
+-export([info/2]).
+
%% ===================================================================
%% Public API
%% ===================================================================
@@ -58,14 +61,15 @@ xref(Config, _) ->
%% Get list of xref checks we want to run
ConfXrefChecks = rebar_config:get(Config, xref_checks,
- [exports_not_used,
- undefined_function_calls]),
+ [exports_not_used,
+ undefined_function_calls]),
SupportedXrefs = [undefined_function_calls, undefined_functions,
- locals_not_used, exports_not_used,
- deprecated_function_calls, deprecated_functions],
+ locals_not_used, exports_not_used,
+ deprecated_function_calls, deprecated_functions],
- XrefChecks = sets:to_list(sets:intersection(sets:from_list(SupportedXrefs),
+ XrefChecks = sets:to_list(sets:intersection(
+ sets:from_list(SupportedXrefs),
sets:from_list(ConfXrefChecks))),
%% Run xref checks
@@ -92,17 +96,37 @@ xref(Config, _) ->
%% Internal functions
%% ===================================================================
+info(help, xref) ->
+ ?CONSOLE(
+ "Run cross reference analysis.~n"
+ "~n"
+ "Valid rebar.config options:~n"
+ " ~p~n"
+ " ~p~n"
+ " ~p~n",
+ [
+ {xref_warnings, false},
+ {xref_checks, [undefined_function_calls, undefined_functions,
+ locals_not_used, exports_not_used,
+ deprecated_function_calls, deprecated_functions]},
+ {xref_queries,
+ [{"(xc - uc) || (xu - x - b"
+ " - (\"mod\":\".*foo\"/\"4\"))",[]}]}
+ ]).
+
xref_checks(XrefChecks) ->
- XrefWarnCount = lists:foldl(
- fun(XrefCheck, Acc) ->
- {ok, Results} = xref:analyze(xref, XrefCheck),
- FilteredResults =filter_xref_results(XrefCheck, Results),
- lists:foreach(fun(Res) -> display_xrefresult(XrefCheck, Res) end, FilteredResults),
- Acc + length(FilteredResults)
- end,
- 0, XrefChecks),
+ XrefWarnCount = lists:foldl(fun run_xref_check/2, 0, XrefChecks),
XrefWarnCount =:= 0.
+run_xref_check(XrefCheck, Acc) ->
+ {ok, Results} = xref:analyze(xref, XrefCheck),
+ FilteredResults =filter_xref_results(XrefCheck, Results),
+ lists:foreach(fun(Res) ->
+ display_xref_result(XrefCheck, Res)
+ end,
+ FilteredResults),
+ Acc + length(FilteredResults).
+
check_query({Query, Value}) ->
{ok, Answer} = xref:q(xref, Query),
case Answer =:= Value of
@@ -141,78 +165,75 @@ get_xref_ignorelist(Mod, XrefCheck) ->
_Class:_Error -> []
end,
- Ignore_xref = keyall(ignore_xref, Attributes),
+ IgnoreXref = keyall(ignore_xref, Attributes),
- Behaviour_callbacks = case XrefCheck of
- exports_not_used -> [B:behaviour_info(callbacks) || B <- keyall(behaviour, Attributes)];
- _ -> []
- end,
+ BehaviourCallbacks = get_behaviour_callbacks(XrefCheck, Attributes),
- % And create a flat {M,F,A} list
+ %% And create a flat {M,F,A} list
lists:foldl(
- fun(El,Acc) ->
- case El of
- {F, A} -> [{Mod,F,A} | Acc];
- {M, F, A} -> [{M,F,A} | Acc]
- end
- end, [],lists:flatten([Ignore_xref, Behaviour_callbacks])).
+ fun({F, A}, Acc) -> [{Mod,F,A} | Acc];
+ ({M, F, A}, Acc) -> [{M,F,A} | Acc]
+ end, [], lists:flatten([IgnoreXref, BehaviourCallbacks])).
keyall(Key, List) ->
lists:flatmap(fun({K, L}) when Key =:= K -> L; (_) -> [] end, List).
-parse_xref_result(XrefResult) ->
- case XrefResult of
- {_, MFAt} -> MFAt;
- MFAt -> MFAt
- end.
+get_behaviour_callbacks(exports_not_used, Attributes) ->
+ [B:behaviour_info(callbacks) || B <- keyall(behaviour, Attributes)];
+get_behaviour_callbacks(_XrefCheck, _Attributes) ->
+ [].
+
+parse_xref_result({_, MFAt}) -> MFAt;
+parse_xref_result(MFAt) -> MFAt.
filter_xref_results(XrefCheck, XrefResults) ->
- SearchModules = lists:usort(lists:map(
- fun(Res) ->
- case Res of
- {Mt,_Ft,_At} -> Mt;
- {{Ms,_Fs,_As},{_Mt,_Ft,_At}} -> Ms;
- _ -> undefined
- end
- end, XrefResults)),
-
- Ignores = lists:flatten([
- get_xref_ignorelist(Module,XrefCheck) || Module <- SearchModules]),
+ SearchModules = lists:usort(
+ lists:map(
+ fun({Mt,_Ft,_At}) -> Mt;
+ ({{Ms,_Fs,_As},{_Mt,_Ft,_At}}) -> Ms;
+ (_) -> undefined
+ end, XrefResults)),
+
+ Ignores = lists:flatmap(fun(Module) ->
+ get_xref_ignorelist(Module, XrefCheck)
+ end, SearchModules),
[Result || Result <- XrefResults,
- not lists:member(parse_xref_result(Result),Ignores)].
+ not lists:member(parse_xref_result(Result), Ignores)].
-display_xrefresult(Type, XrefResult) ->
+display_xref_result(Type, XrefResult) ->
{ Source, SMFA, TMFA } = case XrefResult of
- {MFASource, MFATarget} ->
- {format_mfa_source(MFASource), format_mfa(MFASource),
- format_mfa(MFATarget)};
- MFATarget ->
- {format_mfa_source(MFATarget), format_mfa(MFATarget),
- undefined}
- end,
+ {MFASource, MFATarget} ->
+ {format_mfa_source(MFASource),
+ format_mfa(MFASource),
+ format_mfa(MFATarget)};
+ MFATarget ->
+ {format_mfa_source(MFATarget),
+ format_mfa(MFATarget),
+ undefined}
+ end,
case Type of
undefined_function_calls ->
?CONSOLE("~sWarning: ~s calls undefined function ~s (Xref)\n",
- [Source, SMFA, TMFA]);
+ [Source, SMFA, TMFA]);
undefined_functions ->
?CONSOLE("~sWarning: ~s is undefined function (Xref)\n",
- [Source, SMFA]);
+ [Source, SMFA]);
locals_not_used ->
?CONSOLE("~sWarning: ~s is unused local function (Xref)\n",
- [Source, SMFA]);
+ [Source, SMFA]);
exports_not_used ->
?CONSOLE("~sWarning: ~s is unused export (Xref)\n",
- [Source, SMFA]);
+ [Source, SMFA]);
deprecated_function_calls ->
?CONSOLE("~sWarning: ~s calls deprecated function ~s (Xref)\n",
- [Source, SMFA, TMFA]);
+ [Source, SMFA, TMFA]);
deprecated_functions ->
?CONSOLE("~sWarning: ~s is deprecated function (Xref)\n",
- [Source, SMFA]);
+ [Source, SMFA]);
Other ->
?CONSOLE("~sWarning: ~s - ~s xref check: ~s (Xref)\n",
- [Source, SMFA, TMFA, Other])
+ [Source, SMFA, TMFA, Other])
end.
format_mfa({M, F, A}) ->
@@ -236,7 +257,6 @@ safe_element(N, Tuple) ->
Value
end.
-
%%
%% Given a MFA, find the file and LOC where it's defined. Note that
%% xref doesn't work if there is no abstract_code, so we can avoid

0 comments on commit 00164b2

Please sign in to comment.