diff options
-rw-r--r-- | lib/elixir/lib/module/checker.ex | 21 | ||||
-rw-r--r-- | lib/elixir/src/elixir_dispatch.erl | 4 | ||||
-rw-r--r-- | lib/elixir/test/elixir/module/checker_test.exs | 24 |
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" => """ |