summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-07-09 18:18:01 +0200
committerEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-07-09 18:18:36 +0200
commit2321f0ec45e47f3fbb839d5ea8c8123f708f920b (patch)
tree557096093bdaf104d1e6d9158ebfc51aed2437d8
parent6b01c70ab4d660b43c5b9c3e0071b75fa88ff81f (diff)
downloadelixir-2321f0ec45e47f3fbb839d5ea8c8123f708f920b.tar.gz
Add warning for unrequired module
-rw-r--r--lib/elixir/lib/module/checker.ex21
-rw-r--r--lib/elixir/src/elixir_dispatch.erl4
-rw-r--r--lib/elixir/test/elixir/module/checker_test.exs24
3 files changed, 42 insertions, 7 deletions
diff --git a/lib/elixir/lib/module/checker.ex b/lib/elixir/lib/module/checker.ex
index 4a49eef95..bf0877028 100644
--- a/lib/elixir/lib/module/checker.ex
+++ b/lib/elixir/lib/module/checker.ex
@@ -126,8 +126,12 @@ defmodule Module.Checker do
defp check_export(module, fun, arity, meta, state) do
case ParallelChecker.fetch_export(state.cache, module, fun, arity) do
- {:ok, _} ->
- check_deprecated(module, fun, arity, meta, state)
+ {:ok, :def, reason} ->
+ check_deprecated(module, fun, arity, reason, meta, state)
+
+ {:ok, :defmacro, reason} ->
+ state = warn(meta, state, {:unrequired_module, module, fun, arity})
+ check_deprecated(module, fun, arity, reason, meta, state)
{:error, :module} ->
if warn_undefined?(module, fun, arity, state) do
@@ -217,14 +221,23 @@ defmodule Module.Checker do
]
end
- defp format_warning({:deprecated, module, function, arity, reason}) do
+ defp format_warning({:deprecated, module, fun, arity, reason}) do
[
- Exception.format_mfa(module, function, arity),
+ Exception.format_mfa(module, fun, arity),
" is deprecated. ",
reason
]
end
+ defp format_warning({:unrequired_module, module, fun, arity}) do
+ [
+ "you must require ",
+ inspect(module),
+ " before invoking the macro ",
+ Exception.format_mfa(module, fun, arity)
+ ]
+ end
+
defp format_locations([location]) do
format_location(location)
end
diff --git a/lib/elixir/src/elixir_dispatch.erl b/lib/elixir/src/elixir_dispatch.erl
index a6cfb1b65..b15e6dddd 100644
--- a/lib/elixir/src/elixir_dispatch.erl
+++ b/lib/elixir/src/elixir_dispatch.erl
@@ -170,7 +170,7 @@ expand_require(Meta, Receiver, {Name, Arity} = Tuple, Args, E) ->
elixir_lexical:record_remote(Receiver, Name, Arity, nil, ?line(Meta), ?key(E, lexical_tracker)),
{ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)};
true ->
- Info = {unrequired_module, {Receiver, Name, length(Args), ?key(E, requires)}},
+ Info = {unrequired_module, {Receiver, Name, length(Args)}},
elixir_errors:form_error(Meta, E, ?MODULE, Info);
false ->
error
@@ -272,7 +272,7 @@ prune_stacktrace([], _MFA, Info, _E) ->
%% ERROR HANDLING
-format_error({unrequired_module, {Receiver, Name, Arity, _Required}}) ->
+format_error({unrequired_module, {Receiver, Name, Arity}}) ->
Module = elixir_aliases:inspect(Receiver),
io_lib:format("you must require ~ts before invoking the macro ~ts.~ts/~B",
[Module, Module, Name, Arity]);
diff --git a/lib/elixir/test/elixir/module/checker_test.exs b/lib/elixir/test/elixir/module/checker_test.exs
index 7e193de12..6f645c5a7 100644
--- a/lib/elixir/test/elixir/module/checker_test.exs
+++ b/lib/elixir/test/elixir/module/checker_test.exs
@@ -402,7 +402,7 @@ defmodule Module.CheckerTest do
assert_no_warnings(files)
end
- test "do not warn for moduel defined in local context" do
+ test "do not warn for module defined in local context" do
files = %{
"a.ex" => """
defmodule A do
@@ -420,6 +420,28 @@ defmodule Module.CheckerTest do
assert_no_warnings(files)
end
+ test "warn for unrequired module" do
+ files = %{
+ "ab.ex" => """
+ defmodule A do
+ def a(), do: B.b()
+ end
+
+ defmodule B do
+ defmacro b(), do: :ok
+ end
+ """
+ }
+
+ warning = """
+ warning: you must require B before invoking the macro B.b/0
+ ab.ex:2: A.a/0
+
+ """
+
+ assert_warnings(files, warning)
+ end
+
test "excludes no_warn_undefined" do
files = %{
"a.ex" => """