Skip to content

Commit 55d31c2

Browse files
committed
Refactor MatchInCondition
1 parent 747c6bc commit 55d31c2

File tree

2 files changed

+81
-65
lines changed

2 files changed

+81
-65
lines changed

lib/credo/check/refactor/match_in_condition.ex

Lines changed: 51 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ defmodule Credo.Check.Refactor.MatchInCondition do
3232
do_something(contents)
3333
end
3434
35-
if contents = file.contents && allowed? do
36-
do_something(contents)
37-
end
38-
3935
If you want to match for something and execute another block otherwise,
4036
consider using a `case` statement:
4137
@@ -53,9 +49,6 @@ defmodule Credo.Check.Refactor.MatchInCondition do
5349
]
5450
]
5551

56-
@condition_ops [:if, :unless]
57-
@trigger "="
58-
5952
@doc false
6053
@impl true
6154
def run(%SourceFile{} = source_file, params) do
@@ -65,81 +58,74 @@ defmodule Credo.Check.Refactor.MatchInCondition do
6558
Credo.Code.prewalk(source_file, &traverse(&1, &2, allow_tagged_tuples, issue_meta))
6659
end
6760

68-
# Skip if arguments is not enumerable
69-
defp traverse({_op, _meta, nil} = ast, issues, _allow_tagged_tuples, _source_file) do
61+
defp traverse({op, _, nil} = ast, issues, _allow_tagged_tuples, _issue_meta)
62+
when op in [:if, :unless] do
7063
{ast, issues}
7164
end
7265

73-
for op <- @condition_ops do
74-
defp traverse({unquote(op), _meta, arguments} = ast, issues, allow_tagged_tuples, issue_meta) do
75-
# remove do/else blocks
76-
condition_arguments = Enum.reject(arguments, &Keyword.keyword?/1)
77-
78-
new_issues =
79-
Credo.Code.prewalk(
80-
condition_arguments,
81-
&traverse_condition(
82-
&1,
83-
&2,
84-
unquote(op),
85-
condition_arguments,
86-
allow_tagged_tuples,
87-
issue_meta
88-
)
89-
)
90-
91-
{ast, issues ++ new_issues}
92-
end
66+
defp traverse({op, _, arguments} = ast, issues, allow_tagged_tuples, issue_meta)
67+
when op in [:if, :unless] do
68+
condition_head = Enum.reject(arguments, &Keyword.keyword?/1)
69+
70+
new_issues =
71+
Credo.Code.prewalk(
72+
condition_head,
73+
&find_match(&1, &2, op, condition_head, allow_tagged_tuples, issue_meta)
74+
)
75+
76+
{ast, issues ++ new_issues}
9377
end
9478

9579
defp traverse(ast, issues, _allow_tagged_tuples, _source_file) do
9680
{ast, issues}
9781
end
9882

99-
defp traverse_condition(
100-
{:=, meta, arguments} = ast,
83+
defp find_match(
84+
{:=, meta, [{var_name, _, nil}, rhs]} = ast,
10185
issues,
10286
op,
10387
op_arguments,
104-
allow_tagged_tuples?,
88+
_allow_tagged_tuples?,
10589
issue_meta
106-
) do
90+
)
91+
when is_atom(var_name) do
10792
assignment_in_body? = Enum.member?(op_arguments, ast)
93+
has_boolean_ops? = contains_boolean_operators?(rhs)
94+
95+
if assignment_in_body? or has_boolean_ops? do
96+
if has_boolean_ops? do
97+
{ast, issues ++ [issue_for(op, meta[:line], issue_meta)]}
98+
else
99+
{ast, issues}
100+
end
101+
else
102+
{ast, issues ++ [issue_for(op, meta[:line], issue_meta)]}
103+
end
104+
end
108105

109-
case arguments do
110-
[{atom, _, nil}, right] when is_atom(atom) ->
111-
# Check if right side contains boolean operators mixed with assignment
112-
has_boolean_ops? = contains_boolean_operators?(right)
113-
114-
if assignment_in_body? or has_boolean_ops? do
115-
if has_boolean_ops? do
116-
new_issue = issue_for(op, meta[:line], issue_meta)
117-
{ast, issues ++ [new_issue]}
118-
else
119-
{ast, issues}
120-
end
121-
else
122-
new_issue = issue_for(op, meta[:line], issue_meta)
123-
124-
{ast, issues ++ [new_issue]}
125-
end
126-
127-
[{tag_atom, {atom, _, nil}}, _right] when is_atom(atom) and is_atom(tag_atom) ->
128-
if allow_tagged_tuples? do
129-
{ast, issues}
130-
else
131-
new_issue = issue_for(op, meta[:line], issue_meta)
132-
133-
{ast, issues ++ [new_issue]}
134-
end
135-
136-
_ ->
137-
new_issue = issue_for(op, meta[:line], issue_meta)
138-
{ast, issues ++ [new_issue]}
106+
defp find_match(
107+
{:=, meta, [{tag_atom, {var_name, _, nil}}, _rhs]} = ast,
108+
issues,
109+
op,
110+
_op_args,
111+
allow_tagged_tuples?,
112+
issue_meta
113+
)
114+
when is_atom(var_name) and is_atom(tag_atom) do
115+
if allow_tagged_tuples? do
116+
{ast, issues}
117+
else
118+
new_issue = issue_for(op, meta[:line], issue_meta)
119+
120+
{ast, issues ++ [new_issue]}
139121
end
140122
end
141123

142-
defp traverse_condition(ast, issues, _op, _op_arguments, _allow_tagged_tuples, _issue_meta) do
124+
defp find_match({:=, meta, _} = ast, issues, op, _op_args, _allow_tagged_tuples, issue_meta) do
125+
{ast, issues ++ [issue_for(op, meta[:line], issue_meta)]}
126+
end
127+
128+
defp find_match(ast, issues, _op, _op_args, _allow_tagged_tuples, _issue_meta) do
143129
{ast, issues}
144130
end
145131

@@ -155,7 +141,7 @@ defmodule Credo.Check.Refactor.MatchInCondition do
155141
format_issue(
156142
issue_meta,
157143
message: "Avoid matches in `#{op}` conditions.",
158-
trigger: @trigger,
144+
trigger: "=",
159145
line_no: line_no
160146
)
161147
end

test/credo/check/refactor/match_in_condition_test.exs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,21 @@ defmodule Credo.Check.Refactor.MatchInConditionTest do
132132
end
133133

134134
test "it should report a violation /4" do
135+
"""
136+
defmodule CredoSampleModule do
137+
def some_function(parameter1, parameter2) do
138+
if (contents = parameter1.contents) && parameter2 do
139+
do_something()
140+
end
141+
end
142+
end
143+
"""
144+
|> to_source_file
145+
|> run_check(@described_check)
146+
|> assert_issue()
147+
end
148+
149+
test "it should report a violation /5" do
135150
"""
136151
defmodule CredoSampleModule do
137152
def some_function(parameter1, parameter2) do
@@ -146,6 +161,21 @@ defmodule Credo.Check.Refactor.MatchInConditionTest do
146161
|> assert_issue()
147162
end
148163

164+
test "it should report a violation /6" do
165+
"""
166+
defmodule CredoSampleModule do
167+
def some_function(a, b) do
168+
if foo = bar(a && b) do
169+
do_something()
170+
end
171+
end
172+
end
173+
"""
174+
|> to_source_file
175+
|> run_check(@described_check)
176+
|> assert_issue()
177+
end
178+
149179
test "it should report a violation when wrapped in parens" do
150180
"""
151181
defmodule CredoSampleModule do

0 commit comments

Comments
 (0)