Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/mix/lib/mix/compilers/elixir.ex
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,14 @@ defmodule Mix.Compilers.Elixir do
end
end

@doc """
Retrieves all diagnostics from the given manifest.
"""
def diagnostics(manifest, dest) do
{_, all_sources, _, _, _, _, _, _} = parse_manifest(manifest, dest)
previous_warnings(all_sources, false)
end

defp compiler_info_from_force(manifest, all_paths, all_modules, dest) do
# A config, path dependency or manifest has changed, let's just compile everything
for {module, _} <- all_modules,
Expand Down
8 changes: 8 additions & 0 deletions lib/mix/lib/mix/compilers/erlang.ex
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ defmodule Mix.Compilers.Erlang do
manifest |> read_manifest() |> Enum.map(&elem(&1, 0))
end

@doc """
Retrieves all diagnostics from the given manifest.
"""
def diagnostics(manifest) do
entries = read_manifest(manifest)
manifest_warnings(entries)
end

defp extract_entries(src_dir, src_ext, dest_dir, dest_ext, force) do
files = Mix.Utils.extract_files(List.wrap(src_dir), List.wrap(src_ext))

Expand Down
64 changes: 63 additions & 1 deletion lib/mix/lib/mix/task.compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,17 @@ defmodule Mix.Task.Compiler do
"""
@callback manifests() :: [Path.t()]

@doc """
Lists persisted diagnostics from the compiler.
"""
@callback diagnostics() :: [Diagnostic.t()]

@doc """
Removes build artifacts and manifests.
"""
@callback clean() :: any

@optional_callbacks clean: 0, manifests: 0
@optional_callbacks clean: 0, manifests: 0, diagnostics: 0

@doc """
Adds a callback that runs after a given compiler.
Expand Down Expand Up @@ -184,6 +189,63 @@ defmodule Mix.Task.Compiler do
end
end

@doc """
Returns all compilers for the current project.
"""
def compilers(config \\ Mix.Project.config()) do
compilers = config[:compilers] || Mix.compilers()

if :xref in compilers do
IO.warn(
"the :xref compiler is deprecated, please remove it from your mix.exs :compilers options"
)

List.delete(compilers, :xref)
else
compilers
end
|> maybe_prepend(:leex)
|> maybe_prepend(:yecc)
end

defp maybe_prepend(compilers, compiler) do
if compiler in compilers do
compilers
else
[compiler | compilers]
end
end

@doc """
Lists manifest files for all compilers in the current project.
"""
def manifests(config \\ Mix.Project.config()) do
Enum.flat_map(compilers(config), fn compiler ->
module = Mix.Task.get("compile.#{compiler}")

if module && function_exported?(module, :manifests, 0) do
module.manifests()
else
[]
end
end)
end

@doc """
Lists persisted diagnostics from all compilers in the current project.
"""
def diagnostics(config \\ Mix.Project.config()) do
Enum.flat_map(compilers(config), fn compiler ->
module = Mix.Task.get("compile.#{compiler}")

if module && function_exported?(module, :diagnostics, 0) do
module.diagnostics()
else
[]
end
end)
end

# Normalize the compiler result to a diagnostic tuple.
@doc false
def normalize(result, name) do
Expand Down
2 changes: 1 addition & 1 deletion lib/mix/lib/mix/tasks/clean.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule Mix.Tasks.Clean do
# First, we get the tasks. After that, we clean them.
# This is to avoid a task cleaning a compiler module.
tasks =
for compiler <- [:protocols] ++ Mix.Tasks.Compile.compilers(),
for compiler <- [:protocols] ++ Mix.Task.Compiler.compilers(),
module = Mix.Task.get("compile.#{compiler}"),
function_exported?(module, :clean, 0),
do: module
Expand Down
2 changes: 1 addition & 1 deletion lib/mix/lib/mix/tasks/compile.all.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ defmodule Mix.Tasks.Compile.All do
Mix.Project.build_structure(config)

config
|> Mix.Tasks.Compile.compilers()
|> Mix.Task.Compiler.compilers()
|> compile(args, :noop, [])
end

Expand Down
6 changes: 6 additions & 0 deletions lib/mix/lib/mix/tasks/compile.elixir.ex
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ defmodule Mix.Tasks.Compile.Elixir do
def manifests, do: [manifest()]
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)

@impl true
def diagnostics do
dest = Mix.Project.compile_path()
Mix.Compilers.Elixir.diagnostics(manifest(), dest)
end

@impl true
def clean do
dest = Mix.Project.compile_path()
Expand Down
5 changes: 5 additions & 0 deletions lib/mix/lib/mix/tasks/compile.erlang.ex
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ defmodule Mix.Tasks.Compile.Erlang do
def manifests, do: [manifest()]
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)

@impl true
def diagnostics do
Mix.Compilers.Erlang.diagnostics(manifest())
end

@impl true
def clean do
Mix.Compilers.Erlang.clean(manifest())
Expand Down
45 changes: 6 additions & 39 deletions lib/mix/lib/mix/tasks/compile.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Mix.Tasks.Compile do
use Mix.Task.Compiler
use Mix.Task

@shortdoc "Compiles source files"

Expand Down Expand Up @@ -42,6 +42,7 @@ defmodule Mix.Tasks.Compile do
the paths set by the code loader from the `ERL_LIBS` environment as
well as explicitly listed by providing `-pa` and `-pz` options
to Erlang.

## Compilers

To see documentation for each specific compiler, you must
Expand Down Expand Up @@ -79,32 +80,8 @@ defmodule Mix.Tasks.Compile do

"""

@doc """
Returns all compilers for the current project.
"""
def compilers(config \\ Mix.Project.config()) do
compilers = config[:compilers] || Mix.compilers()

if :xref in compilers do
IO.warn(
"the :xref compiler is deprecated, please remove it from your mix.exs :compilers options"
)

List.delete(compilers, :xref)
else
compilers
end
|> maybe_prepend(:leex)
|> maybe_prepend(:yecc)
end

defp maybe_prepend(compilers, compiler) do
if compiler in compilers do
compilers
else
[compiler | compilers]
end
end
@deprecated "Use Mix.Task.Compiler.compilers/1 instead"
defdelegate compilers(config \\ Mix.Project.config()), to: Mix.Task.Compiler

@impl true
def run(["--list"]) do
Expand Down Expand Up @@ -228,18 +205,8 @@ defmodule Mix.Tasks.Compile do
end
end

@impl true
def manifests do
Enum.flat_map(compilers(), fn compiler ->
module = Mix.Task.get("compile.#{compiler}")

if module && function_exported?(module, :manifests, 0) do
module.manifests()
else
[]
end
end)
end
@deprecated "Use Mix.Task.Compiler.manifests/0 instead"
defdelegate manifests, to: Mix.Task.Compiler

## Consolidation handling

Expand Down
3 changes: 3 additions & 0 deletions lib/mix/test/mix/tasks/compile.elixir_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,9 @@ defmodule Mix.Tasks.Compile.ElixirTest do
compiler_name: "Elixir",
message: ^message
} = diagnostic

assert [^diagnostic] = Mix.Tasks.Compile.Elixir.diagnostics()
assert [^diagnostic] = Mix.Task.Compiler.diagnostics()
end)
end)
end
Expand Down
3 changes: 3 additions & 0 deletions lib/mix/test/mix/tasks/compile.erlang_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ defmodule Mix.Tasks.Compile.ErlangTest do
assert {:noop, [^diagnostic]} = Mix.Tasks.Compile.Erlang.run(["--verbose"])
refute_received {:mix_shell, :info, ["Compiled src/has_warning.erl"]}

assert [^diagnostic] = Mix.Tasks.Compile.Erlang.diagnostics()
assert [^diagnostic] = Mix.Task.Compiler.diagnostics()

# Should not return warning after changing file
File.write!(file, """
-module(has_warning).
Expand Down
2 changes: 1 addition & 1 deletion lib/mix/test/mix/tasks/compile_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ defmodule Mix.Tasks.CompileTest do

@tag project: [compilers: [:elixir, :app, :custom]]
test "compiles does not require all compilers available on manifest" do
assert Mix.Tasks.Compile.manifests() |> Enum.map(&Path.basename/1) ==
assert Mix.Task.Compiler.manifests() |> Enum.map(&Path.basename/1) ==
["compile.yecc", "compile.leex", "compile.elixir"]
end

Expand Down
Loading