Skip to content

Commit df5bc5a

Browse files
committed
Ensure yecc is available to emit warnings, closes #12691
1 parent 1ca5d78 commit df5bc5a

File tree

4 files changed

+56
-25
lines changed

4 files changed

+56
-25
lines changed

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

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@ defmodule Mix.Compilers.Erlang do
44
@manifest_vsn 1
55

66
@doc """
7-
Compiles the files in `mappings` with given extensions into
8-
the destination, automatically invoking the callback for each
9-
stale input and output pair (or for all if `force` is `true`) and
10-
removing files that no longer have a source, while keeping the
11-
`manifest` up to date.
7+
Compiles the given `mappings`.
128
13-
`mappings` should be a list of tuples in the form of `{src, dest}` paths.
9+
`mappings` is a list of `{src, dest}` pairs, where the source
10+
extensions are compiled into the destination extension,
11+
automatically invoking the callback for each stale pair (or for
12+
all if `force` is `true`) and removing files that no longer have
13+
a source, while keeping the `manifest` up to date.
1414
1515
## Options
1616
1717
* `:force` - forces compilation regardless of modification times
1818
1919
* `:parallel` - a mapset of files to compile in parallel
2020
21+
* `:preload` - any code that must be preloaded if any pending
22+
entry needs to be compiled
23+
2124
## Examples
2225
2326
For example, a simple compiler for Lisp Flavored Erlang
@@ -54,22 +57,25 @@ defmodule Mix.Compilers.Erlang do
5457
def compile(manifest, mappings, src_ext, dest_ext, opts, callback) when is_list(opts) do
5558
force = opts[:force]
5659

57-
files =
60+
entries =
5861
for {src, dest} <- mappings,
59-
target <- extract_targets(src, src_ext, dest, dest_ext, force),
62+
target <- extract_entries(src, src_ext, dest, dest_ext, force),
6063
do: target
6164

62-
compile(manifest, files, src_ext, opts, callback)
65+
if preload = entries != [] && opts[:preload] do
66+
preload.()
67+
end
68+
69+
compile(manifest, entries, src_ext, opts, callback)
6370
end
6471

6572
@doc """
66-
Compiles the given `mappings`.
73+
Compiles the given `entries`.
6774
68-
`mappings` should be a list of tuples in the form of `{src, dest}`.
75+
`entries` are a list of `{:ok | :stale, src, dest}` tuples.
6976
70-
A `manifest` file and a `callback` to be invoked for each src/dest pair
71-
must be given. A src/dest pair where destination is `nil` is considered
72-
to be up to date and won't be (re-)compiled.
77+
A `manifest` file and a `callback` to be invoked for each stale
78+
src/dest pair must also be given.
7379
7480
## Options
7581
@@ -78,8 +84,8 @@ defmodule Mix.Compilers.Erlang do
7884
* `:parallel` - a mapset of files to compile in parallel
7985
8086
"""
81-
def compile(manifest, mappings, opts \\ [], callback) do
82-
compile(manifest, mappings, :erl, opts, callback)
87+
def compile(manifest, entries, opts \\ [], callback) do
88+
compile(manifest, entries, :erl, opts, callback)
8389
end
8490

8591
defp compile(manifest, mappings, ext, opts, callback) do
@@ -102,7 +108,7 @@ defmodule Mix.Compilers.Erlang do
102108
# Clear stale and removed files from manifest
103109
entries =
104110
Enum.reject(entries, fn {dest, _warnings} ->
105-
dest in removed || Enum.any?(stale, fn {_, stale_dest} -> dest == stale_dest end)
111+
dest in removed || List.keymember?(stale, dest, 1)
106112
end)
107113

108114
if Keyword.get(opts, :all_warnings, true), do: show_warnings(entries)
@@ -156,9 +162,8 @@ defmodule Mix.Compilers.Erlang do
156162
end
157163
end
158164

159-
@doc """
160-
Ensures the native OTP application is available.
161-
"""
165+
# TODO: Deprecate this in favor of `Mix.ensure_application!/1` in Elixir v1.19.
166+
@doc false
162167
def ensure_application!(app, _input) do
163168
Mix.ensure_application!(app)
164169
{:ok, _} = Application.ensure_all_started(app)
@@ -202,7 +207,7 @@ defmodule Mix.Compilers.Erlang do
202207
manifest |> read_manifest() |> Enum.map(&elem(&1, 0))
203208
end
204209

205-
defp extract_targets(src_dir, src_ext, dest_dir, dest_ext, force) do
210+
defp extract_entries(src_dir, src_ext, dest_dir, dest_ext, force) do
206211
files = Mix.Utils.extract_files(List.wrap(src_dir), List.wrap(src_ext))
207212

208213
for file <- files do

lib/mix/lib/mix/tasks/compile.leex.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@ defmodule Mix.Tasks.Compile.Leex do
5353
Mix.raise(":leex_options should be a list of options, got: #{inspect(options)}")
5454
end
5555

56-
opts = [parallel: true] ++ opts
56+
opts = [parallel: true, preload: &preload/0] ++ opts
5757

5858
Erlang.compile(manifest(), mappings, :xrl, :erl, opts, fn input, output ->
59-
Erlang.ensure_application!(:parsetools, input)
6059
options = options ++ @forced_opts ++ [scannerfile: Erlang.to_erl_file(output)]
6160
:leex.file(Erlang.to_erl_file(input), options)
6261
end)
6362
end
6463

64+
defp preload do
65+
Mix.ensure_application!(:parsetools)
66+
{:ok, _} = Application.ensure_all_started(:parsetools)
67+
end
68+
6569
@impl true
6670
def manifests, do: [manifest()]
6771
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)

lib/mix/lib/mix/tasks/compile.yecc.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@ defmodule Mix.Tasks.Compile.Yecc do
5353
Mix.raise(":yecc_options should be a list of options, got: #{inspect(options)}")
5454
end
5555

56-
opts = [parallel: true] ++ opts
56+
opts = [parallel: true, preload: &preload/0] ++ opts
5757

5858
Erlang.compile(manifest(), mappings, :yrl, :erl, opts, fn input, output ->
59-
Erlang.ensure_application!(:parsetools, input)
6059
options = options ++ @forced_opts ++ [parserfile: Erlang.to_erl_file(output)]
6160
:yecc.file(Erlang.to_erl_file(input), options)
6261
end)
6362
end
6463

64+
defp preload do
65+
Mix.ensure_application!(:parsetools)
66+
{:ok, _} = Application.ensure_all_started(:parsetools)
67+
end
68+
6569
@impl true
6670
def manifests, do: [manifest()]
6771
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)

lib/mix/test/mix/tasks/compile.yecc_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ defmodule Mix.Tasks.Compile.YeccTest do
6060
severity: :warning
6161
} = diagnostic
6262
end)
63+
64+
# Removing parse tools re-add it later even if only to show warnings
65+
:code.del_path(:parsetools)
66+
:code.delete(:yecc)
67+
:code.purge(:yecc)
68+
refute Code.ensure_loaded?(:yecc)
69+
70+
capture_io(fn ->
71+
assert {:noop, [diagnostic]} = Mix.Tasks.Compile.Yecc.run([])
72+
73+
assert %Mix.Task.Compiler.Diagnostic{
74+
compiler_name: "yecc",
75+
file: ^file,
76+
message: "conflicts: 1 shift/reduce, 0 reduce/reduce",
77+
position: 0,
78+
severity: :warning
79+
} = diagnostic
80+
end)
6381
end)
6482
end
6583

0 commit comments

Comments
 (0)