Skip to content

Commit def65ab

Browse files
committed
Do not store anonymous functions in cache
1 parent dc8cfcd commit def65ab

File tree

1 file changed

+55
-63
lines changed

1 file changed

+55
-63
lines changed

lib/mix/lib/mix/tasks/format.ex

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,64 @@ defmodule Mix.Tasks.Format do
233233
{formatter_opts_and_subs, _sources} =
234234
eval_deps_and_subdirectories(cwd, dot_formatter, formatter_opts, [dot_formatter])
235235

236+
formatter_opts_and_subs = load_plugins(formatter_opts_and_subs)
237+
236238
args
237239
|> expand_args(cwd, dot_formatter, formatter_opts_and_subs, opts)
238240
|> Task.async_stream(&format_file(&1, opts), ordered: false, timeout: :infinity)
239241
|> Enum.reduce({[], []}, &collect_status/2)
240242
|> check!(opts)
241243
end
242244

245+
defp load_plugins({formatter_opts, subs}) do
246+
plugins = Keyword.get(formatter_opts, :plugins, [])
247+
248+
if not is_list(plugins) do
249+
Mix.raise("Expected :plugins to return a list of directories, got: #{inspect(plugins)}")
250+
end
251+
252+
if plugins != [] do
253+
Mix.Task.run("loadpaths", [])
254+
end
255+
256+
if not Enum.all?(plugins, &Code.ensure_loaded?/1) do
257+
Mix.Task.run("compile", [])
258+
end
259+
260+
for plugin <- plugins do
261+
cond do
262+
not Code.ensure_loaded?(plugin) ->
263+
Mix.raise("Formatter plugin #{inspect(plugin)} cannot be found")
264+
265+
not function_exported?(plugin, :features, 1) ->
266+
Mix.raise("Formatter plugin #{inspect(plugin)} does not define features/1")
267+
268+
true ->
269+
:ok
270+
end
271+
end
272+
273+
sigils =
274+
for plugin <- plugins,
275+
sigil <- find_sigils_from_plugins(plugin, formatter_opts),
276+
do: {sigil, plugin}
277+
278+
sigils =
279+
sigils
280+
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
281+
|> Enum.map(fn {sigil, plugins} ->
282+
{sigil,
283+
fn input, opts ->
284+
Enum.reduce(plugins, input, fn plugin, input ->
285+
plugin.format(input, opts ++ formatter_opts)
286+
end)
287+
end}
288+
end)
289+
290+
{Keyword.put(formatter_opts, :sigils, sigils),
291+
Enum.map(subs, fn {path, opts} -> {path, load_plugins(opts)} end)}
292+
end
293+
243294
@doc """
244295
Returns a formatter function and the formatter options to
245296
be used for the given file.
@@ -289,7 +340,6 @@ defmodule Mix.Tasks.Format do
289340
defp eval_deps_and_subdirectories(cwd, dot_formatter, formatter_opts, sources) do
290341
deps = Keyword.get(formatter_opts, :import_deps, [])
291342
subs = Keyword.get(formatter_opts, :subdirectories, [])
292-
plugins = Keyword.get(formatter_opts, :plugins, [])
293343

294344
if not is_list(deps) do
295345
Mix.raise("Expected :import_deps to return a list of dependencies, got: #{inspect(deps)}")
@@ -299,65 +349,17 @@ defmodule Mix.Tasks.Format do
299349
Mix.raise("Expected :subdirectories to return a list of directories, got: #{inspect(subs)}")
300350
end
301351

302-
if not is_list(plugins) do
303-
Mix.raise("Expected :plugins to return a list of modules, got: #{inspect(plugins)}")
304-
end
305-
306-
maybe_load_and_compile_plugins(plugins)
307-
308-
for plugin <- plugins do
309-
cond do
310-
not Code.ensure_loaded?(plugin) ->
311-
Mix.raise("Formatter plugin #{inspect(plugin)} cannot be found")
312-
313-
not function_exported?(plugin, :features, 1) ->
314-
Mix.raise("Formatter plugin #{inspect(plugin)} does not define features/1")
315-
316-
true ->
317-
:ok
318-
end
319-
end
320-
321-
sigils =
322-
for plugin <- plugins,
323-
sigil <- find_sigils_from_plugins(plugin, formatter_opts),
324-
do: {sigil, plugin}
325-
326-
sigils =
327-
sigils
328-
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
329-
|> Enum.map(fn {sigil, plugins} ->
330-
{sigil,
331-
fn input, opts ->
332-
Enum.reduce(plugins, input, fn plugin, input ->
333-
plugin.format(input, opts ++ formatter_opts)
334-
end)
335-
end}
336-
end)
337-
338-
formatter_opts =
339-
formatter_opts
340-
|> Keyword.put(:plugins, plugins)
341-
|> Keyword.put(:sigils, sigils)
342-
343352
if deps == [] and subs == [] do
344353
{{formatter_opts, []}, sources}
345354
else
346355
manifest = Path.join(Mix.Project.manifest_path(), @manifest)
347356

348-
{cached?, {{locals_without_parens, subdirectories}, sources}} =
357+
{{locals_without_parens, subdirectories}, sources} =
349358
maybe_cache_in_manifest(dot_formatter, manifest, fn ->
350359
{subdirectories, sources} = eval_subs_opts(subs, cwd, sources)
351360
{{eval_deps_opts(deps), subdirectories}, sources}
352361
end)
353362

354-
# If we read from cache, we may still need to load and compile plugins.
355-
if cached? do
356-
Enum.each(subdirectories, fn {_path, {opts, _deps}} ->
357-
maybe_load_and_compile_plugins(Keyword.get(opts, :plugins, []))
358-
end)
359-
end
360-
361363
formatter_opts =
362364
Keyword.update(
363365
formatter_opts,
@@ -370,21 +372,11 @@ defmodule Mix.Tasks.Format do
370372
end
371373
end
372374

373-
defp maybe_load_and_compile_plugins(plugins) do
374-
if plugins != [] do
375-
Mix.Task.run("loadpaths", [])
376-
end
377-
378-
if not Enum.all?(plugins, &Code.ensure_loaded?/1) do
379-
Mix.Task.run("compile", [])
380-
end
381-
end
382-
383375
defp maybe_cache_in_manifest(dot_formatter, manifest, fun) do
384376
cond do
385-
is_nil(Mix.Project.get()) or dot_formatter != ".formatter.exs" -> {false, fun.()}
386-
entry = read_manifest(manifest) -> {true, entry}
387-
true -> {false, write_manifest!(manifest, fun.())}
377+
is_nil(Mix.Project.get()) or dot_formatter != ".formatter.exs" -> fun.()
378+
entry = read_manifest(manifest) -> entry
379+
true -> write_manifest!(manifest, fun.())
388380
end
389381
end
390382

0 commit comments

Comments
 (0)