diff --git a/CHANGELOG.md b/CHANGELOG.md index 009622afbf9..ad557c04537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [#8862](https://github.com/rubocop-hq/rubocop/issues/8862): Fix an error for `Lint/AmbiguousRegexpLiteral` when using regexp without method calls in nested structure. ([@koic][]) * [#8872](https://github.com/rubocop-hq/rubocop/issues/8872): Fix an error for `Metrics/ClassLength` when multiple assignments to constants. ([@koic][]) * [#8871](https://github.com/rubocop-hq/rubocop/issues/8871): Fix a false positive for `Style/RedundantBegin` when using `begin` for method argument or part of conditions. ([@koic][]) +* [#8875](https://github.com/rubocop-hq/rubocop/issues/8875): Fix an incorrect auto-correct for `Style/ClassEqualityComparison` when comparing class name. ([@koic][]) ## 0.93.0 (2020-10-08) diff --git a/lib/rubocop/cop/style/class_equality_comparison.rb b/lib/rubocop/cop/style/class_equality_comparison.rb index 57c3b533308..066a3221eef 100644 --- a/lib/rubocop/cop/style/class_equality_comparison.rb +++ b/lib/rubocop/cop/style/class_equality_comparison.rb @@ -21,7 +21,7 @@ class ClassEqualityComparison < Base include IgnoredMethods extend AutoCorrector - MSG = 'Use `Object.instance_of?` instead of comparing classes.' + MSG = 'Use `instance_of?(%s)` instead of comparing classes.' RESTRICT_ON_SEND = %i[== equal? eql?].freeze @@ -36,13 +36,28 @@ def on_send(node) return if def_node && ignored_method?(def_node.method_name) class_comparison_candidate?(node) do |receiver_node, class_node| - range = range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos) + range = offense_range(receiver_node, node) + class_name = class_name(class_node, node) - add_offense(range) do |corrector| - corrector.replace(range, "instance_of?(#{class_node.source})") + add_offense(range, message: format(MSG, class_name: class_name)) do |corrector| + corrector.replace(range, "instance_of?(#{class_name})") end end end + + private + + def class_name(class_node, node) + if node.children.first.method?(:name) + class_node.source.delete('"').delete("'") + else + class_node.source + end + end + + def offense_range(receiver_node, node) + range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos) + end end end end diff --git a/spec/rubocop/cop/style/class_equality_comparison_spec.rb b/spec/rubocop/cop/style/class_equality_comparison_spec.rb index b0261adb1e1..d402e0df67c 100644 --- a/spec/rubocop/cop/style/class_equality_comparison_spec.rb +++ b/spec/rubocop/cop/style/class_equality_comparison_spec.rb @@ -5,21 +5,58 @@ { 'IgnoredMethods' => [] } end - it 'registers an offense and corrects when comparing class for equality' do + it 'registers an offense and corrects when comparing class using `==` for equality' do expect_offense(<<~RUBY) var.class == Date - ^^^^^^^^^^^^^ Use `Object.instance_of?` instead of comparing classes. + ^^^^^^^^^^^^^ Use `instance_of?(Date)` instead of comparing classes. + RUBY + + expect_correction(<<~RUBY) + var.instance_of?(Date) + RUBY + end + + it 'registers an offense and corrects when comparing class using `equal?` for equality' do + expect_offense(<<~RUBY) var.class.equal?(Date) - ^^^^^^^^^^^^^^^^^^ Use `Object.instance_of?` instead of comparing classes. + ^^^^^^^^^^^^^^^^^^ Use `instance_of?(Date)` instead of comparing classes. + RUBY + + expect_correction(<<~RUBY) + var.instance_of?(Date) + RUBY + end + + it 'registers an offense and corrects when comparing class using `eql?` for equality' do + expect_offense(<<~RUBY) var.class.eql?(Date) - ^^^^^^^^^^^^^^^^ Use `Object.instance_of?` instead of comparing classes. + ^^^^^^^^^^^^^^^^ Use `instance_of?(Date)` instead of comparing classes. + RUBY + + expect_correction(<<~RUBY) + var.instance_of?(Date) RUBY end - it 'registers an offense and corrects when comparing class name for equality' do + it 'registers an offense and corrects when comparing single quoted class name for equality' do + expect_offense(<<~RUBY) + var.class.name == 'Date' + ^^^^^^^^^^^^^^^^^^^^ Use `instance_of?(Date)` instead of comparing classes. + RUBY + + expect_correction(<<~RUBY) + var.instance_of?(Date) + RUBY + end + + it 'registers an offense and corrects when comparing double quoted class name for equality' do expect_offense(<<~RUBY) var.class.name == "Date" - ^^^^^^^^^^^^^^^^^^^^ Use `Object.instance_of?` instead of comparing classes. + ^^^^^^^^^^^^^^^^^^^^ Use `instance_of?(Date)` instead of comparing classes. + RUBY + + expect_correction(<<~RUBY) + var.instance_of?(Date) RUBY end