Skip to content

Commit

Permalink
Add Lint/DuplicateWhenCondition rule
Browse files Browse the repository at this point in the history
  • Loading branch information
Sija committed Feb 17, 2025
1 parent db1b386 commit 7921890
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
45 changes: 45 additions & 0 deletions spec/ameba/rule/lint/duplicate_when_condition_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "../../../spec_helper"

module Ameba::Rule::Lint
describe DuplicateWhenCondition do
subject = DuplicateWhenCondition.new

it "passes if there are no duplicated `when` conditions" do
expect_no_issues subject, <<-CRYSTAL
case x
when .nil?
do_something
when Symbol
do_something_else
end
CRYSTAL
end

it "reports if there are a duplicated `when` conditions" do
expect_issue subject, <<-CRYSTAL
case x
when .foo?, .nil?
do_something
when .nil?
# ^^^^^ error: Duplicate `when` condition detected
do_something_else
end
CRYSTAL

expect_issue subject, <<-CRYSTAL
case
when foo?
:foo
when foo?, bar?
# ^^^^ error: Duplicate `when` condition detected
:foobar
when Time.utc.year == 1996
:yo
when Time.utc.year == 1996
# ^^^^^^^^^^^^^^^^^^^^^ error: Duplicate `when` condition detected
:yo
end
CRYSTAL
end
end
end
53 changes: 53 additions & 0 deletions src/ameba/rule/lint/duplicate_when_condition.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Ameba::Rule::Lint
# Reports repeated conditions used in case `when` expressions.
#
# This is considered invalid:
#
# ```
# case x
# when .nil?
# do_something
# when .nil?
# do_something_else
# end
# ```
#
# And this is valid:
#
# ```
# case x
# when .nil?
# do_something
# when Symbol
# do_something_else
# end
# ```
#
# YAML configuration example:
#
# ```
# Lint/DuplicateWhenCondition:
# Enabled: true
# ```
class DuplicateWhenCondition < Base
properties do
since_version "1.7.0"
description "Reports repeated conditions used in case `when` expressions"
end

MSG = "Duplicate `when` condition detected"

def test(source, node : Crystal::Case)
node.whens.each_with_object(Set(String).new) do |when_node, processed_conditions|
when_node.conds.each do |cond|
cond_s = cond.to_s
if processed_conditions.includes?(cond_s)
issue_for cond, MSG
else
processed_conditions << cond_s
end
end
end
end
end
end

0 comments on commit 7921890

Please sign in to comment.