summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-10-10 23:11:10 +0200
committerGitHub <noreply@github.com>2019-10-10 23:11:10 +0200
commitc6da1cfaa83e420726be25617440fc09f118de52 (patch)
tree28409e425e2bd5b65097c206db45b2d77c40e064
parentf52f2c79527f5477a91876536e5f2debbdf0a51d (diff)
downloadelixir-c6da1cfaa83e420726be25617440fc09f118de52.tar.gz
Run checker on Code.require_file/1 (#9393)
Closes #9362.
-rw-r--r--lib/elixir/lib/code.ex19
-rw-r--r--lib/elixir/lib/kernel/parallel_compiler.ex18
-rw-r--r--lib/elixir/lib/module/checker.ex19
-rw-r--r--lib/elixir/lib/module/parallel_checker.ex3
-rw-r--r--lib/elixir/src/elixir_compiler.erl2
-rw-r--r--lib/elixir/src/elixir_module.erl2
-rw-r--r--lib/elixir/test/elixir/code_test.exs9
-rw-r--r--lib/elixir/test/elixir/fixtures/checker_warning.exs3
8 files changed, 48 insertions, 27 deletions
diff --git a/lib/elixir/lib/code.ex b/lib/elixir/lib/code.ex
index c3ae3ba57..f21eb06ca 100644
--- a/lib/elixir/lib/code.ex
+++ b/lib/elixir/lib/code.ex
@@ -844,7 +844,7 @@ defmodule Code do
:elixir_code_server.call({:acquire, file})
loaded = :elixir_compiler.file(file, fn _, _ -> :ok end)
:elixir_code_server.cast({:required, file})
- loaded
+ verify_loaded(loaded)
end
@doc """
@@ -890,7 +890,7 @@ defmodule Code do
:proceed ->
loaded = :elixir_compiler.file(file, fn _, _ -> :ok end)
:elixir_code_server.cast({:required, file})
- loaded
+ verify_loaded(loaded)
end
end
@@ -1083,7 +1083,8 @@ defmodule Code do
"""
@spec compile_string(List.Chars.t(), binary) :: [{module, binary}]
def compile_string(string, file \\ "nofile") when is_binary(file) do
- :elixir_compiler.string(to_charlist(string), file, fn _, _ -> :ok end)
+ loaded = :elixir_compiler.string(to_charlist(string), file, fn _, _ -> :ok end)
+ Enum.map(loaded, fn {module, _map, binary} -> {module, binary} end)
end
@doc """
@@ -1096,7 +1097,8 @@ defmodule Code do
"""
@spec compile_quoted(Macro.t(), binary) :: [{module, binary}]
def compile_quoted(quoted, file \\ "nofile") when is_binary(file) do
- :elixir_compiler.quoted(quoted, file, fn _, _ -> :ok end)
+ loaded = :elixir_compiler.quoted(quoted, file, fn _, _ -> :ok end)
+ Enum.map(loaded, fn {module, _map, binary} -> {module, binary} end)
end
@doc """
@@ -1116,7 +1118,8 @@ defmodule Code do
@doc since: "1.7.0"
@spec compile_file(binary, nil | binary) :: [{module, binary}]
def compile_file(file, relative_to \\ nil) when is_binary(file) do
- :elixir_compiler.file(find_file(file, relative_to), fn _, _ -> :ok end)
+ loaded = :elixir_compiler.file(find_file(file, relative_to), fn _, _ -> :ok end)
+ verify_loaded(loaded)
end
@doc """
@@ -1343,4 +1346,10 @@ defmodule Code do
raise Code.LoadError, file: file
end
end
+
+ defp verify_loaded(loaded) do
+ maps_binaries = Enum.map(loaded, fn {_module, map, binary} -> {map, binary} end)
+ {loaded, _warnings} = Module.ParallelChecker.verify(maps_binaries, [])
+ loaded
+ end
end
diff --git a/lib/elixir/lib/kernel/parallel_compiler.ex b/lib/elixir/lib/kernel/parallel_compiler.ex
index bd77ff536..02c6f75cc 100644
--- a/lib/elixir/lib/kernel/parallel_compiler.ex
+++ b/lib/elixir/lib/kernel/parallel_compiler.ex
@@ -357,15 +357,7 @@ defmodule Kernel.ParallelCompiler do
defp checker_compiled_modules(result) do
for {{:module, _module}, {binary, module_map}} <- result do
- map = %{
- module: module_map.module,
- file: module_map.file,
- no_warn_undefined: no_warn_undefined(module_map.compile_opts),
- definitions: module_map.definitions,
- deprecated: module_map.deprecated
- }
-
- {map, binary}
+ {module_map, binary}
end
end
@@ -377,14 +369,6 @@ defmodule Kernel.ParallelCompiler do
end
end
- defp no_warn_undefined(compile_opts) do
- for(
- {:no_warn_undefined, values} <- compile_opts,
- value <- List.wrap(values),
- do: value
- )
- end
-
# The goal of this function is to find leaves in the dependency graph,
# i.e. to find code that depends on code that we know is not being defined.
defp without_definition(waiting, files) do
diff --git a/lib/elixir/lib/module/checker.ex b/lib/elixir/lib/module/checker.ex
index afaf5527f..6a6d43b10 100644
--- a/lib/elixir/lib/module/checker.ex
+++ b/lib/elixir/lib/module/checker.ex
@@ -16,8 +16,15 @@ defmodule Module.Checker do
end
end
- defp prepare_module({_module, map}) when is_map(map) do
- {:ok, map}
+ defp prepare_module({module, module_map}) when is_map(module_map) do
+ {:ok,
+ %{
+ module: module,
+ file: module_map.file,
+ no_warn_undefined: no_warn_undefined(module_map.compile_opts),
+ definitions: module_map.definitions,
+ deprecated: module_map.deprecated
+ }}
end
defp prepare_module({module, binary}) when is_binary(binary) do
@@ -34,6 +41,14 @@ defmodule Module.Checker do
end
end
+ defp no_warn_undefined(compile_opts) do
+ for(
+ {:no_warn_undefined, values} <- compile_opts,
+ value <- List.wrap(values),
+ do: value
+ )
+ end
+
defp debug_info(module, binary) do
with {:ok, {_, [debug_info: chunk]}} <- :beam_lib.chunks(binary, [:debug_info]),
{:debug_info_v1, backend, data} <- chunk,
diff --git a/lib/elixir/lib/module/parallel_checker.ex b/lib/elixir/lib/module/parallel_checker.ex
index 41d4f8cca..ca737457f 100644
--- a/lib/elixir/lib/module/parallel_checker.ex
+++ b/lib/elixir/lib/module/parallel_checker.ex
@@ -12,10 +12,11 @@ defmodule Module.ParallelChecker do
"""
@spec verify([{%{}, binary()}], [{module(), binary()}], pos_integer()) ::
{[{module(), binary()}], [warning()]}
- def verify(compiled_modules, runtime_binaries, schedulers) do
+ def verify(compiled_modules, runtime_binaries, schedulers \\ nil) do
compiled_maps = Enum.map(compiled_modules, fn {map, _binary} -> {map.module, map} end)
check_modules = compiled_maps ++ runtime_binaries
+ schedulers = schedulers || max(:erlang.system_info(:schedulers_online), 2)
{:ok, server} = :gen_server.start_link(__MODULE__, [check_modules, self(), schedulers], [])
preload_cache(get_ets(server), check_modules)
start(server)
diff --git a/lib/elixir/src/elixir_compiler.erl b/lib/elixir/src/elixir_compiler.erl
index 1873ad40e..70858cfd7 100644
--- a/lib/elixir/src/elixir_compiler.erl
+++ b/lib/elixir/src/elixir_compiler.erl
@@ -174,7 +174,7 @@ bootstrap_main() ->
<<"lib/elixir/lib/kernel/parallel_compiler.ex">>,
<<"lib/elixir/lib/kernel/lexical_tracker.ex">>].
-binary_to_path({ModuleName, Binary}, CompilePath) ->
+binary_to_path({ModuleName, _ModuleMap, Binary}, CompilePath) ->
Path = filename:join(CompilePath, atom_to_list(ModuleName) ++ ".beam"),
case file:write_file(Path, Binary) of
ok -> Path;
diff --git a/lib/elixir/src/elixir_module.erl b/lib/elixir/src/elixir_module.erl
index f435ff37e..8ce8c1163 100644
--- a/lib/elixir/src/elixir_module.erl
+++ b/lib/elixir/src/elixir_module.erl
@@ -409,7 +409,7 @@ beam_location(#{module := Module}) ->
make_module_available(Module, Binary, ModuleMap) ->
case get(elixir_module_binaries) of
Current when is_list(Current) ->
- put(elixir_module_binaries, [{Module, Binary} | Current]);
+ put(elixir_module_binaries, [{Module, ModuleMap, Binary} | Current]);
_ ->
ok
end,
diff --git a/lib/elixir/test/elixir/code_test.exs b/lib/elixir/test/elixir/code_test.exs
index 248f7b313..3c5f53507 100644
--- a/lib/elixir/test/elixir/code_test.exs
+++ b/lib/elixir/test/elixir/code_test.exs
@@ -117,6 +117,15 @@ defmodule CodeTest do
Code.unrequire_files([fixture_path("code_sample.exs")])
end
+ test "require_file/1 checker warning" do
+ output =
+ ExUnit.CaptureIO.capture_io(:stderr, fn ->
+ Code.require_file(fixture_path("checker_warning.exs"))
+ end)
+
+ assert output =~ "function clause will never match"
+ end
+
describe "string_to_quoted/2" do
test "converts strings to quoted expressions" do
assert Code.string_to_quoted("1 + 2") == {:ok, {:+, [line: 1], [1, 2]}}
diff --git a/lib/elixir/test/elixir/fixtures/checker_warning.exs b/lib/elixir/test/elixir/fixtures/checker_warning.exs
new file mode 100644
index 000000000..a9c0cab9f
--- /dev/null
+++ b/lib/elixir/test/elixir/fixtures/checker_warning.exs
@@ -0,0 +1,3 @@
+defmodule CodeTest.CheckerWarning do
+ def foo(x) when is_atom(x) and is_list(x), do: x
+end