diff options
author | Glauber Campinho <ggcampinho@gmail.com> | 2018-09-16 10:44:26 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2018-09-16 10:44:26 +0200 |
commit | f3322732287ff733b02cd79debbf1b53de676251 (patch) | |
tree | 9a93d573d38afceefac9d2225145f48484f5906e | |
parent | 57c291280924dcbb7e9d5c771e2d3c23f422491d (diff) | |
download | elixir-f3322732287ff733b02cd79debbf1b53de676251.tar.gz |
Use head definition meta to warn about unused args (#8198)
Fixes #8184
-rw-r--r-- | lib/elixir/src/elixir_def.erl | 24 | ||||
-rw-r--r-- | lib/elixir/test/elixir/kernel/warning_test.exs | 68 |
2 files changed, 68 insertions, 24 deletions
diff --git a/lib/elixir/src/elixir_def.erl b/lib/elixir/src/elixir_def.erl index 24fca3410..e5b36f28e 100644 --- a/lib/elixir/src/elixir_def.erl +++ b/lib/elixir/src/elixir_def.erl @@ -65,17 +65,17 @@ fetch_definitions(File, Module) -> {All, Unreachable}. fetch_definition([Tuple | T], File, Module, Set, Bag, All, Private) -> - [{_, Kind, Meta, _, Check, {Defaults, _, _}}] = ets:lookup(Set, {def, Tuple}), + [{_, Kind, Meta, _, Check, {MaxDefaults, _, Defaults}}] = ets:lookup(Set, {def, Tuple}), try ets:lookup_element(Bag, {clauses, Tuple}, 2) of Clauses -> NewAll = - [{Tuple, Kind, add_defaults_to_meta(Defaults, Meta), Clauses} | All], + [{Tuple, Kind, add_defaults_to_meta(MaxDefaults, Meta), Clauses} | All], NewPrivate = case (Kind == defp) orelse (Kind == defmacrop) of true -> - WarnMeta = case Check of true -> Meta; false -> false end, - [{Tuple, Kind, WarnMeta, Defaults} | Private]; + Metas = head_and_definition_meta(Check, Meta, MaxDefaults - Defaults, All), + [{Tuple, Kind, Metas, MaxDefaults} | Private]; false -> Private end, @@ -92,6 +92,13 @@ fetch_definition([], _File, _Module, _Set, _Bag, All, Private) -> add_defaults_to_meta(0, Meta) -> Meta; add_defaults_to_meta(Defaults, Meta) -> [{defaults, Defaults} | Meta]. +head_and_definition_meta(true, Meta, 0, _All) -> + Meta; +head_and_definition_meta(true, _Meta, _HeadDefaults, [{_, _, HeadMeta, _} | _]) -> + HeadMeta; +head_and_definition_meta(false, _Meta, _HeadDefaults, _All) -> + false. + %% Section for storing definitions store_definition(Kind, CheckClauses, Call, Body, Pos) -> @@ -242,22 +249,23 @@ store_definition(Check, Kind, Meta, Name, Arity, File, Module, Defaults, Clauses ok end, - MaxDefaults = + {MaxDefaults, FirstMeta} = case ets:lookup(Set, {def, Tuple}) of [{_, StoredKind, StoredMeta, StoredFile, StoredCheck, {StoredDefaults, LastHasBody, LastDefaults}}] -> check_valid_kind(Meta, File, Name, Arity, Kind, StoredKind), (Check and StoredCheck) andalso check_valid_clause(Meta, File, Name, Arity, Kind, Set, StoredMeta, StoredFile), check_valid_defaults(Meta, File, Name, Arity, Kind, Defaults, StoredDefaults, LastDefaults, HasBody, LastHasBody), - max(Defaults, StoredDefaults); + + {max(Defaults, StoredDefaults), StoredMeta}; [] -> ets:insert(Bag, {defs, Tuple}), - Defaults + {Defaults, Meta} end, Check andalso ets:insert(Set, {?last_def, Tuple}), ets:insert(Bag, [{{clauses, Tuple}, Clause} || Clause <- Clauses]), - ets:insert(Set, {{def, Tuple}, Kind, Meta, File, Check, {MaxDefaults, HasBody, Defaults}}). + ets:insert(Set, {{def, Tuple}, Kind, FirstMeta, File, Check, {MaxDefaults, HasBody, Defaults}}). %% Handling of defaults diff --git a/lib/elixir/test/elixir/kernel/warning_test.exs b/lib/elixir/test/elixir/kernel/warning_test.exs index 76c986eb6..95f257718 100644 --- a/lib/elixir/test/elixir/kernel/warning_test.exs +++ b/lib/elixir/test/elixir/kernel/warning_test.exs @@ -343,7 +343,7 @@ defmodule Kernel.WarningTest do defp hello, do: nil end """) - end) =~ "function hello/0 is unused" + end) =~ "function hello/0 is unused\n nofile:2" assert capture_err(fn -> Code.eval_string(""" @@ -352,7 +352,7 @@ defmodule Kernel.WarningTest do defp hello(1), do: :ok end """) - end) =~ "function hello/1 is unused" + end) =~ "function hello/1 is unused\n nofile:2" assert capture_err(fn -> Code.eval_string(~S""" @@ -363,20 +363,34 @@ defmodule Kernel.WarningTest do defp d(x), do: x end """) - end) =~ "function c/2 is unused" - after - purge([Sample1, Sample2, Sample3]) - end + end) =~ "function c/2 is unused\n nofile:4" - test "unused cyclic functions" do assert capture_err(fn -> - Code.eval_string(""" - defmodule Sample do - defp a, do: b() - defp b, do: a() + Code.eval_string(~S""" + defmodule Sample4 do + def a, do: nil + defp b(x \\ 1, y \\ 1) + defp b(x, y), do: [x, y] end """) - end) =~ "function a/0 is unused" + end) =~ "function b/2 is unused\n nofile:3" + after + purge([Sample1, Sample2, Sample3, Sample4]) + end + + test "unused cyclic functions" do + message = + capture_err(fn -> + Code.eval_string(""" + defmodule Sample do + defp a, do: b() + defp b, do: a() + end + """) + end) + + assert message =~ "function a/0 is unused\n nofile:2" + assert message =~ "function b/0 is unused\n nofile:3" after purge(Sample) end @@ -418,7 +432,7 @@ defmodule Kernel.WarningTest do defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """) - end) =~ "default arguments in b/3 are never used" + end) =~ "default arguments in b/3 are never used\n nofile:3" assert capture_err(fn -> Code.eval_string(~S""" @@ -427,7 +441,7 @@ defmodule Kernel.WarningTest do defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """) - end) =~ "the first 2 default arguments in b/3 are never used" + end) =~ "the first 2 default arguments in b/3 are never used\n nofile:3" assert capture_err(fn -> Code.eval_string(~S""" @@ -436,7 +450,7 @@ defmodule Kernel.WarningTest do defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """) - end) =~ "the first default argument in b/3 is never used" + end) =~ "the first default argument in b/3 is never used\n nofile:3" assert capture_err(fn -> Code.eval_string(~S""" @@ -446,8 +460,30 @@ defmodule Kernel.WarningTest do end """) end) == "" + + assert capture_err(fn -> + Code.eval_string(~S""" + defmodule Sample5 do + def a, do: b(1, 2, 3) + defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3) + + defp b(arg1, arg2, arg3), do: [arg1, arg2, arg3] + end + """) + end) =~ "default arguments in b/3 are never used\n nofile:3" + + assert capture_err(fn -> + Code.eval_string(~S""" + defmodule Sample6 do + def a, do: b(1, 2) + defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3) + + defp b(arg1, arg2, arg3), do: [arg1, arg2, arg3] + end + """) + end) =~ "the first 2 default arguments in b/3 are never used\n nofile:3" after - purge([Sample1, Sample2, Sample3, Sample4]) + purge([Sample1, Sample2, Sample3, Sample4, Sample5, Sample6]) end test "unused import" do |