diff --git a/lib/elixir/lib/module/parallel_checker.ex b/lib/elixir/lib/module/parallel_checker.ex index 7627428d31..f3211a37ad 100644 --- a/lib/elixir/lib/module/parallel_checker.ex +++ b/lib/elixir/lib/module/parallel_checker.ex @@ -212,9 +212,14 @@ defmodule Module.ParallelChecker do defp collect_results(count, warnings, errors) do receive do - {:diagnostic, %{file: file} = diagnostic, read_snippet} -> + {:diagnostic, %{file: file, source: source} = diagnostic, read_snippet} -> :elixir_errors.print_diagnostic(diagnostic, read_snippet) - diagnostic = %{diagnostic | file: file && Path.absname(file)} + + diagnostic = %{ + diagnostic + | file: file && Path.absname(file), + source: source && Path.absname(source) + } if Map.get(diagnostic, :severity, :warning) == :error do collect_results(count, warnings, [diagnostic | errors]) diff --git a/lib/elixir/test/elixir/module/types/integration_test.exs b/lib/elixir/test/elixir/module/types/integration_test.exs index fa1db95edd..3765f0e480 100644 --- a/lib/elixir/test/elixir/module/types/integration_test.exs +++ b/lib/elixir/test/elixir/module/types/integration_test.exs @@ -865,10 +865,18 @@ defmodule Module.Types.IntegrationTest do files = %{ "a.ex" => """ defmodule A do + @after_verify __MODULE__ @file "generated.ex" def fun(arg) do :ok = List.to_tuple(arg) end + + def __after_verify__(__MODULE__) do + IO.warn("This is a manually emitted warning", + file: Path.relative_to_cwd(__ENV__.file), + line: __ENV__.line + ) + end end """ } @@ -880,6 +888,11 @@ defmodule Module.Types.IntegrationTest do message: "the following pattern will never match" <> _, file: file, source: source + }, + %{ + message: "This is a manually emitted warning", + file: file2, + source: source2 } ] = warnings.runtime_warnings @@ -887,6 +900,10 @@ defmodule Module.Types.IntegrationTest do assert Path.type(source) == :absolute assert String.ends_with?(file, "generated.ex") assert Path.type(file) == :absolute + assert String.ends_with?(source2, "a.ex") + assert Path.type(source2) == :absolute + assert String.ends_with?(file2, "a.ex") + assert Path.type(file2) == :absolute after purge(A) end diff --git a/lib/mix/test/mix/tasks/compile.elixir_test.exs b/lib/mix/test/mix/tasks/compile.elixir_test.exs index dc1e0b1286..ca83b53be8 100644 --- a/lib/mix/test/mix/tasks/compile.elixir_test.exs +++ b/lib/mix/test/mix/tasks/compile.elixir_test.exs @@ -1313,6 +1313,37 @@ defmodule Mix.Tasks.Compile.ElixirTest do end) end + test "tracks warnings from after_verify with relative paths" do + in_fixture("no_mixfile", fn -> + Mix.Project.push(MixTest.Case.Sample) + + File.write!("lib/a.ex", """ + defmodule A do + @after_verify __MODULE__ + + def __after_verify__(__MODULE__) do + IO.warn("oops", file: Path.relative_to_cwd(__ENV__.file), line: 13) + end + end + """) + + # after_verify runs in the checker, which must make source and file absolute + file = Path.absname("lib/a.ex") + + assert capture_io(:stderr, fn -> + assert {:ok, + [%Mix.Task.Compiler.Diagnostic{source: ^file, file: ^file, position: 13}]} = + Mix.Tasks.Compile.Elixir.run([]) + + assert {:noop, + [%Mix.Task.Compiler.Diagnostic{source: ^file, file: ^file, position: 13}]} = + Mix.Tasks.Compile.Elixir.run(["--all-warnings"]) + end) =~ "oops" + + purge([A]) + end) + end + test "recompiles modules with exports tracking" do Process.register(self(), __MODULE__) Code.put_compiler_option(:tracers, [__MODULE__])