We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
2 parents 3bfa4d0 + 1bd3066 commit 63ec628Copy full SHA for 63ec628
lib/gradient/elixir_checker.ex
@@ -59,15 +59,16 @@ defmodule Gradient.ElixirChecker do
59
# Spec name doesn't match the function name
60
{fun, [{:spec_error, :wrong_spec_name, anno, n, a} | errors]}
61
62
- {:spec, {n, a}, anno} = s1, {{:spec, _, _}, errors} ->
63
- # Only one spec per function clause is allowed
64
- {s1, [{:spec_error, :spec_after_spec, anno, n, a} | errors]}
+ {:spec, {n, a}, anno} = s1, {{:spec, {n2, a2}, _}, errors} when n != n2 or a != a2 ->
+ # Specs with diffrent name/arity are mixed
+ {s1, [{:spec_error, :mixed_specs, anno, n, a} | errors]}
65
66
x, {_, errors} ->
67
{x, errors}
68
end)
69
|> elem(1)
70
|> Enum.map(&{file, &1})
71
+ |> Enum.reverse()
72
end
73
74
# Filter out __info__ and other generated functions with the same name pattern
lib/gradient/elixir_fmt.ex
@@ -119,9 +119,9 @@ defmodule Gradient.ElixirFmt do
119
)
120
121
122
- def format_type_error({:spec_error, :spec_after_spec, anno, name, arity}, opts) do
+ def format_type_error({:spec_error, :mixed_specs, anno, name, arity}, opts) do
123
:io_lib.format(
124
- "~sThe spec ~p/~p~s follows another spec, but only one spec per function clause is allowed~n",
+ "~sThe spec ~p/~p~s follows a spec with different name/arity~n",
125
[
126
format_location(anno, :brief, opts),
127
name,
test/examples/spec_correct.ex
@@ -3,4 +3,13 @@ defmodule CorrectSpec do
3
def convert(int) when is_integer(int), do: int / 1
4
@spec convert(atom()) :: binary()
5
def convert(atom) when is_atom(atom), do: to_string(atom)
6
+
7
+ @spec encode(integer()) :: float()
8
+ @spec encode(atom()) :: binary()
9
+ def encode(val) do
10
+ case val do
11
+ _ when is_integer(val) -> val / 1
12
+ _ when is_atom(val) -> to_string(val)
13
+ end
14
15
test/examples/spec_after_spec.ex renamed to test/examples/spec_mixed.ex
@@ -1,6 +1,8 @@
1
-defmodule SpecAfterSpec do
+defmodule SpecMixed do
2
@spec convert(integer()) :: float()
- @spec convert(atom()) :: binary()
+ def encode(atom) when is_atom(atom), do: to_string(atom)
test/gradient/elixir_checker_test.exs
@@ -23,16 +23,17 @@ defmodule Gradient.ElixirCheckerTest do
23
ast = load("Elixir.SpecWrongName.beam")
24
25
assert [
26
- {_, {:spec_error, :wrong_spec_name, 11, :last_two, 1}},
27
- {_, {:spec_error, :wrong_spec_name, 5, :convert, 1}}
+ {_, {:spec_error, :wrong_spec_name, 5, :convert, 1}},
+ {_, {:spec_error, :wrong_spec_name, 11, :last_two, 1}}
28
] = ElixirChecker.check(ast, [])
29
30
31
- test "more than one spec per function clause is not allowed" do
32
- ast = load("Elixir.SpecAfterSpec.beam")
+ test "mixing specs names is not allowed" do
+ ast = load("Elixir.SpecMixed.beam")
33
34
35
- {_, {:spec_error, :spec_after_spec, 3, :convert, 1}}
+ {_, {:spec_error, :mixed_specs, 3, :encode, 1}},
36
+ {_, {:spec_error, :wrong_spec_name, 3, :encode, 1}}
37
38
39
test/gradient/elixir_fmt_test.exs
@@ -251,11 +251,11 @@ defmodule Gradient.ElixirFmtTest do
251
252
test "follows another spec" do
253
msg =
254
- {:spec_error, :spec_after_spec, 3, :convert, 1}
+ {:spec_error, :mixed_specs, 3, :encode, 1}
255
|> ElixirFmt.format_error([])
256
|> :erlang.iolist_to_binary()
257
258
- assert "The spec convert/1 on line 3 follows another spec, but only one spec per function clause is allowed\n" =
+ assert "The spec encode/1 on line 3 follows a spec with different name/arity\n" =
259
msg
260
261
test/mix/tasks/gradient_test.exs
@@ -93,8 +93,8 @@ defmodule Mix.Tasks.GradientTest do
93
94
95
test "--no-ex-check option" do
96
- beam = Path.join(@build_path, "Elixir.SpecAfterSpec.beam")
97
- ex_spec_error_msg = "The spec convert/1 on line"
+ beam = Path.join(@build_path, "Elixir.SpecMixed.beam")
+ ex_spec_error_msg = "The spec encode/1 on line"
98
99
output = run_task(test_opts([beam]))
100
assert String.contains?(output, ex_spec_error_msg)
0 commit comments