Bläddra i källkod

fix base path used for yrl/xrl includefile configs (#1952)

pull/1953/head
Tristan Sloughter 6 år sedan
committed by GitHub
förälder
incheckning
37fdc7e515
Ingen känd nyckel hittad för denna signaturen i databasen GPG-nyckel ID: 4AEE18F83AFDEB23
3 ändrade filer med 176 tillägg och 18 borttagningar
  1. +21
    -9
      src/rebar_compiler_xrl.erl
  2. +7
    -7
      src/rebar_compiler_yrl.erl
  3. +148
    -2
      test/rebar_compile_SUITE.erl

+ 21
- 9
src/rebar_compiler_xrl.erl Visa fil

@ -8,6 +8,8 @@
compile/4,
clean/2]).
-export([update_opts/2]).
context(AppInfo) ->
Dir = rebar_app_info:dir(AppInfo),
Mappings = [{".erl", filename:join([Dir, "src"])}],
@ -25,28 +27,38 @@ needed_files(_, FoundFiles, Mappings, AppInfo) ->
rebar_compiler:needs_compile(Source, ".erl", Mappings)],
Opts = rebar_opts:get(rebar_app_info:opts(AppInfo), xrl_opts, []),
Opts1 = update_opts(Opts, AppInfo),
{{FirstFiles, Opts}, {RestFiles, Opts}}.
{{FirstFiles, Opts1}, {RestFiles, Opts1}}.
dependencies(_, _, _) ->
[].
compile(Source, [{_, OutDir}], _, Opts) ->
BaseName = filename:basename(Source),
Target = filename:join([OutDir, BaseName]),
AllOpts = [{parserfile, Target} | Opts],
AllOpts1 = [{includefile, filename:join(OutDir, I)} || {includefile, I} <- AllOpts,
filename:pathtype(I) =:= relative],
case leex:file(Source, AllOpts1 ++ [{return, true}]) of
compile(Source, [{_, _}], _, Opts) ->
case leex:file(Source, [{return, true} | Opts]) of
{ok, _} ->
ok;
{ok, _Mod, Ws} ->
rebar_compiler:ok_tuple(Source, Ws);
{error, Es, Ws} ->
rebar_compiler:error_tuple(Source, Es, Ws, AllOpts1)
rebar_compiler:error_tuple(Source, Es, Ws, Opts)
end.
clean(XrlFiles, _AppInfo) ->
rebar_file_utils:delete_each(
[rebar_utils:to_list(re:replace(F, "\\.xrl$", ".erl", [unicode]))
|| F <- XrlFiles]).
%% make includefile options absolute paths
update_opts(Opts, AppInfo) ->
OutDir = rebar_app_info:out_dir(AppInfo),
lists:map(fun({includefile, I}) ->
case filename:pathtype(I) =:= relative of
true ->
{includefile, filename:join(OutDir, I)};
false ->
{includefile, I}
end;
(O) ->
O
end, Opts).

+ 7
- 7
src/rebar_compiler_yrl.erl Visa fil

@ -25,24 +25,24 @@ needed_files(_, FoundFiles, Mappings, AppInfo) ->
rebar_compiler:needs_compile(Source, ".erl", Mappings)],
Opts = rebar_opts:get(rebar_app_info:opts(AppInfo), yrl_opts, []),
{{FirstFiles, Opts}, {RestFiles, Opts}}.
Opts1 = rebar_compiler_xrl:update_opts(Opts, AppInfo),
{{FirstFiles, Opts1}, {RestFiles, Opts1}}.
dependencies(_, _, _) ->
[].
compile(Source, [{_, OutDir}], _, Opts) ->
BaseName = filename:basename(Source),
BaseName = filename:basename(Source, ".yrl"),
Target = filename:join([OutDir, BaseName]),
AllOpts = [{parserfile, Target} | Opts],
AllOpts1 = [{includefile, filename:join(OutDir, I)} || {includefile, I} <- AllOpts,
filename:pathtype(I) =:= relative],
case yecc:file(Source, AllOpts1 ++ [{return, true}]) of
AllOpts = [{parserfile, Target}, {return, true} | Opts],
case yecc:file(Source, AllOpts) of
{ok, _} ->
ok;
{ok, _Mod, Ws} ->
rebar_compiler:ok_tuple(Source, Ws);
{error, Es, Ws} ->
rebar_compiler:error_tuple(Source, Es, Ws, AllOpts1)
rebar_compiler:error_tuple(Source, Es, Ws, AllOpts)
end.
clean(YrlFiles, _AppInfo) ->

+ 148
- 2
test/rebar_compile_SUITE.erl Visa fil

@ -852,7 +852,13 @@ dont_recompile_yrl_or_xrl(Config) ->
XrlBeam = filename:join([EbinDir, filename:basename(Xrl, ".xrl") ++ ".beam"]),
YrlBeam = filename:join([EbinDir, filename:basename(Yrl, ".yrl") ++ ".beam"]),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
Hrl = filename:join([AppDir, "include", "some_header.hrl"]),
ok = filelib:ensure_dir(Hrl),
HrlBody = yeccpre_hrl(),
ok = ec_file:write(Hrl, HrlBody),
RebarConfig = [{yrl_opts, [{includefile, "include/some_header.hrl"}]}],
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
XrlModTime = filelib:last_modified(XrlErl),
YrlModTime = filelib:last_modified(YrlErl),
@ -862,7 +868,7 @@ dont_recompile_yrl_or_xrl(Config) ->
timer:sleep(1000),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
NewXrlModTime = filelib:last_modified(XrlErl),
NewYrlModTime = filelib:last_modified(YrlErl),
@ -2208,3 +2214,143 @@ regex_filter_regression(Config) ->
{ok, [{file, Expected}]}),
ok.
%%
%% a copy of lib/parsetools/include/yeccpre.hrl so we can test yrl includefile
yeccpre_hrl() ->
<<"-type yecc_ret() :: {'error', _} | {'ok', _}.
-spec parse(Tokens :: list()) -> yecc_ret().
parse(Tokens) ->
yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
-spec parse_and_scan({function() | {atom(), atom()}, [_]}
| {atom(), atom(), [_]}) -> yecc_ret().
parse_and_scan({F, A}) ->
yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
Arity = length(A),
yeccpars0([], {{fun M:F/Arity, A}, no_line}, 0, [], []).
-spec format_error(any()) -> [char() | list()].
format_error(Message) ->
case io_lib:deep_char_list(Message) of
true ->
Message;
_ ->
io_lib:write(Message)
end.
%% To be used in grammar files to throw an error message to the parser
%% toplevel. Doesn't have to be exported!
-compile({nowarn_unused_function, return_error/2}).
-spec return_error(integer(), any()) -> no_return().
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
-define(CODE_VERSION, \"1.4\").
yeccpars0(Tokens, Tzr, State, States, Vstack) ->
try yeccpars1(Tokens, Tzr, State, States, Vstack)
catch
error:Error ->
try yecc_error_type(Error, []) of
Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
[])
catch _:_ -> erlang:raise(error, Error, [])
end;
%% Probably thrown from return_error/2:
throw: {error, {_Line, ?MODULE, _M}} = Error ->
Error
end.
yecc_error_type(function_clause, _) ->
not_implemented.
yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr);
yeccpars1([], {{F, A},_Line}, State, States, Vstack) ->
case apply(F, A) of
{ok, Tokens, Endline} ->
yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack);
{eof, Endline} ->
yeccpars1([], {no_func, Endline}, State, States, Vstack);
{error, Descriptor, _Endline} ->
{error, Descriptor}
end;
yeccpars1([], {no_func, no_line}, State, States, Vstack) ->
Line = 999999,
yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [],
{no_func, Line});
yeccpars1([], {no_func, Endline}, State, States, Vstack) ->
yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [],
{no_func, Endline}).
%% yeccpars1/7 is called from generated code.
%%
%% When using the {includefile, Includefile} option, make sure that
%% yeccpars1/7 can be found by parsing the file without following
%% include directives. yecc will otherwise assume that an old
%% yeccpre.hrl is included (one which defines yeccpars1/5).
yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) ->
yeccpars2(State, element(1, Token), [State1 | States],
[Token0 | Vstack], Token, Tokens, Tzr);
yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) ->
yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]);
yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) ->
Line = yecctoken_end_location(Token0),
yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
yecc_end(Line), [], {no_func, Line});
yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) ->
yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
yecc_end(Line), [], {no_func, Line}).
%% For internal use only.
yecc_end({Line,_Column}) ->
{'$end', Line};
yecc_end(Line) ->
{'$end', Line}.
yecctoken_end_location(Token) ->
try erl_anno:end_location(element(2, Token)) of
undefined -> yecctoken_location(Token);
Loc -> Loc
catch _:_ -> yecctoken_location(Token)
end.
-compile({nowarn_unused_function, yeccerror/1}).
yeccerror(Token) ->
Text = yecctoken_to_string(Token),
Location = yecctoken_location(Token),
{error, {Location, ?MODULE, [\"syntax error before: \", Text]}}.
-compile({nowarn_unused_function, yecctoken_to_string/1}).
yecctoken_to_string(Token) ->
try erl_scan:text(Token) of
undefined -> yecctoken2string(Token);
Txt -> Txt
catch _:_ -> yecctoken2string(Token)
end.
yecctoken_location(Token) ->
try erl_scan:location(Token)
catch _:_ -> element(2, Token)
end.
-compile({nowarn_unused_function, yecctoken2string/1}).
yecctoken2string({atom, _, A}) -> io_lib:write_atom(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
yecctoken2string({char,_,C}) -> io_lib:write_char(C);
yecctoken2string({var,_,V}) -> io_lib:format(\"~s\", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_string(S);
yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
yecctoken2string({_Cat, _, Val}) -> io_lib:format(\"~p\", [Val]);
yecctoken2string({dot, _}) -> \"'.'\";
yecctoken2string({'$end', _}) -> [];
yecctoken2string({Other, _}) when is_atom(Other) ->
io_lib:write_atom(Other);
yecctoken2string(Other) ->
io_lib:format(\"~p\", [Other]).
">>.

Laddar…
Avbryt
Spara