Add RuboCop for `assert_not` over `assert !`
We added `assert_not` inf75addd
"to replace warty 'assert !foo'".fa8d35b
agrees that it is warty, and so do I. This custom Rubocop rule turns the wart into a violation. As with my last custom cop, https://github.com/rails/rails/pull/32441, I want to make sure this looks right on code climate before pushing another commit to autocorrect everything. @toshimaru I just noticed https://github.com/toshimaru/rubocop-rails/pull/26 Is there a better way to add these custom cops, or were you saying we shouldn't have custom cops at all?
This commit is contained in:
parent
ef2af628a9
commit
087e0ccb72
|
@ -15,6 +15,11 @@ CustomCops/RefuteNot:
|
||||||
Include:
|
Include:
|
||||||
- '**/*_test.rb'
|
- '**/*_test.rb'
|
||||||
|
|
||||||
|
# Prefer assert_not over assert !
|
||||||
|
CustomCops/AssertNot:
|
||||||
|
Include:
|
||||||
|
- '**/*_test.rb'
|
||||||
|
|
||||||
# Prefer &&/|| over and/or.
|
# Prefer &&/|| over and/or.
|
||||||
Style/AndOr:
|
Style/AndOr:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "custom_cops/refute_not"
|
require_relative "custom_cops/refute_not"
|
||||||
|
require_relative "custom_cops/assert_not"
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CustomCops
|
||||||
|
# Enforces the use of `assert_not` over `assert !`.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# assert !x
|
||||||
|
# assert ! x
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# assert_not x
|
||||||
|
#
|
||||||
|
class AssertNot < RuboCop::Cop::Cop
|
||||||
|
MSG = "Prefer `assert_not` over `assert !`"
|
||||||
|
|
||||||
|
def_node_matcher :offensive?, "(send nil? :assert (send ... :!))"
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
add_offense(node) if offensive?(node)
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(node)
|
||||||
|
expression = node.loc.expression
|
||||||
|
|
||||||
|
->(corrector) do
|
||||||
|
corrector.replace(
|
||||||
|
expression,
|
||||||
|
corrected_source(expression.source)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def corrected_source(source)
|
||||||
|
source.gsub(/^assert(\(| ) *! */, "assert_not\\1")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "support/cop_helper"
|
||||||
|
require_relative "../../lib/custom_cops/assert_not"
|
||||||
|
|
||||||
|
class AssertNotTest < ActiveSupport::TestCase
|
||||||
|
include CopHelper
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@cop = CustomCops::AssertNot.new
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects 'assert !'" do
|
||||||
|
inspect_source @cop, "assert !x"
|
||||||
|
assert_offense @cop, "^^^^^^^^^ Prefer `assert_not` over `assert !`"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects 'assert !' with a complex value" do
|
||||||
|
inspect_source @cop, "assert !a.b(c)"
|
||||||
|
assert_offense @cop, "^^^^^^^^^^^^^^ Prefer `assert_not` over `assert !`"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "autocorrects `assert !`" do
|
||||||
|
corrected = autocorrect_source(@cop, "assert !false")
|
||||||
|
assert_equal "assert_not false", corrected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "autocorrects `assert !` with extra spaces" do
|
||||||
|
corrected = autocorrect_source(@cop, "assert ! false")
|
||||||
|
assert_equal "assert_not false", corrected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "autocorrects `assert !` with parentheses" do
|
||||||
|
corrected = autocorrect_source(@cop, "assert(!false)")
|
||||||
|
assert_equal "assert_not(false)", corrected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accepts `assert_not`" do
|
||||||
|
inspect_source @cop, "assert_not x"
|
||||||
|
assert_empty @cop.offenses
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "support/cop_helper"
|
require "support/cop_helper"
|
||||||
require "./lib/custom_cops/refute_not"
|
require_relative "../../lib/custom_cops/refute_not"
|
||||||
|
|
||||||
class RefuteNotTest < ActiveSupport::TestCase
|
class RefuteNotTest < ActiveSupport::TestCase
|
||||||
include CopHelper
|
include CopHelper
|
||||||
|
@ -59,15 +59,6 @@ class RefuteNotTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def assert_offense(cop, expected_message)
|
|
||||||
assert_not_empty cop.offenses
|
|
||||||
|
|
||||||
offense = cop.offenses.first
|
|
||||||
carets = "^" * offense.column_length
|
|
||||||
|
|
||||||
assert_equal expected_message, "#{carets} #{offense.message}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def offense_message(refute_method, assert_method)
|
def offense_message(refute_method, assert_method)
|
||||||
carets = "^" * refute_method.to_s.length
|
carets = "^" * refute_method.to_s.length
|
||||||
"#{carets} Prefer `#{assert_method}` over `#{refute_method}`"
|
"#{carets} Prefer `#{assert_method}` over `#{refute_method}`"
|
||||||
|
|
|
@ -16,6 +16,18 @@ module CopHelper
|
||||||
rewrite(cop, processed_source)
|
rewrite(cop, processed_source)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assert_offense(cop, expected_message)
|
||||||
|
assert_not_empty(
|
||||||
|
cop.offenses,
|
||||||
|
"Expected offense with message \"#{expected_message}\", but got no offense"
|
||||||
|
)
|
||||||
|
|
||||||
|
offense = cop.offenses.first
|
||||||
|
carets = "^" * offense.column_length
|
||||||
|
|
||||||
|
assert_equal expected_message, "#{carets} #{offense.message}"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
TARGET_RUBY_VERSION = 2.4
|
TARGET_RUBY_VERSION = 2.4
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue