diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f9c852a7b..852101fae06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ * [#8474](https://github.com/rubocop-hq/rubocop/pull/8474): Add new `Lint/DuplicateRequire` cop. ([@fatkodima][]) +### Bug fixes + +* [#8508](https://github.com/rubocop-hq/rubocop/pull/8508): Fix a false positive for `Style/CaseLikeIf` when conditional contains comparison with a class. Mark `Style/CaseLikeIf` as not safe. ([@fatkodima][]) + ### Changes * [#8362](https://github.com/rubocop-hq/rubocop/issues/8362): Add numbers of correctable offenses to summary. ([@nguyenquangminh0711][]) diff --git a/config/default.yml b/config/default.yml index 8cae2bd6398..fe0c98a738d 100644 --- a/config/default.yml +++ b/config/default.yml @@ -2596,6 +2596,7 @@ Style/CaseLikeIf: Description: 'This cop identifies places where `if-elsif` constructions can be replaced with `case-when`.' StyleGuide: '#case-vs-if-else' Enabled: 'pending' + Safe: false VersionAdded: '0.88' Style/CharacterLiteral: diff --git a/docs/modules/ROOT/pages/cops_style.adoc b/docs/modules/ROOT/pages/cops_style.adoc index 5e2bb89bbfd..62bd7850258 100644 --- a/docs/modules/ROOT/pages/cops_style.adoc +++ b/docs/modules/ROOT/pages/cops_style.adoc @@ -865,8 +865,8 @@ some_string =~ /something/ | Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged | Pending -| Yes -| Yes +| No +| Yes (Unsafe) | 0.88 | - |=== diff --git a/lib/rubocop/cop/style/case_like_if.rb b/lib/rubocop/cop/style/case_like_if.rb index 5d18fd4af2f..3fe33176a8a 100644 --- a/lib/rubocop/cop/style/case_like_if.rb +++ b/lib/rubocop/cop/style/case_like_if.rb @@ -159,9 +159,10 @@ def condition_from_send_node(node, target) case node.method_name when :is_a? node.arguments.first if node.receiver == target - when :==, :eql?, :equal?, :=~, :match, :match? - lhs, _method, rhs = *node - condition_from_binary_op(lhs, rhs, target) + when :==, :eql?, :equal? + condition_from_equality_node(node, target) + when :=~, :match, :match? + condition_from_match_node(node, target) when :=== lhs, _method, rhs = *node lhs if rhs == target @@ -172,6 +173,17 @@ def condition_from_send_node(node, target) end # rubocop:enable Metrics/CyclomaticComplexity + def condition_from_equality_node(node, target) + lhs, _method, rhs = *node + condition = condition_from_binary_op(lhs, rhs, target) + condition if condition && !class_reference?(condition) + end + + def condition_from_match_node(node, target) + lhs, _method, rhs = *node + condition_from_binary_op(lhs, rhs, target) + end + def condition_from_binary_op(lhs, rhs, target) lhs = deparenthesize(lhs) rhs = deparenthesize(rhs) @@ -202,6 +214,10 @@ def const_reference?(node) name == name.upcase end + def class_reference?(node) + node.const_type? && node.children[1].match?(/[[:lower:]]/) + end + def deparenthesize(node) node = node.children.last while node.begin_type? node diff --git a/spec/rubocop/cop/style/case_like_if_spec.rb b/spec/rubocop/cop/style/case_like_if_spec.rb index 18ce2f19e5f..05025c8d467 100644 --- a/spec/rubocop/cop/style/case_like_if_spec.rb +++ b/spec/rubocop/cop/style/case_like_if_spec.rb @@ -77,6 +77,15 @@ RUBY end + it 'does not register an offense when one of the branches contains `==` with class reference' do + expect_no_offenses(<<~RUBY) + if x == 1 + elsif x == Foo + else + end + RUBY + end + it 'does not register an offense when using `==` with constant containing 1 letter in name' do expect_no_offenses(<<~RUBY) if x == F