Skip to content

Commit cef51ea

Browse files
committed
Refactor ExpensiveEmptyEnumCheck
1 parent e781dbb commit cef51ea

File tree

1 file changed

+26
-56
lines changed

1 file changed

+26
-56
lines changed

lib/credo/check/warning/expensive_empty_enum_check.ex

Lines changed: 26 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ defmodule Credo.Check.Warning.ExpensiveEmptyEnumCheck do
55
explanations: [
66
# TODO: improve checkdoc
77
check: """
8-
Checking if the size of the enum is `0` can be very expensive, since you are
9-
determining the exact count of elements.
8+
Checking if the size of the enum is `0` (or not `0`) can be very expensive,
9+
since you are determining the exact count of elements.
1010
1111
Checking if an enum is empty should be done by using
1212
@@ -17,7 +17,7 @@ defmodule Credo.Check.Warning.ExpensiveEmptyEnumCheck do
1717
list == []
1818
1919
20-
For Enum.count/2: Checking if an enum doesn't contain specific elements should
20+
For `Enum.count/2`: Checking if an enum doesn't contain specific elements should
2121
be done by using
2222
2323
not Enum.any?(enum, condition)
@@ -28,9 +28,9 @@ defmodule Credo.Check.Warning.ExpensiveEmptyEnumCheck do
2828
@doc false
2929
@impl true
3030
def run(%SourceFile{} = source_file, params) do
31-
issue_meta = IssueMeta.for(source_file, params)
32-
33-
Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
31+
ctx = Context.build(source_file, params, __MODULE__)
32+
result = Credo.Code.prewalk(source_file, &walk/2, ctx)
33+
result.issues
3434
end
3535

3636
@enum_count_pattern quote do: {
@@ -43,74 +43,44 @@ defmodule Credo.Check.Warning.ExpensiveEmptyEnumCheck do
4343
{@enum_count_pattern, "Enum.count"},
4444
{@length_pattern, "length"}
4545
]
46-
@eq_operators [:==, :!=, :===, :!==, :>, :<]
47-
48-
# Comparisons against 0
49-
for {pattern, trigger} <- @comparisons,
50-
operator <- @eq_operators do
51-
defp traverse(
52-
{unquote(operator), _meta, [unquote(pattern), 0]} = ast,
53-
issues,
54-
issue_meta
55-
) do
56-
{ast, issues_for_call(unquote(trigger), issues, issue_meta, ast)}
57-
end
46+
@operators [:==, :!=, :===, :!==, :>, :<]
5847

59-
defp traverse(
60-
{unquote(operator), _meta, [0, unquote(pattern)]} = ast,
61-
issues,
62-
issue_meta
63-
) do
64-
{ast, issues_for_call(unquote(trigger), issues, issue_meta, ast)}
48+
for {pattern, trigger} <- @comparisons do
49+
# Comparisons against 0
50+
defp walk({op, meta, [unquote(pattern), 0]} = ast, ctx) when op in @operators do
51+
{ast, put_issue(ctx, issue_for(ctx, meta, unquote(trigger), suggest(ast)))}
6552
end
66-
end
6753

68-
# Comparisons against 1
69-
for {pattern, trigger} <- @comparisons do
70-
defp traverse(
71-
{:>=, _meta, [unquote(pattern), 1]} = ast,
72-
issues,
73-
issue_meta
74-
) do
75-
{ast, issues_for_call(unquote(trigger), issues, issue_meta, ast)}
54+
defp walk({op, meta, [0, unquote(pattern)]} = ast, ctx) when op in @operators do
55+
{ast, put_issue(ctx, issue_for(ctx, meta, unquote(trigger), suggest(ast)))}
7656
end
7757

78-
defp traverse(
79-
{:<=, _meta, [1, unquote(pattern)]} = ast,
80-
issues,
81-
issue_meta
82-
) do
83-
{ast, issues_for_call(unquote(trigger), issues, issue_meta, ast)}
58+
# Comparisons against 1
59+
defp walk({:>=, meta, [unquote(pattern), 1]} = ast, ctx) do
60+
{ast, put_issue(ctx, issue_for(ctx, meta, unquote(trigger), suggest(ast)))}
8461
end
85-
end
8662

87-
defp traverse(ast, issues, _issue_meta) do
88-
{ast, issues}
63+
defp walk({:<=, meta, [1, unquote(pattern)]} = ast, ctx) do
64+
{ast, put_issue(ctx, issue_for(ctx, meta, unquote(trigger), suggest(ast)))}
65+
end
8966
end
9067

91-
defp issues_for_call(trigger, issues, issue_meta, ast) do
92-
meta = get_meta(ast)
93-
[issue_for(issue_meta, meta, trigger, suggest(ast)) | issues]
68+
defp walk(ast, ctx) do
69+
{ast, ctx}
9470
end
9571

9672
defp suggest({_op, _, [_, {_pattern, _, args}]}), do: suggest_for_arity(Enum.count(args))
9773
defp suggest({_op, _, [{_pattern, _, args}, _]}), do: suggest_for_arity(Enum.count(args))
9874

99-
defp get_meta({_op, _, [_, {{:., _, [{:__aliases__, meta, _}, _]}, _, _}]}), do: meta
100-
defp get_meta({_op, _, [_, {_, meta, _}]}), do: meta
101-
defp get_meta({_op, _, [{{:., _, [{:__aliases__, meta, _}, _]}, _, _}, _]}), do: meta
102-
defp get_meta({_op, _, [{_, meta, _}, _]}), do: meta
103-
10475
defp suggest_for_arity(2), do: "`not Enum.any?/2`"
105-
defp suggest_for_arity(1), do: "`Enum.empty?/1` or `list == []`"
76+
defp suggest_for_arity(1), do: "`Enum.empty?/1`"
10677

107-
defp issue_for(issue_meta, meta, trigger, suggestion) do
78+
defp issue_for(ctx, meta, trigger, suggestion) do
10879
format_issue(
109-
issue_meta,
110-
message: "#{trigger} is expensive, prefer #{suggestion}.",
80+
ctx,
81+
message: "Using `#{trigger}/1` is expensive, prefer #{suggestion}.",
11182
trigger: trigger,
112-
line_no: meta[:line],
113-
column: meta[:column]
83+
line_no: meta[:line]
11484
)
11585
end
11686
end

0 commit comments

Comments
 (0)