Skip to content

Commit 9c42348

Browse files
Add API for fetching all persisted compiler diagnostics (#13907)
1 parent fa2a49f commit 9c42348

File tree

11 files changed

+105
-43
lines changed

11 files changed

+105
-43
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ defmodule Mix.Compilers.Elixir do
324324
end
325325
end
326326

327+
@doc """
328+
Retrieves all diagnostics from the given manifest.
329+
"""
330+
def diagnostics(manifest, dest) do
331+
{_, all_sources, _, _, _, _, _, _} = parse_manifest(manifest, dest)
332+
previous_warnings(all_sources, false)
333+
end
334+
327335
defp compiler_info_from_force(manifest, all_paths, all_modules, dest) do
328336
# A config, path dependency or manifest has changed, let's just compile everything
329337
for {module, _} <- all_modules,

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ defmodule Mix.Compilers.Erlang do
207207
manifest |> read_manifest() |> Enum.map(&elem(&1, 0))
208208
end
209209

210+
@doc """
211+
Retrieves all diagnostics from the given manifest.
212+
"""
213+
def diagnostics(manifest) do
214+
entries = read_manifest(manifest)
215+
manifest_warnings(entries)
216+
end
217+
210218
defp extract_entries(src_dir, src_ext, dest_dir, dest_ext, force) do
211219
files = Mix.Utils.extract_files(List.wrap(src_dir), List.wrap(src_ext))
212220

lib/mix/lib/mix/task.compiler.ex

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,17 @@ defmodule Mix.Task.Compiler do
162162
"""
163163
@callback manifests() :: [Path.t()]
164164

165+
@doc """
166+
Lists persisted diagnostics from the compiler.
167+
"""
168+
@callback diagnostics() :: [Diagnostic.t()]
169+
165170
@doc """
166171
Removes build artifacts and manifests.
167172
"""
168173
@callback clean() :: any
169174

170-
@optional_callbacks clean: 0, manifests: 0
175+
@optional_callbacks clean: 0, manifests: 0, diagnostics: 0
171176

172177
@doc """
173178
Adds a callback that runs after a given compiler.
@@ -199,6 +204,63 @@ defmodule Mix.Task.Compiler do
199204
end
200205
end
201206

207+
@doc """
208+
Returns all compilers for the current project.
209+
"""
210+
def compilers(config \\ Mix.Project.config()) do
211+
compilers = config[:compilers] || Mix.compilers()
212+
213+
if :xref in compilers do
214+
IO.warn(
215+
"the :xref compiler is deprecated, please remove it from your mix.exs :compilers options"
216+
)
217+
218+
List.delete(compilers, :xref)
219+
else
220+
compilers
221+
end
222+
|> maybe_prepend(:leex)
223+
|> maybe_prepend(:yecc)
224+
end
225+
226+
defp maybe_prepend(compilers, compiler) do
227+
if compiler in compilers do
228+
compilers
229+
else
230+
[compiler | compilers]
231+
end
232+
end
233+
234+
@doc """
235+
Lists manifest files for all compilers in the current project.
236+
"""
237+
def manifests(config \\ Mix.Project.config()) do
238+
Enum.flat_map(compilers(config), fn compiler ->
239+
module = Mix.Task.get("compile.#{compiler}")
240+
241+
if module && function_exported?(module, :manifests, 0) do
242+
module.manifests()
243+
else
244+
[]
245+
end
246+
end)
247+
end
248+
249+
@doc """
250+
Lists persisted diagnostics from all compilers in the current project.
251+
"""
252+
def diagnostics(config \\ Mix.Project.config()) do
253+
Enum.flat_map(compilers(config), fn compiler ->
254+
module = Mix.Task.get("compile.#{compiler}")
255+
256+
if module && function_exported?(module, :diagnostics, 0) do
257+
module.diagnostics()
258+
else
259+
[]
260+
end
261+
end)
262+
end
263+
202264
# Normalize the compiler result to a diagnostic tuple.
203265
@doc false
204266
def normalize(result, name) do

lib/mix/lib/mix/tasks/clean.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ defmodule Mix.Tasks.Clean do
3939
# First, we get the tasks. After that, we clean them.
4040
# This is to avoid a task cleaning a compiler module.
4141
tasks =
42-
for compiler <- [:protocols] ++ Mix.Tasks.Compile.compilers(),
42+
for compiler <- [:protocols] ++ Mix.Task.Compiler.compilers(),
4343
module = Mix.Task.get("compile.#{compiler}"),
4444
function_exported?(module, :clean, 0),
4545
do: module

lib/mix/lib/mix/tasks/compile.all.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ defmodule Mix.Tasks.Compile.All do
6767
Mix.Project.build_structure(config)
6868

6969
config
70-
|> Mix.Tasks.Compile.compilers()
70+
|> Mix.Task.Compiler.compilers()
7171
|> compile(args, :noop, [])
7272
end
7373

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ defmodule Mix.Tasks.Compile.Elixir do
144144
def manifests, do: [manifest()]
145145
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)
146146

147+
@impl true
148+
def diagnostics do
149+
dest = Mix.Project.compile_path()
150+
Mix.Compilers.Elixir.diagnostics(manifest(), dest)
151+
end
152+
147153
@impl true
148154
def clean do
149155
dest = Mix.Project.compile_path()

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ defmodule Mix.Tasks.Compile.Erlang do
111111
def manifests, do: [manifest()]
112112
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)
113113

114+
@impl true
115+
def diagnostics do
116+
Mix.Compilers.Erlang.diagnostics(manifest())
117+
end
118+
114119
@impl true
115120
def clean do
116121
Mix.Compilers.Erlang.clean(manifest())

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

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
defmodule Mix.Tasks.Compile do
2-
use Mix.Task.Compiler
2+
use Mix.Task
33

44
@shortdoc "Compiles source files"
55

@@ -42,6 +42,7 @@ defmodule Mix.Tasks.Compile do
4242
the paths set by the code loader from the `ERL_LIBS` environment as
4343
well as explicitly listed by providing `-pa` and `-pz` options
4444
to Erlang.
45+
4546
## Compilers
4647
4748
To see documentation for each specific compiler, you must
@@ -79,32 +80,8 @@ defmodule Mix.Tasks.Compile do
7980
8081
"""
8182

82-
@doc """
83-
Returns all compilers for the current project.
84-
"""
85-
def compilers(config \\ Mix.Project.config()) do
86-
compilers = config[:compilers] || Mix.compilers()
87-
88-
if :xref in compilers do
89-
IO.warn(
90-
"the :xref compiler is deprecated, please remove it from your mix.exs :compilers options"
91-
)
92-
93-
List.delete(compilers, :xref)
94-
else
95-
compilers
96-
end
97-
|> maybe_prepend(:leex)
98-
|> maybe_prepend(:yecc)
99-
end
100-
101-
defp maybe_prepend(compilers, compiler) do
102-
if compiler in compilers do
103-
compilers
104-
else
105-
[compiler | compilers]
106-
end
107-
end
83+
@deprecated "Use Mix.Task.Compiler.compilers/1 instead"
84+
defdelegate compilers(config \\ Mix.Project.config()), to: Mix.Task.Compiler
10885

10986
@impl true
11087
def run(["--list"]) do
@@ -228,18 +205,8 @@ defmodule Mix.Tasks.Compile do
228205
end
229206
end
230207

231-
@impl true
232-
def manifests do
233-
Enum.flat_map(compilers(), fn compiler ->
234-
module = Mix.Task.get("compile.#{compiler}")
235-
236-
if module && function_exported?(module, :manifests, 0) do
237-
module.manifests()
238-
else
239-
[]
240-
end
241-
end)
242-
end
208+
@deprecated "Use Mix.Task.Compiler.manifests/0 instead"
209+
defdelegate manifests, to: Mix.Task.Compiler
243210

244211
## Consolidation handling
245212

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,9 @@ defmodule Mix.Tasks.Compile.ElixirTest do
14691469
compiler_name: "Elixir",
14701470
message: ^message
14711471
} = diagnostic
1472+
1473+
assert [^diagnostic] = Mix.Tasks.Compile.Elixir.diagnostics()
1474+
assert [^diagnostic] = Mix.Task.Compiler.diagnostics()
14721475
end)
14731476
end)
14741477
end

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ defmodule Mix.Tasks.Compile.ErlangTest do
132132
assert {:noop, [^diagnostic]} = Mix.Tasks.Compile.Erlang.run(["--verbose"])
133133
refute_received {:mix_shell, :info, ["Compiled src/has_warning.erl"]}
134134

135+
assert [^diagnostic] = Mix.Tasks.Compile.Erlang.diagnostics()
136+
assert [^diagnostic] = Mix.Task.Compiler.diagnostics()
137+
135138
# Should not return warning after changing file
136139
File.write!(file, """
137140
-module(has_warning).

0 commit comments

Comments
 (0)