Skip to content

Commit c69fa11

Browse files
author
José Valim
committed
Improve error messages for bodyless and skip warning on quoted headers
Closes #5435
1 parent f091c60 commit c69fa11

File tree

5 files changed

+18
-14
lines changed

5 files changed

+18
-14
lines changed

lib/elixir/lib/supervisor.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ defmodule Supervisor do
228228
quote location: :keep do
229229
@behaviour Supervisor
230230
import Supervisor.Spec
231+
232+
@doc false
233+
def init(arg)
231234
end
232235
end
233236

lib/elixir/pages/Writing Documentation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ When documenting a function, argument names are inferred by the compiler. For ex
4444
size
4545
end
4646

47-
The compiler will infer this argument as `map`. Sometimes the inference will be suboptimal, especially if the function contains multiple clauses with the argument matching on different values each time. You can specify the proper names for documentation by declaring before a bodyless clause:
47+
The compiler will infer this argument as `map`. Sometimes the inference will be suboptimal, especially if the function contains multiple clauses with the argument matching on different values each time. You can specify the proper names for documentation by declaring only the function head at any moment before the implementation:
4848

4949
def size(map)
5050
def size(%{size: size}) do

lib/elixir/src/elixir_def.erl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ unwrap_definition([[Tuple] | T], File, Module, Table, All, Private) ->
210210

211211
case [Clause || {_, Clause} <- ets:lookup(Table, {clauses, Tuple})] of
212212
[] ->
213-
warn_bodyless_function(Ann, File, Module, Kind, Tuple),
213+
warn_bodyless_function(Check, Ann, File, Module, Kind, Tuple),
214214
unwrap_definition(T, File, Module, Table, All, Private);
215215
Clauses ->
216216
Unwrapped = {Tuple, Kind, Ann, Location,
@@ -283,9 +283,10 @@ default_function_for(Kind, Name, {clause, Ann, Args, _Guards, _Exprs} = Clause)
283283
default_function_for(_, Name, {clause, Ann, Args, _Guards, _Exprs} = Clause) ->
284284
{function, Ann, Name, length(Args), [Clause]}.
285285

286-
warn_bodyless_function(_Ann, _File, 'Elixir.Module', _Kind, _Tuple) ->
287-
ok; %% Documentation for __info__
288-
warn_bodyless_function(Ann, File, _Module, Kind, Tuple) ->
286+
warn_bodyless_function(Check, _Ann, _File, Module, _Kind, _Tuple)
287+
when Check == false; Module == 'Elixir.Module' ->
288+
ok;
289+
warn_bodyless_function(_Check, Ann, File, _Module, Kind, Tuple) ->
289290
elixir_errors:form_warn([{line, erl_anno:line(Ann)}], File, ?MODULE, {bodyless_clause, Kind, Tuple}),
290291
ok.
291292

@@ -385,7 +386,7 @@ assert_valid_name(_Meta, _Kind, _Name, _Args, _S) ->
385386
%% Format errors
386387

387388
format_error({bodyless_clause, Kind, {Name, Arity}}) ->
388-
io_lib:format("bodyless clause provided for nonexistent ~ts ~ts/~B", [Kind, Name, Arity]);
389+
io_lib:format("implementation not provided for predefined ~ts ~ts/~B", [Kind, Name, Arity]);
389390

390391
format_error({no_module, {Kind, Name, Arity}}) ->
391392
io_lib:format("cannot define function outside module, invalid scope for ~ts ~ts/~B", [Kind, Name, Arity]);
@@ -400,7 +401,7 @@ format_error({defs_with_defaults, Name, {Kind, Arity}, {K, A}}) when Arity < A -
400401

401402
format_error({clauses_with_defaults, {Kind, Name, Arity}}) ->
402403
io_lib:format(""
403-
"definitions with multiple clauses and default values require a function head. Instead of:\n"
404+
"definitions with multiple clauses and default values require a header. Instead of:\n"
404405
"\n"
405406
" def foo(:first_clause, b \\\\ :default) do ... end\n"
406407
" def foo(:second_clause, b) do ... end\n"
@@ -411,7 +412,7 @@ format_error({clauses_with_defaults, {Kind, Name, Arity}}) ->
411412
" def foo(:first_clause, b) do ... end\n"
412413
" def foo(:second_clause, b) do ... end\n"
413414
"\n"
414-
"~ts ~ts/~B has multiple clauses and defines defaults in a clause with a body", [Kind, Name, Arity]);
415+
"~ts ~ts/~B has multiple clauses and defines defaults in one or more clauses", [Kind, Name, Arity]);
415416

416417
format_error({ungrouped_clause, {Kind, Name, Arity, OrigLine, OrigFile}}) ->
417418
io_lib:format("clauses for the same ~ts should be grouped together, ~ts ~ts/~B was previously defined (~ts:~B)",
@@ -427,7 +428,7 @@ format_error({invalid_def, Kind, NameAndArgs}) ->
427428
io_lib:format("invalid syntax in ~ts ~ts", [Kind, 'Elixir.Macro':to_string(NameAndArgs)]);
428429

429430
format_error(invalid_args_for_bodyless_clause) ->
430-
"can use only variables and \\\\ as arguments in function heads";
431+
"can use only variables and \\\\ as arguments in definition header";
431432

432433
format_error({is_record, Kind}) ->
433434
io_lib:format("cannot define function named ~ts is_record/2 due to compability "

lib/elixir/test/elixir/kernel/errors_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ defmodule Kernel.ErrorsTest do
203203

204204
test "clause with defaults" do
205205
assert_compile_fail CompileError,
206-
"nofile:3: definitions with multiple clauses and default values require a function head",
206+
"nofile:3: definitions with multiple clauses and default values require a header",
207207
~C'''
208208
defmodule Kernel.ErrorsTest.ClauseWithDefaults1 do
209209
def hello(arg \\ 0), do: nil
@@ -879,7 +879,7 @@ defmodule Kernel.ErrorsTest do
879879

880880
test "invalid args for bodyless clause" do
881881
assert_compile_fail CompileError,
882-
"nofile:2: can use only variables and \\\\ as arguments in function heads",
882+
"nofile:2: can use only variables and \\\\ as arguments in definition header",
883883
'''
884884
defmodule Kernel.ErrorsTest.InvalidArgsForBodylessClause do
885885
def foo(arg // nil)

lib/elixir/test/elixir/kernel/warning_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ defmodule Kernel.WarningTest do
391391
def hello
392392
end
393393
"""
394-
end) =~ "bodyless clause provided for nonexistent def hello/0"
394+
end) =~ "implementation not provided for predefined def hello/0"
395395
after
396396
purge Sample1
397397
end
@@ -438,7 +438,7 @@ defmodule Kernel.WarningTest do
438438
def hello(arg \\ 0), do: nil
439439
end
440440
"""
441-
end) =~ "definitions with multiple clauses and default values require a function head"
441+
end) =~ "definitions with multiple clauses and default values require a header"
442442
after
443443
purge Sample
444444
end
@@ -451,7 +451,7 @@ defmodule Kernel.WarningTest do
451451
def hello(arg), do: nil
452452
end
453453
"""
454-
end) =~ "definitions with multiple clauses and default values require a function head"
454+
end) =~ "definitions with multiple clauses and default values require a header"
455455
after
456456
purge Sample
457457
end

0 commit comments

Comments
 (0)