Skip to content

Commit 182e4b5

Browse files
committed
Track source for warnings, closes #14093
1 parent fe089de commit 182e4b5

File tree

4 files changed

+69
-18
lines changed

4 files changed

+69
-18
lines changed

lib/elixir/lib/module/parallel_checker.ex

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ defmodule Module.ParallelChecker do
239239
|> Module.Types.warnings(file, definitions, no_warn_undefined, cache)
240240
|> Kernel.++(behaviour_warnings)
241241
|> group_warnings()
242-
|> emit_warnings(log?)
242+
|> emit_warnings(file, log?)
243243

244244
Enum.each(after_verify, fn {verify_mod, verify_fun} ->
245245
apply(verify_mod, verify_fun, [module])
@@ -320,9 +320,9 @@ defmodule Module.ParallelChecker do
320320
Enum.sort(ungrouped ++ grouped)
321321
end
322322

323-
defp emit_warnings(warnings, log?) do
323+
defp emit_warnings(warnings, file, log?) do
324324
Enum.flat_map(warnings, fn {locations, diagnostic} ->
325-
diagnostics = Enum.map(locations, &to_diagnostic(diagnostic, &1))
325+
diagnostics = Enum.map(locations, &to_diagnostic(diagnostic, file, &1))
326326
log? and print_diagnostics(diagnostics)
327327
diagnostics
328328
end)
@@ -336,10 +336,12 @@ defmodule Module.ParallelChecker do
336336
:elixir_errors.print_diagnostics(diagnostics)
337337
end
338338

339-
defp to_diagnostic(diagnostic, {file, position, mfa}) when is_list(position) do
339+
defp to_diagnostic(diagnostic, source, {file, position, mfa}) when is_list(position) do
340+
file = Path.absname(file)
341+
340342
%{
341343
severity: :warning,
342-
source: file,
344+
source: source,
343345
file: file,
344346
position: position_to_tuple(position),
345347
stacktrace: [to_stacktrace(file, position, mfa)],

lib/elixir/src/elixir_errors.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ emit_diagnostic(Severity, Position, File, Message, Stacktrace, Options) ->
9292

9393
Diagnostic = #{
9494
severity => Severity,
95-
source => File,
95+
source => case get(elixir_compiler_file) of
96+
undefined -> File;
97+
CompilerFile -> CompilerFile
98+
end,
9699
file => File,
97100
position => Position,
98101
message => unicode:characters_to_binary(Message),

lib/elixir/test/elixir/module/types/integration_test.exs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ defmodule Module.Types.IntegrationTest do
3636
"""
3737
}
3838

39-
modules = compile(files)
39+
modules = compile_modules(files)
4040

4141
assert [
4242
{{:c, 0}, %{}},
@@ -243,6 +243,37 @@ defmodule Module.Types.IntegrationTest do
243243

244244
assert_no_warnings(files)
245245
end
246+
247+
test "returns diagnostics with source and file" do
248+
files = %{
249+
"a.ex" => """
250+
defmodule A do
251+
@file "generated.ex"
252+
def fun(arg) do
253+
:ok = List.to_tuple(arg)
254+
end
255+
end
256+
"""
257+
}
258+
259+
{_modules, warnings} = with_compile_warnings(files)
260+
261+
assert [
262+
%{
263+
message: "the following pattern will never match" <> _,
264+
file: file,
265+
source: source
266+
}
267+
] = warnings.runtime_warnings
268+
269+
assert String.ends_with?(source, "a.ex")
270+
assert Path.type(source) == :absolute
271+
assert String.ends_with?(file, "generated.ex")
272+
assert Path.type(file) == :absolute
273+
after
274+
:code.delete(A)
275+
:code.purge(A)
276+
end
246277
end
247278

248279
describe "undefined warnings" do
@@ -980,27 +1011,39 @@ defmodule Module.Types.IntegrationTest do
9801011
defp capture_compile_warnings(files) do
9811012
in_tmp(fn ->
9821013
paths = generate_files(files)
983-
capture_io(:stderr, fn -> compile_files(paths) end)
1014+
capture_io(:stderr, fn -> compile_to_path(paths) end)
1015+
end)
1016+
end
1017+
1018+
defp with_compile_warnings(files) do
1019+
in_tmp(fn ->
1020+
paths = generate_files(files)
1021+
with_io(:stderr, fn -> compile_to_path(paths) end) |> elem(0)
9841022
end)
9851023
end
9861024

987-
defp compile(files) do
1025+
defp compile_modules(files) do
9881026
in_tmp(fn ->
9891027
paths = generate_files(files)
990-
compile_files(paths)
1028+
{modules, _warnings} = compile_to_path(paths)
1029+
1030+
Map.new(modules, fn module ->
1031+
{^module, binary, _filename} = :code.get_object_code(module)
1032+
{module, binary}
1033+
end)
9911034
end)
9921035
end
9931036

994-
defp compile_files(paths) do
995-
{:ok, modules, _warnings} =
1037+
defp compile_to_path(paths) do
1038+
{:ok, modules, warnings} =
9961039
Kernel.ParallelCompiler.compile_to_path(paths, ".", return_diagnostics: true)
9971040

998-
Map.new(modules, fn module ->
999-
{^module, binary, _filename} = :code.get_object_code(module)
1041+
for module <- modules do
10001042
:code.delete(module)
10011043
:code.purge(module)
1002-
{module, binary}
1003-
end)
1044+
end
1045+
1046+
{modules, warnings}
10041047
end
10051048

10061049
defp generate_files(files) do

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,12 +1045,15 @@ defmodule Mix.Tasks.Compile.ElixirTest do
10451045

10461046
# Compiles with missing external resources
10471047
file = Path.absname("lib/a.eex")
1048+
source = Path.absname("lib/a.ex")
10481049

10491050
assert capture_io(:stderr, fn ->
1050-
assert {:ok, [%Mix.Task.Compiler.Diagnostic{file: ^file, position: 13}]} =
1051+
assert {:ok,
1052+
[%Mix.Task.Compiler.Diagnostic{source: ^source, file: ^file, position: 13}]} =
10511053
Mix.Tasks.Compile.Elixir.run([])
10521054

1053-
assert {:noop, [%Mix.Task.Compiler.Diagnostic{file: ^file, position: 13}]} =
1055+
assert {:noop,
1056+
[%Mix.Task.Compiler.Diagnostic{source: ^source, file: ^file, position: 13}]} =
10541057
Mix.Tasks.Compile.Elixir.run(["--all-warnings"])
10551058
end) =~ "oops"
10561059

0 commit comments

Comments
 (0)