aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/doc/src/compile.xml5
-rw-r--r--lib/compiler/src/compile.erl43
-rw-r--r--lib/compiler/test/compile_SUITE.erl42
-rw-r--r--lib/compiler/test/error_SUITE.erl15
4 files changed, 78 insertions, 27 deletions
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index be9eb1cd75..b87e32a3d9 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -108,6 +108,11 @@
See the <em>Efficiency Guide</em> for further information.</p>
</item>
+ <tag><c>column</c></tag>
+ <item>
+ <p>The compiler will keep the column numbers while parsing.</p>
+ </item>
+
<tag><c>compressed</c></tag>
<item>
<p>The compiler will compress the generated object code,
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 7911f51a73..fbaacc08da 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -41,7 +41,7 @@
-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
--type err_info() :: {erl_scan:line(), module(), term()}. %% ErrorDescriptor
+-type err_info() :: erl_scan:error_info(). %% ErrorDescriptor
-type errors() :: [{file:filename(), [err_info()]}].
-type warnings() :: [{file:filename(), [err_info()]}].
-type mod_ret() :: {'ok', module()}
@@ -146,10 +146,17 @@ env_default_opts() ->
do_compile(Input, Opts0) ->
Opts = expand_opts(Opts0),
- Self = self(),
- Serv = spawn_link(fun() -> internal(Self, Input, Opts) end),
+ {Pid,Ref} =
+ spawn_monitor(fun() ->
+ exit(try
+ internal(Input, Opts)
+ catch
+ error:Reason ->
+ {error,Reason}
+ end)
+ end),
receive
- {Serv,Rep} -> Rep
+ {'DOWN',Ref,process,Pid,Rep} -> Rep
end.
expand_opts(Opts0) ->
@@ -242,11 +249,6 @@ format_error({module_name,Mod,Filename}) ->
errors=[],
warnings=[]}).
-internal(Master, Input, Opts) ->
- Master ! {self(), try internal(Input, Opts)
- catch error:Reason -> {error, Reason}
- end}.
-
internal({forms,Forms}, Opts0) ->
{_,Ps} = passes(forms, Opts0),
Source = proplists:get_value(source, Opts0, ""),
@@ -361,7 +363,17 @@ messages_per_file(Ms) ->
(_) -> false
end, A)
end, T, PrioMs),
- Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end,
+ Prio = lists:sort(fun({_,{As1,_,_}}, {_,{As2,_,_}}) ->
+ {location, Loc1} =
+ erl_scan:attributes_info(As1, location),
+ {location, Loc2} =
+ erl_scan:attributes_info(As2, location),
+ case {Loc1, Loc2} of
+ {{L1, _}, L2} when is_integer(L2) -> L1 < L2;
+ {L1, {L2, _}} when is_integer(L1) -> L1 =< L2;
+ {_, _} -> Loc1 =< Loc2
+ end
+ end,
lists:append(Prio0)),
flatmap(fun mpf/1, [Prio, Rest]).
@@ -771,7 +783,8 @@ parse_module(St) ->
Opts = St#compile.options,
Cwd = ".",
IncludePath = [Cwd, St#compile.dir|inc_paths(Opts)],
- R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
+ AtPos = initial_position(Opts),
+ R = epp:parse_file(St#compile.ifile, AtPos, IncludePath, pre_defs(Opts)),
case R of
{ok,Forms} ->
{ok,St#compile{code=Forms}};
@@ -1421,7 +1434,7 @@ report_warnings(#compile{options=Opts,warnings=Ws0}) ->
end.
format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
- M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n",
+ M = {{F,Loc},io_lib:format("~s:~w:~w: ~s~s\n",
[F,Line,Column,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(F, P, [{Line,Mod,E}|Es]) ->
@@ -1477,6 +1490,12 @@ objfile(Base, St) ->
tmpfile(Ofile) ->
reverse([$#|tl(reverse(Ofile))]).
+initial_position(Opts) ->
+ case lists:member(column, Opts) of
+ true -> {1, 1};
+ false -> 1
+ end.
+
%% pre_defs(Options)
%% inc_paths(Options)
%% Extract the predefined macros and include paths from the option list.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 0dfa18490a..da53a6ba9c 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -76,6 +76,9 @@ app_test(Config) when is_list(Config) ->
file_1(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:minutes(5)),
+
+ process_flag(trap_exit, true),
+
?line {Simple, Target} = files(Config, "file_1"),
?line {ok, Cwd} = file:get_cwd(),
?line ok = file:set_cwd(filename:dirname(Target)),
@@ -102,23 +105,36 @@ file_1(Config) when is_list(Config) ->
%% Cleanup.
?line ok = file:delete(Target),
?line ok = file:del_dir(filename:dirname(Target)),
+
+ %% There should not be any messages in the messages.
+ receive
+ Any ->
+ ?t:fail({unexpected,Any})
+ after 10 ->
+ ok
+ end,
+
?line test_server:timetrap_cancel(Dog),
ok.
forms_2(Config) when is_list(Config) ->
- {ok, simple, Binary} = compile:forms([{attribute,1,module,simple}], [binary, {source,"/foo/bar"}]),
- code:load_binary(simple, "/foo/bar", Binary),
- Info = simple:module_info(compile),
-
- %% Test proper source is returned.
- "/foo/bar" = proplists:get_value(source, Info),
- %% Ensure options is not polluted with the source.
- [] = proplists:get_value(options, Info),
-
- %% Cleanup.
- true = code:delete(simple),
- false = code:purge(simple),
- ok.
+ Src = "/foo/bar",
+ AbsSrc = filename:absname(Src),
+ {ok,simple,Binary} = compile:forms([{attribute,1,module,simple}],
+ [binary,{source,Src}]),
+ code:load_binary(simple, Src, Binary),
+ Info = simple:module_info(compile),
+
+ %% Test that the proper source is returned.
+ AbsSrc = proplists:get_value(source, Info),
+
+ %% Ensure that the options are not polluted with 'source'.
+ [] = proplists:get_value(options, Info),
+
+ %% Cleanup.
+ true = code:delete(simple),
+ false = code:purge(simple),
+ ok.
module_mismatch(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index eb5e50818e..47698ecdb7 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -22,13 +22,15 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- head_mismatch_line/1,warnings_as_errors/1, bif_clashes/1]).
+ head_mismatch_line/1,warnings_as_errors/1, bif_clashes/1,
+ column_number/1
+ ]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [head_mismatch_line, warnings_as_errors, bif_clashes].
+ [head_mismatch_line, warnings_as_errors, bif_clashes, column_number].
groups() ->
[].
@@ -166,6 +168,15 @@ bif_clashes(Config) when is_list(Config) ->
+%% Tests that messages are correctly reported with column numbers
+%% if the column option is set.
+column_number(Config) when is_list(Config) ->
+ Ts1 = [{column_number_warning,
+ <<"\nt(X) -> ok.">>,
+ [return_warnings, export_all, column],
+ {warning, [{{2, 3}, erl_lint, {unused_var, 'X'}}]}}],
+ ?line [] = run(Config, Ts1),
+ ok.
%% Tests that a head mismatch is reported on the correct line (OTP-2125).
head_mismatch_line(Config) when is_list(Config) ->