@@ -5,15 +5,24 @@ defmodule Kernel.ParallelCompiler do
55
66 @ typedoc "The line. 0 indicates no line."
77 @ type line ( ) :: non_neg_integer ( )
8- @ type location ( ) :: line ( ) | { pos_integer ( ) , column :: non_neg_integer }
9- @ type warning ( ) :: { file :: Path . t ( ) , location ( ) , message :: String . t ( ) }
10- @ type error ( ) :: { file :: Path . t ( ) , location ( ) , message :: String . t ( ) }
8+ @ type position ( ) :: line ( ) | { pos_integer ( ) , column :: non_neg_integer }
9+
10+ @ type diagnostic ( severity ) :: % {
11+ file: Path . t ( ) ,
12+ severity: severity ,
13+ message: String . t ( ) ,
14+ position: position
15+ }
1116
1217 @ type info :: % {
13- runtime_warnings: [ warning ] ,
14- compile_warnings: [ warning ]
18+ runtime_warnings: [ diagnostic ( : warning) ] ,
19+ compile_warnings: [ diagnostic ( : warning) ]
1520 }
1621
22+ # Deprecated types
23+ @ type warning ( ) :: { file :: Path . t ( ) , position ( ) , message :: String . t ( ) }
24+ @ type error ( ) :: { file :: Path . t ( ) , position ( ) , message :: String . t ( ) }
25+
1726 @ doc """
1827 Starts a task for parallel compilation.
1928
@@ -62,17 +71,14 @@ defmodule Kernel.ParallelCompiler do
6271
6372 It returns `{:ok, modules, warnings}` or `{:error, errors, warnings}`
6473 by default but we recommend using `return_maps: true` so it returns
65- a map as third element instead of a list of warnings. The map has the
66- shape of:
74+ diagnostics as maps as well as a map of compilation information.
75+ The map has the shape of:
6776
6877 %{
6978 runtime_warnings: [warning],
7079 compile_warnings: [warning]
7180 }
7281
73- Both errors and warnings are a list of three-element tuples containing
74- the file, line and the formatted error/warning.
75-
7682 ## Options
7783
7884 * `:each_file` - for each file compiled, invokes the callback passing the
@@ -109,12 +115,13 @@ defmodule Kernel.ParallelCompiler do
109115 * `:beam_timestamp` - the modification timestamp to give all BEAM files
110116
111117 * `:return_maps` (since v1.15.0) - returns maps with information instead of
112- a list of warnings
118+ a list of warnings and returns diagnostics as maps instead of tuples
113119
114120 """
115121 @ doc since: "1.6.0"
116122 @ spec compile ( [ Path . t ( ) ] , keyword ( ) ) ::
117- { :ok , [ atom ] , [ warning ] | info ( ) } | { :error , [ error ] , [ warning ] | info ( ) }
123+ { :ok , [ atom ] , [ warning ] | info ( ) }
124+ | { :error , [ error ] | [ diagnostic ( :error ) ] , [ warning ] | info ( ) }
118125 def compile ( files , options \\ [ ] ) when is_list ( options ) do
119126 spawn_workers ( files , :compile , options )
120127 end
@@ -126,7 +133,8 @@ defmodule Kernel.ParallelCompiler do
126133 """
127134 @ doc since: "1.6.0"
128135 @ spec compile_to_path ( [ Path . t ( ) ] , Path . t ( ) , keyword ( ) ) ::
129- { :ok , [ atom ] , [ warning ] | info ( ) } | { :error , [ error ] , [ warning ] | info ( ) }
136+ { :ok , [ atom ] , [ warning ] | info ( ) }
137+ | { :error , [ error ] | [ diagnostic ( :error ) ] , [ warning ] | info ( ) }
130138 def compile_to_path ( files , path , options \\ [ ] ) when is_binary ( path ) and is_list ( options ) do
131139 spawn_workers ( files , { :compile , path } , options )
132140 end
@@ -139,17 +147,14 @@ defmodule Kernel.ParallelCompiler do
139147
140148 It returns `{:ok, modules, warnings}` or `{:error, errors, warnings}`
141149 by default but we recommend using `return_maps: true` so it returns
142- a map as third element instead of a list of warnings. The map has the
143- shape of:
150+ diagnostics as maps as well as a map of compilation information.
151+ The map has the shape of:
144152
145153 %{
146154 runtime_warnings: [warning],
147155 compile_warnings: [warning]
148156 }
149157
150- Both errors and warnings are a list of three-element tuples containing
151- the file, line and the formatted error/warning.
152-
153158 ## Options
154159
155160 * `:each_file` - for each file compiled, invokes the callback passing the
@@ -167,12 +172,17 @@ defmodule Kernel.ParallelCompiler do
167172 end
168173
169174 @ doc """
170- Prints a warning returned by the compiler.
175+ Prints a diagnostic returned by the compiler into stderr .
171176 """
172- @ doc since: "1.13.0"
173- @ spec print_warning ( warning ) :: :ok
177+ @ doc since: "1.15.0"
178+ def print_diagnostic ( % { file: file , position: position , message: message , severity: severity } ) do
179+ :elixir_errors . print_diagnostic_no_capture ( severity , position , file , message )
180+ end
181+
182+ @ doc false
183+ # TODO: Deprecate me on Elixir v1.19
174184 def print_warning ( { file , location , warning } ) do
175- :elixir_errors . print_warning_no_diagnostic ( location , file , warning )
185+ :elixir_errors . print_diagnostic_no_capture ( :warning , location , file , warning )
176186 end
177187
178188 @ doc false
@@ -209,7 +219,8 @@ defmodule Kernel.ParallelCompiler do
209219 "Compilation failed due to warnings while using the --warnings-as-errors option"
210220
211221 IO . puts ( :stderr , message )
212- { :error , r_warnings ++ c_warnings , % { info | runtime_warnings: [ ] , compile_warnings: [ ] } }
222+ errors = Enum . map ( r_warnings ++ c_warnings , & Map . replace! ( & 1 , :severity , :error ) )
223+ { :error , errors , % { info | runtime_warnings: [ ] , compile_warnings: [ ] } }
213224
214225 { { :ok , outcome , info } , _ } ->
215226 beam_timestamp = Keyword . get ( options , :beam_timestamp )
@@ -230,7 +241,12 @@ defmodule Kernel.ParallelCompiler do
230241 if Keyword . get ( options , :return_maps , false ) do
231242 { status , modules_or_errors , info }
232243 else
233- { status , modules_or_errors , info . runtime_warnings ++ info . compile_warnings }
244+ to_tuples = & Enum . map ( & 1 , fn diag -> { diag . file , diag . position , diag . message } end )
245+
246+ modules_or_errors =
247+ if status == :ok , do: modules_or_errors , else: to_tuples . ( modules_or_errors )
248+
249+ { status , modules_or_errors , to_tuples . ( info . runtime_warnings ++ info . compile_warnings ) }
234250 end
235251 end
236252
@@ -633,19 +649,13 @@ defmodule Kernel.ParallelCompiler do
633649 state = % { state | timer_ref: timer_ref }
634650 spawn_workers ( queue , spawned , waiting , files , result , warnings , errors , state )
635651
636- { :diagnostic , type , file , location , message } ->
637- file = file && Path . absname ( file )
638- message = :unicode . characters_to_binary ( message )
652+ { :diagnostic , % { severity: :warning } = diagnostic } ->
653+ warnings = [ diagnostic | warnings ]
654+ wait_for_messages ( queue , spawned , waiting , files , result , warnings , errors , state )
639655
640- case type do
641- :warning ->
642- warnings = [ { file , location , message } | warnings ]
643- wait_for_messages ( queue , spawned , waiting , files , result , warnings , errors , state )
644-
645- :error ->
646- errors = [ { file , location , message } | errors ]
647- wait_for_messages ( queue , spawned , waiting , files , result , warnings , errors , state )
648- end
656+ { :diagnostic , % { severity: :error } = diagnostic } ->
657+ errors = [ diagnostic | errors ]
658+ wait_for_messages ( queue , spawned , waiting , files , result , warnings , errors , state )
649659
650660 { :file_ok , child_pid , ref , file , lexical } ->
651661 state . each_file . ( file , lexical )
@@ -816,7 +826,9 @@ defmodule Kernel.ParallelCompiler do
816826 "and that the modules they reference exist and are correctly named\n "
817827 )
818828
819- for { file , _ , description } <- deadlock , do: { Path . absname ( file ) , nil , description }
829+ for { file , _ , description } <- deadlock do
830+ % { severity: :error , file: Path . absname ( file ) , position: nil , message: description }
831+ end
820832 end
821833
822834 defp terminate ( files ) do
@@ -842,7 +854,7 @@ defmodule Kernel.ParallelCompiler do
842854 line = get_line ( file , reason , stack )
843855 file = Path . absname ( file )
844856 message = :unicode . characters_to_binary ( Kernel.CLI . format_error ( kind , reason , stack ) )
845- { file , line || 0 , message }
857+ % { file: file , position: line || 0 , message: message , severity: :error }
846858 end
847859
848860 defp get_line ( _file , % { line: line , column: column } , _stack )
0 commit comments