Skip to content

Commit

Permalink
code and test
Browse files Browse the repository at this point in the history
  • Loading branch information
quangngd committed Mar 24, 2024
1 parent 3fb97c5 commit 7b7a6ae
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 14 deletions.
60 changes: 46 additions & 14 deletions lib/credo/check/readability/predicate_function_names.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,41 +52,73 @@ defmodule Credo.Check.Readability.PredicateFunctionNames do
def run(%SourceFile{} = source_file, params) do
issue_meta = IssueMeta.for(source_file, params)

Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
impl_list = Credo.Code.prewalk(source_file, &find_impls(&1, &2))

Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta, impl_list))
end

defp find_impls({:impl, _, [impl]} = ast, impls) when impl != false do
{ast, [:impl | impls]}
end

# def when
defp find_impls({keyword, meta, [{:when, _, def_ast} | _]}, [:impl | impls])
when keyword in @def_ops do
find_impls({keyword, meta, def_ast}, [:impl | impls])
end

# def 0 arity
defp find_impls({keyword, _meta, [{name, _, nil} | _]} = ast, [:impl | impls])
when keyword in @def_ops do
{ast, [{name, 0} | impls]}
end

# def n arity
defp find_impls({keyword, _meta, [{name, _, args} | _]} = ast, [:impl | impls])
when keyword in @def_ops do
{ast, [{name, length(args)} | impls]}
end

defp find_impls(ast, impls) do
{ast, impls}
end

for op <- @def_ops do
# catch variables named e.g. `defp`
defp traverse({unquote(op), _meta, nil} = ast, issues, _issue_meta) do
defp traverse({unquote(op), _meta, nil} = ast, issues, _issue_meta, _impl_list) do
{ast, issues}
end

defp traverse(
{unquote(op) = op, _meta, arguments} = ast,
issues,
issue_meta
issue_meta,
impl_list
) do
{ast, issues_for_definition(op, arguments, issues, issue_meta)}
{ast, issues_for_definition(op, arguments, issues, issue_meta, impl_list)}
end
end

defp traverse(ast, issues, _issue_meta) do
defp traverse(ast, issues, _issue_meta, _impl_list) do
{ast, issues}
end

defp issues_for_definition(op, body, issues, issue_meta) do
case Enum.at(body, 0) do
{name, meta, nil} ->
issues_for_name(op, name, meta, issues, issue_meta)

{name, meta, [_ | _]} ->
issues_for_name(op, name, meta, issues, issue_meta)
defp issues_for_definition(op, [{name, meta, nil} | _], issues, issue_meta, impl_list) do
issues_for_definition(op, [{name, meta, []}], issues, issue_meta, impl_list)
end

_ ->
issues
defp issues_for_definition(op, [{name, meta, args} | _], issues, issue_meta, impl_list) do
if {name, length(args)} not in impl_list do

Check failure

Code scanning / Credo

Avoid negated conditions in if-else blocks. Error

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.16.1 OTP 26.2

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.15.7 OTP 26.1

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.13.4 OTP 25.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.13.4 OTP 24.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.15.7 OTP 25.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.14.5 OTP 24.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.12.3 OTP 24.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.11.4 OTP 24.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Compile & Run

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.14.5 OTP 23.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.13.4 OTP 23.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.11.4 OTP 23.3

Avoid negated conditions in if-else blocks.

Check warning on line 111 in lib/credo/check/readability/predicate_function_names.ex

View workflow job for this annotation

GitHub Actions / Elixir 1.12.3 OTP 23.3

Avoid negated conditions in if-else blocks.
issues_for_name(op, name, meta, issues, issue_meta)
else
issues
end
end

defp issues_for_definition(_op, _, issues, _issue_meta, _impl_list) do
issues
end

defp issues_for_name(_op, {:unquote, _, [_ | _]} = _name, _meta, issues, _issue_meta) do
issues
end
Expand Down
28 changes: 28 additions & 0 deletions test/credo/check/readability/predicate_function_names_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ defmodule Credo.Check.Readability.PredicateFunctionNamesTest do
|> refute_issues()
end

test "it should NOT report a violation with callback" do
"""
defmodule Foo do
@callback is_bar
@callback is_bar(a)
end
defmodule FooImpl do
@behaviour Foo
@impl Foo
def is_bar do
end
@impl Foo
def is_bar(a) when is_binary(a) do
end
@impl Foo
def is_bar(a) do
end
end
"""
|> to_source_file
|> run_check(@described_check)
|> refute_issues()
end

#
# cases raising issues
#
Expand Down

0 comments on commit 7b7a6ae

Please sign in to comment.