1
0
mirror of https://github.com/amix/vimrc synced 2025-07-21 11:54:59 +08:00
This commit is contained in:
huangqundl
2017-03-17 23:12:53 +08:00
parent 47b213d974
commit cba39b7326
855 changed files with 59981 additions and 35298 deletions

View File

@ -1,56 +1,262 @@
#!/usr/bin/env escript
-export([main/1]).
main([FileName]) ->
LibDirs = (["ebin", "include", "src", "test"] ++
filelib:wildcard("{apps,deps,lib}/*/{ebin,include}")),
compile(FileName, LibDirs);
main([File]) ->
Dir = get_root(filename:dirname(File)),
Defs = [strong_validation,
warn_export_all,
warn_export_vars,
warn_shadow_vars,
warn_obsolete_guard,
warn_unused_import,
report,
{i, Dir ++ "/include"}],
%% `rebar.config` is looked for,
%% but it is not necessarily the one in the project root.
%% I.e. it may be one deeper in the project file hierarchy.
Profile = which_compile_opts_profile(filename:absname(File)),
CompileOpts = case which_build_tool(Dir, Profile) of
{rebar, RebarFile} ->
%% `rebar.config` might contain relative paths.
%% They are relative to the file! Not to the project root.
%% rebar specific begin
rebar_opts(RebarFile);
%% rebar specific end
{erlangmk, ErlangMkDir} ->
%% Erlang.mk specific begin
erlangmk_opts(ErlangMkDir, Profile);
%% Erlang.mk specific end
undefined ->
fallback_opts()
end,
code:add_patha(filename:absname("ebin")),
%% `compile:file/2` requires the `{i, Path}` to be relative
%% to CWD - no surprise here.
compile:file(File, Defs ++ translate_paths(Dir, CompileOpts));
main([FileName, "-rebar", Path, LibDirs]) ->
{ok, L} = file:consult(Path),
P = dict:from_list(L),
Root = filename:dirname(Path),
main(_) ->
io:format("Usage: ~s <file>~n", [escript:script_name()]),
halt(1).
Lib1 = case dict:find(lib_dirs, P) of
{ok, X} -> lists:map(fun(Sub) -> Root ++ "/" ++ Sub end, X);
_ -> []
end,
which_compile_opts_profile(File) ->
case filename:basename(filename:dirname(File)) of
"test" -> test;
_ -> normal
end.
Lib2 = case dict:find(sub_dirs, P) of
{ok, Y} -> lists:foldl(
fun(Sub,Sofar) ->
Sofar ++ [
Root ++ "/" ++ Sub,
Root ++ "/" ++ Sub ++ "/include",
Root ++ "/" ++ Sub ++ "/deps",
Root ++ "/" ++ Sub ++ "/lib"
] end, [], Y);
_ -> []
end,
which_build_tool(Dir, Profile) ->
%% rebar specific begin
RebarFile = rebar_file(Dir, Profile),
%% rebar specific end
case filelib:is_file(RebarFile) of
true ->
{rebar, RebarFile};
false ->
%% Erlang.mk specific begin
ErlangMk = erlangmk_file(Dir),
%% Erlang.mk specific end
case filelib:is_file(ErlangMk) of
true -> {erlangmk, Dir};
false -> undefined
end
end.
LibDirs1 = LibDirs ++ Lib1 ++ Lib2,
%io:format("~p~n", [LibDirs1]),
compile(FileName, LibDirs1);
rebar_file(Dir, normal) -> filename:join(Dir, "rebar.config");
rebar_file(Dir, test) -> filename:join(Dir, "rebar.test.config").
main([FileName | LibDirs]) ->
compile(FileName, LibDirs).
erlangmk_file(Dir) -> filename:join(Dir, "erlang.mk").
compile(FileName, LibDirs) ->
Root = get_root(filename:dirname(FileName)),
ok = code:add_pathsa(LibDirs),
compile:file(FileName,
[warn_obsolete_guard,
warn_unused_import,
warn_shadow_vars,
warn_export_vars,
strong_validation,
report] ++
[{i, filename:join(Root, I)} || I <- LibDirs] ++
case lists:member("deps/pmod_transform/include", LibDirs) of
true -> [{parse_transform, pmod_pt}];
_ -> []
end
).
rebar_opts(RebarFile) ->
Dir = get_root(filename:dirname(RebarFile)),
case file:consult(RebarFile) of
{ok, Terms} ->
RebarLibDirs = proplists:get_value(lib_dirs, Terms, []),
lists:foreach(
fun(LibDir) ->
code:add_pathsa(filelib:wildcard(LibDir ++ "/*/ebin"))
end, RebarLibDirs),
RebarDepsDir = proplists:get_value(deps_dir, Terms, "deps"),
code:add_pathsa(filelib:wildcard(RebarDepsDir ++ "/*/ebin")),
IncludeDeps = {i, filename:join(Dir, RebarDepsDir)},
proplists:get_value(erl_opts, Terms, []) ++ [IncludeDeps];
{error, _} when RebarFile == "rebar.config" ->
fallback_opts();
{error, _} ->
rebar_opts("rebar.config")
end.
erlangmk_opts(BaseDir, Profile) ->
Make =
case os:getenv("MAKE") of
false ->
case os:find_executable("gmake") of
false -> "make";
Path -> Path
end;
Cmd ->
case (lists:member($/, Cmd) orelse lists:member($\\, Cmd)) of
true -> Cmd;
false -> os:find_executable(Cmd)
end
end,
ERLC_OPTS_Target =
case Profile of
normal -> "show-ERLC_OPTS";
test -> "show-TEST_ERLC_OPTS"
end,
Args = [
"--no-print-directory",
"-C", BaseDir,
"show-ERL_LIBS",
ERLC_OPTS_Target
],
try
Port = erlang:open_port({spawn_executable, Make}, [
{args, Args},
exit_status, use_stdio, stderr_to_stdout]),
case erlangmk_port_receive_loop(Port, "", BaseDir) of
{error, _} ->
fallback_opts();
{ok, {ErlLibs, ErlcOpts}} ->
[code:add_pathsa(filelib:wildcard(
filename:join([ErlLib, "*", "ebin"])))
|| ErlLib <- ErlLibs],
ErlcOpts
end
catch
error:_ ->
fallback_opts()
end.
erlangmk_port_receive_loop(Port, Stdout, BaseDir) ->
receive
{Port, {exit_status, 0}} ->
erlangmk_format_opts(Stdout, BaseDir);
{Port, {exit_status, _}} ->
{error, {erlangmk, make_target_failure}};
{Port, {data, Out}} ->
erlangmk_port_receive_loop(Port, Stdout ++ Out, BaseDir)
end.
erlangmk_format_opts(Stdout, BaseDir) ->
case string:tokens(Stdout, "\n") of
[ErlLibsLine | ErlcOptsLines] ->
ErlLibs = erlangmk_format_erl_libs(ErlLibsLine),
ErlcOpts = erlangmk_format_erlc_opts(ErlcOptsLines, BaseDir),
{ok, {ErlLibs, ErlcOpts}};
_ ->
{error, {erlangmk, incorrect_output}}
end.
erlangmk_format_erl_libs(ErlLibsLine) ->
case os:type() of
{win32, _} -> string:tokens(ErlLibsLine, ";");
_ -> string:tokens(ErlLibsLine, ":")
end.
erlangmk_format_erlc_opts(ErlcOptsLines, BaseDir) ->
erlangmk_format_erlc_opts(ErlcOptsLines, [], BaseDir).
erlangmk_format_erlc_opts(["+" ++ Option | Rest], Opts, BaseDir) ->
case make_term(Option) of
{error, _} -> erlangmk_format_erlc_opts(Rest, Opts, BaseDir);
Opt -> erlangmk_format_erlc_opts(Rest, [Opt | Opts], BaseDir)
end;
erlangmk_format_erlc_opts(["-I" ++ Opt | Rest], Opts, BaseDir)
when Opt =/= "" ->
erlangmk_format_erlc_opts(["-I", Opt | Rest], Opts, BaseDir);
erlangmk_format_erlc_opts(["-I", [C | _] = Dir | Rest], Opts, BaseDir)
when C =/= $- andalso C =/= $+ ->
AbsDir = filename:absname(Dir, BaseDir),
erlangmk_format_erlc_opts(Rest, [{i, AbsDir} | Opts], BaseDir);
erlangmk_format_erlc_opts(["-W" ++ Warn | Rest], Opts, BaseDir)
when Warn =/= "" ->
erlangmk_format_erlc_opts(["-W", Warn | Rest], Opts, BaseDir);
erlangmk_format_erlc_opts(["-W", Warn | Rest], Opts, BaseDir) ->
case Warn of
"all" ->
erlangmk_format_erlc_opts(Rest, [{warn_format, 999} | Opts],
BaseDir);
"error" ->
erlangmk_format_erlc_opts(Rest, [warnings_as_errors | Opts],
BaseDir);
"" ->
erlangmk_format_erlc_opts(Rest, [{warn_format, 1} | Opts],
BaseDir);
_ ->
try list_to_integer(Warn) of
Level ->
erlangmk_format_erlc_opts(Rest,
[{warn_format, Level} | Opts], BaseDir)
catch
error:badarg ->
erlangmk_format_erlc_opts(Rest, Opts, BaseDir)
end
end;
erlangmk_format_erlc_opts(["-D" ++ Opt | Rest], Opts, BaseDir)
when Opt =/= "" ->
erlangmk_format_erlc_opts(["-D", Opt | Rest], Opts, BaseDir);
erlangmk_format_erlc_opts(["-D", [C | _] = Val0 | Rest], Opts, BaseDir)
when C =/= $- andalso C =/= $+ ->
{Key0, Val1} = split_at_equals(Val0, []),
Key = list_to_atom(Key0),
case Val1 of
[] ->
erlangmk_format_erlc_opts(Rest, [{d, Key} | Opts], BaseDir);
Val2 ->
case make_term(Val2) of
{error, _} ->
erlangmk_format_erlc_opts(Rest, Opts, BaseDir);
Val ->
erlangmk_format_erlc_opts(Rest, [{d, Key, Val} | Opts], BaseDir)
end
end;
erlangmk_format_erlc_opts([PathFlag, [_ | _] = Dir | Rest], Opts, BaseDir)
when PathFlag =:= "-pa" orelse PathFlag =:= "-pz" ->
AbsDir = filename:absname(Dir, BaseDir),
case PathFlag of
"-pa" -> code:add_patha(AbsDir);
"-pz" -> code:add_pathz(AbsDir)
end,
erlangmk_format_erlc_opts(Rest, Opts, BaseDir);
erlangmk_format_erlc_opts([_ | Rest], Opts, BaseDir) ->
erlangmk_format_erlc_opts(Rest, Opts, BaseDir);
erlangmk_format_erlc_opts([], Opts, _) ->
lists:reverse(Opts).
%% Function imported from erl_compile.erl from Erlang 19.1.
make_term(Str) ->
case erl_scan:string(Str) of
{ok, Tokens, _} ->
case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
{ok, Term} -> Term;
{error, Reason} -> {error, Reason}
end;
{error, Reason, _} ->
{error, Reason}
end.
%% Function imported from erl_compile.erl from Erlang 19.1.
split_at_equals([$=|T], Acc) ->
{lists:reverse(Acc),T};
split_at_equals([H|T], Acc) ->
split_at_equals(T, [H|Acc]);
split_at_equals([], Acc) ->
{lists:reverse(Acc),[]}.
fallback_opts() ->
code:add_pathsa(filelib:wildcard("deps/*/ebin")),
code:add_pathsa(nested_app_ebins()),
[
{ i, filename:absname("apps") }, { i, filename:absname("deps") } | [ { i, filename:absname(Path) } || Path <- filelib:wildcard("deps/*/apps")]
].
nested_app_ebins() ->
DetectedAppSrcFiles = filelib:wildcard("deps/*/apps/**/*.app.src"),
[apps_dir_from_src(AppSrcFile)||AppSrcFile<-DetectedAppSrcFiles].
apps_dir_from_src(SrcFile) ->
SrcDir = filename:dirname(SrcFile),
filename:join(SrcDir, "../../ebin").
get_root(Dir) ->
Path = filename:split(filename:absname(Dir)),
@ -64,3 +270,15 @@ get_root(["test" | Tail], _Path) ->
lists:reverse(Tail);
get_root([_ | Tail], Path) ->
get_root(Tail, Path).
translate_paths(Dir, RebarOpts) ->
[ translate_path(Dir, Opt) || Opt <- RebarOpts ].
translate_path(Dir, {i, Path}) ->
case Path of
%% absolute
"/" ++ _ -> {i, Path};
%% relative -> make absolute taking rebar.config location into account
_ -> {i, filename:join([Dir, Path])}
end;
translate_path(_, Other) -> Other.

View File

@ -19,17 +19,19 @@ if !exists('g:syntastic_erlc_include_path')
let g:syntastic_erlc_include_path = ''
endif
let s:check_file = syntastic#util#shescape(expand('<sfile>:p:h') . syntastic#util#Slash() . 'erlang_check_file.erl')
let s:check_file = syntastic#util#shescape(expand('<sfile>:p:h', 1) . syntastic#util#Slash() . 'erlang_check_file.erl')
let s:save_cpo = &cpo
set cpo&vim
function! SyntaxCheckers_erlang_escript_GetLocList() dict
if expand('%:e') ==# 'hrl'
let buf = bufnr('')
if fnamemodify(bufname(buf), ':e') ==# 'hrl'
return []
endif
let shebang = syntastic#util#parseShebang()
let shebang = syntastic#util#parseShebang(buf)
if shebang['exe'] ==# 'escript'
let args = '-s'
let post_args = ''
@ -39,7 +41,7 @@ function! SyntaxCheckers_erlang_escript_GetLocList() dict
endif
let makeprg = self.makeprgBuild({
\ 'args_after': args,
\ 'fname': syntastic#util#shexpand('%:p'),
\ 'fname': syntastic#util#shexpand(fnamemodify(bufname(buf), ':p')),
\ 'post_args_after': post_args })
let errorformat =
@ -58,4 +60,4 @@ call g:SyntasticRegistry.CreateAndRegisterChecker({
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4:
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -9,7 +9,7 @@
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"============================================================================
if exists("g:loaded_syntastic_erlang_syntaxerl_checker")
if exists('g:loaded_syntastic_erlang_syntaxerl_checker')
finish
endif
@ -39,4 +39,4 @@ call g:SyntasticRegistry.CreateAndRegisterChecker({
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4:
" vim: set sw=4 sts=4 et fdm=marker: