Преглед на файлове

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

Fixes and updates
pull/3/head
Dave Smith преди 12 години
родител
ревизия
00164b280a
променени са 8 файла, в които са добавени 125 реда и са изтрити 87 реда
  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

+ 0
- 7
.hgignore Целия файл

@ -1,7 +0,0 @@
\.beam
^rebar$
.~
\.orig
\.swp
rt.work/*
^.gitignore$

+ 0
- 1
.hgtags Целия файл

@ -1 +0,0 @@
e8747041ef63f1b394d3b156c72c5bc12e92ecc4 RELEASE-1

+ 1
- 0
Makefile Целия файл

@ -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:

+ 11
- 0
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

+ 3
- 1
rebar.config.sample Целия файл

@ -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()},...]}

+ 22
- 16
src/rebar_core.erl Целия файл

@ -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.

+ 10
- 4
src/rebar_ct.erl Целия файл

@ -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} =

+ 78
- 58
src/rebar_xref.erl Целия файл

@ -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

Зареждане…
Отказ
Запис