Skip to content

Commit aec930c

Browse files
committed
Use a map to track Mix compiler state
1 parent c6d3e48 commit aec930c

File tree

1 file changed

+70
-39
lines changed

1 file changed

+70
-39
lines changed

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

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ defmodule Mix.Compilers.Elixir do
159159

160160
stale = changed -- removed
161161

162-
{sources, removed_modules} =
162+
{sources, stale_exports} =
163163
update_stale_sources(sources, stale, removed_modules, sources_stats)
164164

165165
consolidation_status =
@@ -186,12 +186,26 @@ defmodule Mix.Compilers.Elixir do
186186

187187
try do
188188
consolidation = {consolidation_status, old_protocols_and_impls, protocols_and_impls}
189-
state = {%{}, exports, sources, [], modules, removed_modules, consolidation}
189+
190+
state = %{
191+
modules: %{},
192+
exports: exports,
193+
sources: sources,
194+
changed: [],
195+
pending_modules: modules,
196+
stale_exports: stale_exports,
197+
consolidation: consolidation
198+
}
199+
190200
compiler_loop(stale, stale_modules, dest, timestamp, opts, state)
191201
else
192202
{:ok, %{runtime_warnings: runtime_warnings, compile_warnings: compile_warnings}, state} ->
193-
{modules, _exports, sources, _changed, pending_modules, _stale_exports,
194-
protocols_and_impls} = state
203+
%{
204+
modules: modules,
205+
sources: sources,
206+
pending_modules: pending_modules,
207+
consolidation: protocols_and_impls
208+
} = state
195209

196210
previous_warnings =
197211
if Keyword.get(opts, :all_warnings, true),
@@ -233,11 +247,10 @@ defmodule Mix.Compilers.Elixir do
233247
else: {errors, r_warnings ++ c_warnings}
234248

235249
# In case of errors, we show all previous warnings and all new ones.
236-
{_, _, sources, _, _, _, _} = state
237250
errors = Enum.map(errors, &diagnostic/1)
238251
warnings = Enum.map(warnings, &diagnostic/1)
239252
all_warnings = Keyword.get(opts, :all_warnings, errors == [])
240-
{:error, previous_warnings(sources, all_warnings) ++ warnings ++ errors}
253+
{:error, previous_warnings(state.sources, all_warnings) ++ warnings ++ errors}
241254
after
242255
Code.compiler_options(previous_opts)
243256
end
@@ -1012,7 +1025,7 @@ defmodule Mix.Compilers.Elixir do
10121025
spawn_link(fn ->
10131026
compile_opts = [
10141027
after_compile: fn ->
1015-
compiler_call(parent, ref, {:after_compile, opts})
1028+
compiler_call(parent, ref, {:after_compile, dest, opts})
10161029
end,
10171030
each_cycle: fn ->
10181031
compiler_call(parent, ref, {:each_cycle, stale_modules, dest, timestamp})
@@ -1060,8 +1073,8 @@ defmodule Mix.Compilers.Elixir do
10601073

10611074
defp compiler_loop(ref, pid, state, cwd) do
10621075
receive do
1063-
{^ref, {:after_compile, opts}} ->
1064-
{response, state} = after_compile(state, opts)
1076+
{^ref, {:after_compile, dest, opts}} ->
1077+
{response, state} = after_compile(dest, state, opts)
10651078
send(pid, {ref, response})
10661079
compiler_loop(ref, pid, state, cwd)
10671080

@@ -1098,21 +1111,39 @@ defmodule Mix.Compilers.Elixir do
10981111
end
10991112
end
11001113

1101-
defp after_compile(state, opts) do
1102-
{modules, exports, sources, changed, pending_modules, stale_exports, consolidation} = state
1103-
1104-
state =
1105-
{modules, exports, sources, changed, pending_modules, stale_exports,
1106-
maybe_consolidate(consolidation, modules, pending_modules, opts)}
1107-
1108-
{:ok, state}
1114+
defp after_compile(_dest, state, opts) do
1115+
%{modules: modules, pending_modules: pending_modules, consolidation: consolidation} = state
1116+
consolidation = maybe_consolidate(consolidation, modules, pending_modules, opts)
1117+
{:ok, %{state | consolidation: consolidation}}
11091118
end
11101119

1111-
defp each_cycle(stale_modules, compile_path, timestamp, state) do
1112-
{modules, _exports, sources, changed, pending_modules, stale_exports, consolidation} = state
1113-
1120+
defp each_cycle(stale_modules, dest, timestamp, state) do
1121+
%{
1122+
modules: modules,
1123+
sources: sources,
1124+
changed: changed,
1125+
pending_modules: pending_modules,
1126+
stale_exports: stale_exports
1127+
} = state
1128+
1129+
# At this point, we may have additional files to compile.
1130+
# There are two potential sources:
1131+
#
1132+
# * We need to go through all exports that we have confirmed that changed.
1133+
# When we first compile, we store all removed/changed modules as stale
1134+
# exports. Then, if they are not compiled again, or compiled with a
1135+
# different exports MD5, they remain as stale, causing the next cycle.
1136+
#
1137+
# * In case a module is defined in two places, we add all sources to changed
11141138
{pending_modules, exports, changed} =
1115-
update_stale_entries(pending_modules, sources, changed, %{}, stale_exports, compile_path)
1139+
update_stale_entries(pending_modules, sources, changed, %{}, stale_exports, dest)
1140+
1141+
state = %{
1142+
state
1143+
| changed: [],
1144+
exports: exports,
1145+
pending_modules: pending_modules
1146+
}
11161147

11171148
# Those files have been changed transitively, so we mark them as changed
11181149
# in case compilation fails mid-cycle. The combination of the outdated
@@ -1152,36 +1183,30 @@ defmodule Mix.Compilers.Elixir do
11521183
end)
11531184

11541185
runtime_paths =
1155-
Enum.map(runtime_modules, &{&1, Path.join(compile_path, Atom.to_string(&1) <> ".beam")})
1186+
Enum.map(runtime_modules, &{&1, Path.join(dest, Atom.to_string(&1) <> ".beam")})
11561187

1157-
state = {modules, exports, sources, [], pending_modules, stale_exports, consolidation}
1188+
state = %{state | sources: sources}
11581189
{{:runtime, runtime_paths, []}, state}
11591190
else
11601191
Mix.Utils.compiling_n(length(changed), :ex)
11611192

1162-
# If we have a compile time dependency to a module, as soon as its file
1163-
# change, we will detect the compile time dependency and recompile. However,
1164-
# the whole goal of pending exports is to delay this decision, so we need to
1165-
# track which modules were removed and start them as our pending exports and
1166-
# remove the pending exports as we notice they have not gone stale.
1167-
{sources, removed_modules} =
1168-
Enum.reduce(changed, {sources, %{}}, fn file, {acc_sources, acc_modules} ->
1193+
# Now we need to detect the new stale_exports.
1194+
# This is a simplified version of update_stale_sources.
1195+
{sources, %{}} =
1196+
Enum.reduce(changed, {sources, stale_exports}, fn file, {acc_sources, acc_modules} ->
11691197
source(size: size, digest: digest, modules: modules) = Map.fetch!(acc_sources, file)
11701198
acc_modules = Enum.reduce(modules, acc_modules, &Map.put(&2, &1, true))
1171-
1172-
# Define empty records for the sources that needs
1173-
# to be recompiled (but were not changed on disk)
11741199
{Map.replace!(acc_sources, file, source(size: size, digest: digest)), acc_modules}
11751200
end)
11761201

1177-
state = {modules, exports, sources, [], pending_modules, removed_modules, consolidation}
1202+
state = %{state | sources: sources, stale_exports: stale_exports}
11781203
{{:compile, changed, []}, state}
11791204
end
11801205
end
11811206

11821207
defp each_file(file, references, verbose, state, cwd) do
11831208
{compile_references, export_references, runtime_references, compile_env} = references
1184-
{modules, exports, sources, changed, pending_modules, stale_exports, consolidation} = state
1209+
%{sources: sources} = state
11851210

11861211
file = Path.relative_to(file, cwd)
11871212

@@ -1208,12 +1233,18 @@ defmodule Mix.Compilers.Elixir do
12081233
compile_env: compile_env
12091234
)
12101235

1211-
sources = Map.replace!(sources, file, source)
1212-
{modules, exports, sources, changed, pending_modules, stale_exports, consolidation}
1236+
%{state | sources: Map.replace!(sources, file, source)}
12131237
end
12141238

12151239
defp each_module(file, module, kind, external, new_export, recompile?, state, timestamp, cwd) do
1216-
{modules, exports, sources, changed, pending_modules, stale_exports, consolidation} = state
1240+
%{
1241+
modules: modules,
1242+
exports: exports,
1243+
sources: sources,
1244+
changed: changed,
1245+
pending_modules: pending_modules,
1246+
stale_exports: stale_exports
1247+
} = state
12171248

12181249
file = Path.relative_to(file, cwd)
12191250
external = process_external_resources(external, cwd)
@@ -1266,7 +1297,7 @@ defmodule Mix.Compilers.Elixir do
12661297
%{} -> changed
12671298
end
12681299

1269-
{modules, exports, sources, changed, pending_modules, stale_exports, consolidation}
1300+
%{state | modules: modules, changed: changed, sources: sources, stale_exports: stale_exports}
12701301
end
12711302

12721303
defp detect_kind(module) do

0 commit comments

Comments
 (0)