mirror of
https://github.com/amix/vimrc
synced 2025-07-21 11:54:59 +08:00
merge
This commit is contained in:
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user