forked from rubocop/rubocop-rails
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This converts `assert_not(obj.one?)` into `assert_not_predicate(obj, :one?)` These methods are rails-specific and not present by default in minitest. For users that prefer the `refute` method calls, `Rails/RefuteMethods` will correct this if configured that way. Both the code and tests are pretty much a one-to-one copy from rubocop-minitest.`RefutePredicate`
- Loading branch information
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#1155](https://github.com/rubocop/rubocop-rails/issues/1155): Add new `Rails/AssertNotPredicate` to convert `assert_not(obj.foo?)` into `assert_not_predicate(obj, :foo?)`. ([@earlopain][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Rails | ||
# Prefer assert_not_predicate(obj, :foo?) over assert_not(obj.foo?) | ||
# | ||
# @example | ||
# # bad | ||
# assert_not(obj.one?) | ||
# assert_not(obj.one?, 'message') | ||
# | ||
# # good | ||
# assert_not_predicate(obj, :one?) | ||
# assert_not_predicate(obj, :one?, 'message') | ||
# | ||
class AssertNotPredicate < Base | ||
# NOTE: Code lifted from rubocop-minitest `PredicateAssertionHandleable` | ||
extend AutoCorrector | ||
|
||
MSG = 'Prefer using `%<assertion_type>s_predicate(%<new_arguments>s)`.' | ||
RESTRICT_ON_SEND = [:assert_not].freeze | ||
|
||
def assertion_type | ||
:assert_not | ||
end | ||
|
||
def on_send(node) | ||
return unless node.first_argument | ||
return if node.first_argument.block_type? || node.first_argument.numblock_type? | ||
return unless predicate_method?(node.first_argument) | ||
return unless node.first_argument.arguments.count.zero? | ||
|
||
add_offense(node, message: offense_message(node.arguments)) do |corrector| | ||
autocorrect(corrector, node, node.arguments) | ||
end | ||
end | ||
|
||
def autocorrect(corrector, node, arguments) | ||
corrector.replace(node.loc.selector, "#{assertion_type}_predicate") | ||
|
||
new_arguments = new_arguments(arguments).join(', ') | ||
|
||
corrector.replace(node.first_argument, new_arguments) | ||
end | ||
|
||
private | ||
|
||
def predicate_method?(first_argument) | ||
first_argument.respond_to?(:predicate_method?) && first_argument.predicate_method? | ||
end | ||
|
||
def offense_message(arguments) | ||
message_argument = arguments.last if arguments.first != arguments.last | ||
|
||
new_arguments = [new_arguments(arguments), message_argument&.source].flatten.compact.join(', ') | ||
|
||
format(MSG, assertion_type: assertion_type, new_arguments: new_arguments) | ||
end | ||
|
||
def new_arguments(arguments) | ||
receiver = correct_receiver(arguments.first.receiver) | ||
method_name = arguments.first.method_name | ||
|
||
[receiver, ":#{method_name}"] | ||
end | ||
|
||
def correct_receiver(receiver) | ||
receiver ? receiver.source : 'self' | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Rails::AssertNotPredicate, :config do | ||
it 'registers an offense when using assert_not with predicate method' do | ||
expect_offense(<<~RUBY) | ||
assert_not(obj.one?) | ||
^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_not_predicate(obj, :one?)`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
assert_not_predicate(obj, :one?) | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using assert_not with predicate method and message' do | ||
expect_offense(<<~RUBY) | ||
assert_not(obj.one?, 'message') | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_not_predicate(obj, :one?, 'message')`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
assert_not_predicate(obj, :one?, 'message') | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using assert_not with predicate method and heredoc message' do | ||
expect_offense(<<~RUBY) | ||
assert_not(obj.one?, <<~MESSAGE) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_not_predicate(obj, :one?, <<~MESSAGE)`. | ||
message | ||
MESSAGE | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
assert_not_predicate(obj, :one?, <<~MESSAGE) | ||
message | ||
MESSAGE | ||
RUBY | ||
end | ||
|
||
it 'registers and offense when using assert_not with receiver omitted predicate method' do | ||
expect_offense(<<~RUBY) | ||
assert_not(one?) | ||
^^^^^^^^^^^^^^^^ Prefer using `assert_not_predicate(self, :one?)`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
assert_not_predicate(self, :one?) | ||
RUBY | ||
end | ||
|
||
it 'registers no offense when using assert_not_predicate method' do | ||
expect_no_offenses(<<~RUBY) | ||
assert_not_predicate(obj, :one?) | ||
RUBY | ||
end | ||
|
||
it 'registers no offense when using assert_not with non predicate method' do | ||
expect_no_offenses(<<~RUBY) | ||
assert_not(obj.do_something) | ||
RUBY | ||
end | ||
|
||
it 'registers no offense when using assert_not with local variable' do | ||
expect_no_offenses(<<~RUBY) | ||
obj = create_obj | ||
assert_not(obj) | ||
RUBY | ||
end | ||
|
||
it 'registers no offense when using assert_not_predicate with predicate method and arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
assert_not(obj.foo?(arg)) | ||
RUBY | ||
end | ||
|
||
it 'registers no offense when using assert_not with predicate method and numbered arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
assert_not([1, 2, 3].any? { some_filter_function _1 }) | ||
RUBY | ||
end | ||
|
||
it 'raises no error when using assert_not with block' do | ||
expect_no_offenses(<<~RUBY) | ||
assert_not { false } | ||
RUBY | ||
end | ||
end |