Skip to content

Commit 5ec9ca5

Browse files
Notify modules diff from compile.erlang (#13904)
1 parent 2ce6cfd commit 5ec9ca5

File tree

6 files changed

+88
-66
lines changed

6 files changed

+88
-66
lines changed

lib/mix/lib/mix/compilers/elixir.ex

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,17 @@ defmodule Mix.Compilers.Elixir do
207207
modules_diff(modules, removed_modules, all_modules, timestamp)
208208
end
209209

210-
unless_previous_warnings_as_errors(
211-
previous_warnings,
212-
opts,
213-
{:ok, all_warnings, lazy_modules_diff}
214-
)
210+
Mix.Task.Compiler.notify_modules_compiled(lazy_modules_diff)
211+
212+
unless_previous_warnings_as_errors(previous_warnings, opts, {:ok, all_warnings})
215213

216214
{:error, errors, %{runtime_warnings: r_warnings, compile_warnings: c_warnings}, state} ->
217215
# In case of errors, we show all previous warnings and all new ones.
218216
{_, _, sources, _, _, _} = state
219217
errors = Enum.map(errors, &diagnostic/1)
220218
warnings = Enum.map(r_warnings ++ c_warnings, &diagnostic/1)
221219
all_warnings = Keyword.get(opts, :all_warnings, errors == [])
222-
{:error, previous_warnings(sources, all_warnings) ++ warnings ++ errors, nil}
220+
{:error, previous_warnings(sources, all_warnings) ++ warnings ++ errors}
223221
after
224222
Code.compiler_options(previous_opts)
225223
end
@@ -257,11 +255,7 @@ defmodule Mix.Compilers.Elixir do
257255
all_warnings = Keyword.get(opts, :all_warnings, true)
258256
previous_warnings = previous_warnings(sources, all_warnings)
259257

260-
unless_previous_warnings_as_errors(
261-
previous_warnings,
262-
opts,
263-
{status, previous_warnings, nil}
264-
)
258+
unless_previous_warnings_as_errors(previous_warnings, opts, {status, previous_warnings})
265259
end
266260
end
267261

@@ -1003,17 +997,13 @@ defmodule Mix.Compilers.Elixir do
1003997
File.rm(manifest <> ".checkpoint")
1004998
end
1005999

1006-
defp unless_previous_warnings_as_errors(
1007-
previous_warnings,
1008-
opts,
1009-
{status, all_warnings, modules_diff}
1010-
) do
1000+
defp unless_previous_warnings_as_errors(previous_warnings, opts, {status, all_warnings}) do
10111001
if previous_warnings != [] and opts[:warnings_as_errors] do
10121002
message = "Compilation failed due to warnings while using the --warnings-as-errors option"
10131003
IO.puts(:stderr, message)
1014-
{:error, all_warnings, modules_diff}
1004+
{:error, all_warnings}
10151005
else
1016-
{status, all_warnings, modules_diff}
1006+
{status, all_warnings}
10171007
end
10181008
end
10191009

lib/mix/lib/mix/compilers/erlang.ex

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ defmodule Mix.Compilers.Erlang do
5454
`{:error, errors, warnings}` in case of error. This function returns
5555
`{status, diagnostics}` as specified in `Mix.Task.Compiler`.
5656
"""
57-
def compile(manifest, mappings, src_ext, dest_ext, opts, callback) when is_list(opts) do
57+
def compile(manifest, mappings, src_ext, dest_ext, opts, callback)
58+
when is_atom(src_ext) and is_atom(dest_ext) and is_list(opts) do
5859
force = opts[:force]
5960

6061
entries =
@@ -66,40 +67,26 @@ defmodule Mix.Compilers.Erlang do
6667
preload.()
6768
end
6869

69-
compile(manifest, entries, src_ext, opts, callback)
70+
compile_entries(manifest, entries, src_ext, dest_ext, opts, callback)
7071
end
7172

72-
@doc """
73-
Compiles the given `entries`.
74-
75-
`entries` are a list of `{:ok | :stale, src, dest}` tuples.
76-
77-
A `manifest` file and a `callback` to be invoked for each stale
78-
src/dest pair must also be given.
79-
80-
## Options
81-
82-
* `:force` - forces compilation regardless of modification times
83-
84-
* `:parallel` - a mapset of files to compile in parallel
85-
86-
"""
73+
# TODO: remove me on v1.22
74+
@deprecated "Use compile/6 or open an up an issue"
8775
def compile(manifest, entries, opts \\ [], callback) do
88-
compile(manifest, entries, :erl, opts, callback)
76+
compile_entries(manifest, entries, :erl, :beam, opts, callback)
8977
end
9078

91-
defp compile(manifest, mappings, ext, opts, callback) do
79+
@doc false
80+
def compile_entries(manifest, mappings, src_ext, dest_ext, opts, callback) do
9281
stale = for {:stale, src, dest} <- mappings, do: {src, dest}
9382

9483
# Get the previous entries from the manifest
9584
timestamp = System.os_time(:second)
96-
entries = read_manifest(manifest)
85+
old_entries = entries = read_manifest(manifest)
9786

9887
# Files to remove are the ones in the manifest but they no longer have a source
9988
removed =
100-
entries
101-
|> Enum.filter(fn {dest, _} -> not List.keymember?(mappings, dest, 2) end)
102-
|> Enum.map(&elem(&1, 0))
89+
for {dest, _} <- entries, not List.keymember?(mappings, dest, 2), do: dest
10390

10491
# Remove manifest entries with no source
10592
Enum.each(removed, &File.rm/1)
@@ -116,7 +103,7 @@ defmodule Mix.Compilers.Erlang do
116103
if stale == [] and removed == [] do
117104
{:noop, manifest_warnings(entries)}
118105
else
119-
Mix.Utils.compiling_n(length(stale), ext)
106+
Mix.Utils.compiling_n(length(stale), src_ext)
120107
Mix.Project.ensure_structure()
121108

122109
# Let's prepend the newly created path so compiled files
@@ -151,6 +138,19 @@ defmodule Mix.Compilers.Erlang do
151138
# Return status and diagnostics
152139
warnings = manifest_warnings(entries) ++ to_diagnostics(warnings, :warning)
153140

141+
if dest_ext == :beam do
142+
lazy_modules_diff = fn ->
143+
{changed, added} =
144+
stale
145+
|> Enum.map(&elem(&1, 1))
146+
|> Enum.split_with(fn dest -> List.keymember?(old_entries, dest, 0) end)
147+
148+
modules_diff(added, changed, removed, timestamp)
149+
end
150+
151+
Mix.Task.Compiler.notify_modules_compiled(lazy_modules_diff)
152+
end
153+
154154
case status do
155155
:ok ->
156156
{:ok, warnings}
@@ -320,4 +320,21 @@ defmodule Mix.Compilers.Erlang do
320320
defp location_to_string({line, column}), do: "#{line}:#{column}:"
321321
defp location_to_string(0), do: ""
322322
defp location_to_string(line), do: "#{line}:"
323+
324+
defp modules_diff(added, changed, removed, timestamp) do
325+
%{
326+
added: modules_from_paths(added),
327+
changed: modules_from_paths(changed),
328+
removed: modules_from_paths(removed),
329+
timestamp: timestamp
330+
}
331+
end
332+
333+
defp modules_from_paths(paths) do
334+
Enum.map(paths, &module_from_path/1)
335+
end
336+
337+
defp module_from_path(path) do
338+
path |> Path.basename() |> Path.rootname() |> String.to_atom()
339+
end
323340
end

lib/mix/lib/mix/tasks/compile.elixir.ex

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,15 @@ defmodule Mix.Tasks.Compile.Elixir do
127127

128128
with_logger_app(project, fn ->
129129
Mix.Project.with_build_lock(project, fn ->
130-
{status, warnings, lazy_modules_diff} =
131-
Mix.Compilers.Elixir.compile(
132-
manifest,
133-
srcs,
134-
dest,
135-
cache_key,
136-
Mix.Tasks.Compile.Erlang.manifests(),
137-
Mix.Tasks.Compile.Erlang.modules(),
138-
opts
139-
)
140-
141-
if lazy_modules_diff do
142-
Mix.Task.Compiler.notify_modules_compiled(lazy_modules_diff)
143-
end
144-
145-
{status, warnings}
130+
Mix.Compilers.Elixir.compile(
131+
manifest,
132+
srcs,
133+
dest,
134+
cache_key,
135+
Mix.Tasks.Compile.Erlang.manifests(),
136+
Mix.Tasks.Compile.Erlang.modules(),
137+
opts
138+
)
146139
end)
147140
end)
148141
end

lib/mix/lib/mix/tasks/compile.erlang.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ defmodule Mix.Tasks.Compile.Erlang do
8484

8585
opts = [parallel: MapSet.new(find_parallel(erls))] ++ opts
8686

87-
Erlang.compile(manifest(), tuples, opts, fn input, _output ->
87+
Erlang.compile_entries(manifest(), tuples, :erl, :beam, opts, fn input, _output ->
8888
# We're purging the module because a previous compiler (for example, Phoenix)
8989
# might have already loaded the previous version of it.
9090
module = input |> Path.basename(".erl") |> String.to_atom()

lib/mix/test/mix/sync/pubsub_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,16 @@ defmodule Mix.Sync.PubSubTest do
7575
%{event: "event1"}
7676
end
7777

78-
PubSub.broadcast(@pubsub_key, lazy_message)
78+
PubSub.broadcast([@pubsub_key, "lazy"], lazy_message)
7979

80-
PubSub.subscribe(@pubsub_key)
80+
PubSub.subscribe([@pubsub_key, "lazy"])
8181

8282
lazy_message = fn ->
8383
send(self(), :lazy2)
8484
%{event: "event2"}
8585
end
8686

87-
PubSub.broadcast(@pubsub_key, lazy_message)
87+
PubSub.broadcast([@pubsub_key, "lazy"], lazy_message)
8888

8989
refute_received :lazy1
9090
assert_received :lazy2

lib/mix/test/mix/tasks/compile_test.exs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ defmodule Mix.Tasks.CompileTest do
415415
File.write!("lib/b.ex", "defmodule B do end")
416416
File.write!("lib/c.ex", "defmodule C do end")
417417

418+
File.mkdir_p!("src")
419+
420+
File.write!("src/a.erl", "-module(a).")
421+
File.write!("src/b.erl", "-module(b).")
422+
File.write!("src/c.erl", "-module(c).")
423+
418424
mix(["deps.compile"])
419425

420426
parent = self()
@@ -433,8 +439,9 @@ defmodule Mix.Tasks.CompileTest do
433439
assert_receive {^port, {:data, "ok\n"}}, timeout
434440
send(parent, :mix_started)
435441

436-
assert_receive {^port, {:data, output}}, timeout
437-
send(parent, {:output, output})
442+
assert_receive {^port, {:data, output_erl}}, timeout
443+
assert_receive {^port, {:data, output_ex}}, timeout
444+
send(parent, {:output, output_erl <> output_ex})
438445
end)
439446

440447
assert_receive :mix_started, timeout
@@ -445,6 +452,11 @@ defmodule Mix.Tasks.CompileTest do
445452
assert_receive {:output, output}, timeout
446453

447454
assert output == """
455+
Received :modules_compiled with
456+
added: [:a, :b, :c], changed: [], removed: []
457+
app: :with_reloader
458+
build_scm: Mix.SCM.Path
459+
os_pid: "#{os_pid}"
448460
Received :modules_compiled with
449461
added: [A, B, C], changed: [], removed: []
450462
app: :with_reloader
@@ -454,10 +466,14 @@ defmodule Mix.Tasks.CompileTest do
454466

455467
# Changed
456468
File.write!("lib/a.ex", "defmodule A do @moduledoc false end")
469+
File.write!("src/a.erl", "-module(a). -export([a/0]). a() -> ok.")
470+
File.touch!("src/a.erl", System.os_time(:second) + 10)
457471
# Removed
458472
File.rm!("lib/b.ex")
473+
File.rm!("src/b.erl")
459474
# New
460475
File.write!("lib/d.ex", "defmodule D do end")
476+
File.write!("src/d.erl", "-module(d).")
461477

462478
spawn_link(fn ->
463479
port =
@@ -473,8 +489,9 @@ defmodule Mix.Tasks.CompileTest do
473489
assert_receive {^port, {:data, "ok\n"}}, timeout
474490
send(parent, :mix_started)
475491

476-
assert_receive {^port, {:data, output}}, timeout
477-
send(parent, {:output, output})
492+
assert_receive {^port, {:data, output_erl}}, timeout
493+
assert_receive {^port, {:data, output_ex}}, timeout
494+
send(parent, {:output, output_erl <> output_ex})
478495
end)
479496

480497
assert_receive :mix_started, timeout
@@ -485,6 +502,11 @@ defmodule Mix.Tasks.CompileTest do
485502
assert_receive {:output, output}, timeout
486503

487504
assert output == """
505+
Received :modules_compiled with
506+
added: [:d], changed: [:a], removed: [:b]
507+
app: :with_reloader
508+
build_scm: Mix.SCM.Path
509+
os_pid: "#{os_pid}"
488510
Received :modules_compiled with
489511
added: [D], changed: [A], removed: [B]
490512
app: :with_reloader

0 commit comments

Comments
 (0)