Skip to content

Commit

Permalink
Merge pull request #955 from rubocop-hq/new-rubocop-autocorrect
Browse files Browse the repository at this point in the history
New RuboCop autocorrect
  • Loading branch information
bquorning committed Jul 9, 2020
2 parents e6857d8 + ac953d8 commit b53f08a
Show file tree
Hide file tree
Showing 54 changed files with 385 additions and 522 deletions.
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Expand Up @@ -14,4 +14,4 @@ InternalAffairs/MethodNameEqual:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 104
Max: 106
29 changes: 11 additions & 18 deletions lib/rubocop/cop/rspec/align_left_let_brace.rb
Expand Up @@ -18,35 +18,28 @@ module RSpec
# let(:a) { b }
#
class AlignLeftLetBrace < Cop
extend AutoCorrector

MSG = 'Align left let brace'

def self.autocorrect_incompatible_with
[Layout::ExtraSpacing]
end

def investigate(_processed_source)
def on_new_investigation
return if processed_source.blank?

token_aligner.offending_tokens.each do |let|
add_offense(let, location: :begin)
end
end
token_aligner =
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)

def autocorrect(let)
lambda do |corrector|
corrector.insert_before(
let.loc.begin,
token_aligner.indent_for(let)
)
token_aligner.offending_tokens.each do |let|
add_offense(let.loc.begin) do |corrector|
corrector.insert_before(
let.loc.begin, token_aligner.indent_for(let)
)
end
end
end

private

def token_aligner
@token_aligner ||=
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
end
end
end
end
Expand Down
29 changes: 11 additions & 18 deletions lib/rubocop/cop/rspec/align_right_let_brace.rb
Expand Up @@ -18,35 +18,28 @@ module RSpec
# let(:a) { b }
#
class AlignRightLetBrace < Cop
extend AutoCorrector

MSG = 'Align right let brace'

def self.autocorrect_incompatible_with
[Layout::ExtraSpacing]
end

def investigate(_processed_source)
def on_new_investigation
return if processed_source.blank?

token_aligner.offending_tokens.each do |let|
add_offense(let, location: :end)
end
end
token_aligner =
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)

def autocorrect(let)
lambda do |corrector|
corrector.insert_before(
let.loc.end,
token_aligner.indent_for(let)
)
token_aligner.offending_tokens.each do |let|
add_offense(let.loc.end) do |corrector|
corrector.insert_before(
let.loc.end, token_aligner.indent_for(let)
)
end
end
end

private

def token_aligner
@token_aligner ||=
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/be.rb
Expand Up @@ -28,7 +28,7 @@ class Be < Cop

def on_send(node)
be_without_args(node) do |matcher|
add_offense(matcher, location: :selector)
add_offense(matcher.loc.selector)
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions lib/rubocop/cop/rspec/be_eql.rb
Expand Up @@ -36,6 +36,8 @@ module RSpec
# coerce objects for comparison.
#
class BeEql < Cop
extend AutoCorrector

MSG = 'Prefer `be` over `eql`.'

def_node_matcher :eql_type_with_identity, <<-PATTERN
Expand All @@ -44,13 +46,11 @@ class BeEql < Cop

def on_send(node)
eql_type_with_identity(node) do |eql|
add_offense(eql, location: :selector)
add_offense(eql.loc.selector) do |corrector|
corrector.replace(eql.loc.selector, 'be')
end
end
end

def autocorrect(node)
->(corrector) { corrector.replace(node.loc.selector, 'be') }
end
end
end
end
Expand Down
34 changes: 18 additions & 16 deletions lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
Expand Up @@ -24,6 +24,8 @@ module Capybara
# expect(page).to have_current_path(/widgets/)
#
class CurrentPathExpectation < Cop
extend AutoCorrector

MSG = 'Do not set an RSpec expectation on `current_path` in ' \
'Capybara feature specs - instead, use the ' \
'`have_current_path` matcher on `page`'
Expand All @@ -47,30 +49,30 @@ class CurrentPathExpectation < Cop

def on_send(node)
expectation_set_on_current_path(node) do
add_offense(node, location: :selector)
add_offense(node.loc.selector) do |corrector|
next unless node.chained?

autocorrect(corrector, node)
end
end
end

def autocorrect(node)
lambda do |corrector|
return unless node.chained?
private

as_is_matcher(node.parent) do |to_sym, matcher_node|
rewrite_expectation(corrector, node, to_sym, matcher_node)
end
def autocorrect(corrector, node)
as_is_matcher(node.parent) do |to_sym, matcher_node|
rewrite_expectation(corrector, node, to_sym, matcher_node)
end

regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
rewrite_expectation(corrector, node, to_sym, matcher_node)
convert_regexp_str_to_literal(corrector, matcher_node, regexp)
end
regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
rewrite_expectation(corrector, node, to_sym, matcher_node)
convert_regexp_str_to_literal(corrector, matcher_node, regexp)
end
end

private

def rewrite_expectation(corrector, node, to_symbol, matcher_node)
current_path_node = node.first_argument
corrector.replace(current_path_node.loc.expression, 'page')
corrector.replace(current_path_node, 'page')
corrector.replace(node.parent.loc.selector, 'to')
matcher_method = if to_symbol == :to
'have_current_path'
Expand All @@ -84,7 +86,7 @@ def rewrite_expectation(corrector, node, to_symbol, matcher_node)
def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str)
str_node = matcher_node.first_argument
regexp_expr = Regexp.new(regexp_str).inspect
corrector.replace(str_node.loc.expression, regexp_expr)
corrector.replace(str_node, regexp_expr)
end

# `have_current_path` with no options will include the querystring
Expand All @@ -97,7 +99,7 @@ def add_ignore_query_options(corrector, node)
return if %i[regexp str].include?(expectation_last_child.type)

corrector.insert_after(
expectation_last_child.loc.expression,
expectation_last_child,
', ignore_query: true'
)
end
Expand Down
17 changes: 8 additions & 9 deletions lib/rubocop/cop/rspec/capybara/feature_methods.rb
Expand Up @@ -41,6 +41,8 @@ module Capybara
# end
# end
class FeatureMethods < Cop
extend AutoCorrector

MSG = 'Use `%<replacement>s` instead of `%<method>s`.'

# https://git.io/v7Kwr
Expand Down Expand Up @@ -71,18 +73,15 @@ def on_block(node)
feature_method(node) do |send_node, match|
next if enabled?(match)

add_offense(
send_node,
location: :selector,
message: format(MSG, method: match, replacement: MAP[match])
)
add_offense(send_node.loc.selector) do |corrector|
corrector.replace(send_node.loc.selector, MAP[match].to_s)
end
end
end

def autocorrect(node)
lambda do |corrector|
corrector.replace(node.loc.selector, MAP[node.method_name].to_s)
end
def message(range)
name = range.source.to_sym
format(MSG, method: name, replacement: MAP[name])
end

private
Expand Down
12 changes: 5 additions & 7 deletions lib/rubocop/cop/rspec/context_method.rb
Expand Up @@ -24,6 +24,8 @@ module RSpec
# # ...
# end
class ContextMethod < Cop
extend AutoCorrector

MSG = 'Use `describe` for testing methods.'

def_node_matcher :context_method, <<-PATTERN
Expand All @@ -32,13 +34,9 @@ class ContextMethod < Cop

def on_block(node)
context_method(node) do |context|
add_offense(context)
end
end

def autocorrect(node)
lambda do |corrector|
corrector.replace(node.parent.loc.selector, 'describe')
add_offense(context) do |corrector|
corrector.replace(node.send_node.loc.selector, 'describe')
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/cop.rb
Expand Up @@ -17,7 +17,7 @@ module RSpec
# # Patterns:
# # - '_test.rb$'
# # - '(?:^|/)test/'
class Cop < ::RuboCop::Cop::Cop
class Cop < ::RuboCop::Cop::Base
include RuboCop::RSpec::Language
include RuboCop::RSpec::Language::NodePattern

Expand Down
17 changes: 10 additions & 7 deletions lib/rubocop/cop/rspec/described_class.rb
Expand Up @@ -55,6 +55,7 @@ module RSpec
# end
#
class DescribedClass < Cop
extend AutoCorrector
include ConfigurableEnforcedStyle

DESCRIBED_CLASS = 'described_class'
Expand Down Expand Up @@ -85,22 +86,24 @@ def on_block(node)
return unless body

find_usage(body) do |match|
add_offense(match, message: message(match.const_name))
msg = message(match.const_name)
add_offense(match, message: msg) do |corrector|
autocorrect(corrector, match)
end
end
end

def autocorrect(node)
private

def autocorrect(corrector, match)
replacement = if style == :described_class
DESCRIBED_CLASS
else
@described_class.const_name
end
lambda do |corrector|
corrector.replace(node.loc.expression, replacement)
end
end

private
corrector.replace(match, replacement)
end

def find_usage(node, &block)
yield(node) if offensive?(node)
Expand Down
15 changes: 4 additions & 11 deletions lib/rubocop/cop/rspec/dialect.rb
Expand Up @@ -42,6 +42,7 @@ module RSpec
# # ...
# end
class Dialect < Cop
extend AutoCorrector
include MethodPreference

MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
Expand All @@ -52,24 +53,16 @@ def on_send(node)
return unless rspec_method?(node)
return unless preferred_methods[node.method_name]

add_offense(node)
end
msg = format(MSG, prefer: preferred_method(node.method_name),
current: node.method_name)

def autocorrect(node)
lambda do |corrector|
add_offense(node, message: msg) do |corrector|
current = node.loc.selector
preferred = preferred_method(current.source)

corrector.replace(current, preferred)
end
end

private

def message(node)
format(MSG, prefer: preferred_method(node.method_name),
current: node.method_name)
end
end
end
end
Expand Down
14 changes: 5 additions & 9 deletions lib/rubocop/cop/rspec/empty_hook.rb
Expand Up @@ -23,6 +23,7 @@ module RSpec
# end
# after(:all) { cleanup_feed }
class EmptyHook < Cop
extend AutoCorrector
include RuboCop::Cop::RangeHelp

MSG = 'Empty hook detected.'
Expand All @@ -33,15 +34,10 @@ class EmptyHook < Cop

def on_block(node)
empty_hook?(node) do |hook|
add_offense(hook)
end
end

def autocorrect(node)
lambda do |corrector|
block = node.parent
range = range_with_surrounding_space(range: block.loc.expression)
corrector.remove(range)
add_offense(hook) do |corrector|
range = range_with_surrounding_space(range: node.loc.expression)
corrector.remove(range)
end
end
end
end
Expand Down

0 comments on commit b53f08a

Please sign in to comment.