77-export ([compile_error /1 , compile_error /3 , parse_error /5 ]).
88-export ([function_error /4 , module_error /4 , file_error /4 ]).
99-export ([erl_warn /3 , file_warn /4 ]).
10- -export ([print_diagnostic /5 , print_diagnostic_no_capture /2 , print_diagnostic_no_capture /4 ]).
10+ -export ([print_diagnostic /1 , emit_diagnostic /5 ]).
11+ -export ([print_warning /1 , print_warning /3 ]).
1112-include (" elixir.hrl" ).
1213-type location () :: non_neg_integer () | {non_neg_integer (), non_neg_integer ()}.
1314
14- % % Low-level warning, should be used only from Erlang passes.
15- -spec erl_warn (location () | none , unicode :chardata (), unicode :chardata ()) -> ok .
16- erl_warn (none , File , Warning ) ->
17- erl_warn (0 , File , Warning );
18- erl_warn (Location , File , Warning ) when is_binary (File ) ->
19- send_diagnostic (warning , Location , File , Warning ),
20- print_diagnostic_no_capture (warning , Location , File , Warning ).
15+ % % Diagnostic API
16+
17+ % % TODO: Remove me on Elixir v2.0.
18+ print_warning (Location , File , Message ) ->
19+ print_warning ([Message , file_format (Location , File ), $\n ]).
20+
21+ % % Used by parallel checker as it groups warnings.
22+ print_warning (Message ) ->
23+ io :put_chars (standard_error , [prefix (warning ), Message , $\n ]).
2124
22- -spec print_diagnostic_no_capture (warning | error , location (), unicode :chardata (), unicode :chardata ()) -> ok .
23- print_diagnostic_no_capture (Type , Location , File , Message ) ->
24- print_diagnostic_no_capture (Type , [Message , " \n " , file_format (Location , File ), $\n ]).
25+ print_diagnostic (#{severity := Severity , message := Message , stacktrace := Stacktrace } = Diagnostic ) ->
26+ Location =
27+ case (Stacktrace =:= []) orelse elixir_config :is_bootstrap () of
28+ true ->
29+ #{position := Position , file := File } = Diagnostic ,
30+ file_format (Position , File );
2531
26- -spec print_diagnostic_no_capture (warning | error , unicode :chardata ()) -> ok .
27- print_diagnostic_no_capture (Type , Message ) ->
28- io :put_chars (standard_error , [prefix (Type ), Message , $\n ]),
32+ false ->
33+ [[" \n " , 'Elixir.Exception' :format_stacktrace_entry (E )] || E <- Stacktrace ]
34+ end ,
35+ io :put_chars (standard_error , [prefix (Severity ), Message , Location , " \n\n " ]),
2936 ok .
3037
31- -spec print_diagnostic (warning | error , location (), unicode :chardata () | nil , unicode :chardata (), unicode :chardata ()) -> ok .
32- print_diagnostic (Type , Location , File , DiagMessage , PrintMessage )
33- when is_binary (File ) or (File == nil ) ->
34- send_diagnostic (Type , Location , File , DiagMessage ),
35- print_diagnostic_no_capture (Type , PrintMessage ).
38+ emit_diagnostic (Severity , Position , File , Message , Stacktrace ) ->
39+ Diagnostic = #{
40+ severity => Severity ,
41+ file => if File =:= nil -> nil ; true -> filename :absname (File ) end ,
42+ position => Position ,
43+ message => unicode :characters_to_binary (Message ),
44+ stacktrace => Stacktrace
45+ },
46+
47+ print_diagnostic (Diagnostic ),
48+
49+ case get (elixir_compiler_info ) of
50+ undefined -> ok ;
51+ {CompilerPid , _ } -> CompilerPid ! {diagnostic , Diagnostic }
52+ end ,
53+
54+ ok .
3655
3756% % Compilation error/warn handling.
3857
58+ % % Low-level warning, should be used only from Erlang passes.
59+ -spec erl_warn (location () | none , unicode :chardata (), unicode :chardata ()) -> ok .
60+ erl_warn (none , File , Warning ) ->
61+ erl_warn (0 , File , Warning );
62+ erl_warn (Location , File , Warning ) when is_binary (File ) ->
63+ emit_diagnostic (warning , Location , File , Warning , []).
64+
3965-spec file_warn (list (), binary () | #{file := binary (), _ => _ }, module (), any ()) -> ok .
4066file_warn (Meta , File , Module , Desc ) when is_list (Meta ), is_binary (File ) ->
4167 file_warn (Meta , #{file => File }, Module , Desc );
@@ -44,9 +70,9 @@ file_warn(Meta, E, Module, Desc) when is_list(Meta) ->
4470 case elixir_config :is_bootstrap () of
4571 true -> ok ;
4672 false ->
47- {EnvLine , EnvFile , EnvLocation } = env_format (Meta , E ),
73+ {EnvLine , EnvFile , EnvStacktrace } = env_format (Meta , E ),
4874 Message = Module :format_error (Desc ),
49- print_diagnostic (warning , EnvLine , EnvFile , Message , [ Message , " \n " , EnvLocation , $ \n ] )
75+ emit_diagnostic (warning , EnvLine , EnvFile , Message , EnvStacktrace )
5076 end .
5177
5278-spec file_error (list (), binary () | #{file := binary (), _ => _ }, module (), any ()) -> no_return ().
@@ -77,9 +103,9 @@ function_error(Meta, Env, Module, Desc) ->
77103 file_error (Meta , Env , Module , Desc ).
78104
79105print_error (Meta , Env , Module , Desc ) ->
80- {EnvLine , EnvFile , EnvLocation } = env_format (Meta , Env ),
106+ {EnvLine , EnvFile , EnvStacktrace } = env_format (Meta , Env ),
81107 Message = Module :format_error (Desc ),
82- print_diagnostic (error , EnvLine , EnvFile , Message , [ Message , " \n " , EnvLocation , $ \n ] ),
108+ emit_diagnostic (error , EnvLine , EnvFile , Message , EnvStacktrace ),
83109 ok .
84110
85111% % Compilation error.
@@ -94,11 +120,11 @@ compile_error(#{file := File}) ->
94120
95121-spec compile_error (list (), binary (), binary () | unicode :charlist ()) -> no_return ().
96122compile_error (Meta , File , Message ) when is_binary (Message ) ->
97- MetaLocation = meta_location (Meta , File ),
98- raise ('Elixir.CompileError' , Message , MetaLocation );
123+ { File , Line } = meta_location (Meta , File ),
124+ raise ('Elixir.CompileError' , Message , [{ file , File }, { line , Line }] );
99125compile_error (Meta , File , Message ) when is_list (Message ) ->
100- MetaLocation = meta_location (Meta , File ),
101- raise ('Elixir.CompileError' , elixir_utils :characters_to_binary (Message ), MetaLocation ).
126+ { File , Line } = meta_location (Meta , File ),
127+ raise ('Elixir.CompileError' , elixir_utils :characters_to_binary (Message ), [{ file , File }, { line , Line }] ).
102128
103129% % Tokenization parsing/errors.
104130
@@ -210,21 +236,6 @@ snippet(InputString, Location, StartLine, StartColumn) ->
210236
211237% % Helpers
212238
213- send_diagnostic (Severity , Position , File , Message ) ->
214- case get (elixir_compiler_info ) of
215- undefined -> ok ;
216- {CompilerPid , _ } ->
217- Diagnostic = #{
218- severity => Severity ,
219- file => if File =:= nil -> nil ; true -> filename :absname (File ) end ,
220- position => Position ,
221- message => unicode :characters_to_binary (Message )
222- },
223-
224- CompilerPid ! {diagnostic , Diagnostic }
225- end ,
226- ok .
227-
228239prefix (warning ) ->
229240 case application :get_env (elixir , ansi_enabled , false ) of
230241 true -> <<" \e [33mwarning: \e [0m" >>;
@@ -237,33 +248,35 @@ prefix(error) ->
237248 end .
238249
239250env_format (Meta , #{file := EnvFile } = E ) ->
240- [{ file , File }, { line , Line }] = meta_location (Meta , EnvFile ),
251+ { File , Line } = meta_location (Meta , EnvFile ),
241252
242- Location =
253+ Stacktrace =
243254 case E of
244255 #{function := {Name , Arity }, module := Module } ->
245- [file_format ( Line , File ), " : " , 'Elixir.Exception' : format_mfa ( Module , Name , Arity ) ];
256+ [{ Module , Name , Arity , [{ file , elixir_utils : relative_to_cwd ( File )}, { line , Line }]} ];
246257 #{module := Module } when Module /= nil ->
247- [file_format ( Line , File ), " : " , elixir_aliases : inspect ( Module ) ];
258+ [{ Module , '__MODULE__' , 0 , [{ file , elixir_utils : relative_to_cwd ( File )}, { line , Line }]} ];
248259 #{} ->
249- file_format ( Line , File )
260+ []
250261 end ,
251262
252- {Line , File , Location }.
263+ {Line , File , Stacktrace }.
253264
265+ file_format (_ , nil ) ->
266+ " " ;
254267file_format ({0 , _Column }, File ) ->
255- elixir_utils :relative_to_cwd (File );
268+ [ " \n " , elixir_utils :relative_to_cwd (File )] ;
256269file_format ({Line , Column }, File ) ->
257- io_lib :format (" ~ts :~w :~w " , [elixir_utils :relative_to_cwd (File ), Line , Column ]);
270+ io_lib :format (" \n ~ts :~w :~w " , [elixir_utils :relative_to_cwd (File ), Line , Column ]);
258271file_format (0 , File ) ->
259- elixir_utils :relative_to_cwd (File );
272+ [ " \n " , elixir_utils :relative_to_cwd (File )] ;
260273file_format (Line , File ) ->
261- io_lib :format (" ~ts :~w " , [elixir_utils :relative_to_cwd (File ), Line ]).
274+ io_lib :format (" \n ~ts :~w " , [elixir_utils :relative_to_cwd (File ), Line ]).
262275
263276meta_location (Meta , File ) ->
264277 case elixir_utils :meta_keep (Meta ) of
265- {F , L } -> [{ file , F }, { line , L }] ;
266- nil -> [{ file , File }, { line , ? line (Meta )}]
278+ {F , L } -> { F , L } ;
279+ nil -> { File , ? line (Meta )}
267280 end .
268281
269282raise (Kind , Message , Opts ) when is_binary (Message ) ->
0 commit comments