From 4fd778a7063f37e3ba21435097d162e3cd51de36 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 10 Aug 2020 22:51:23 +0900 Subject: [PATCH] Use `Cop::Base` API for `Style` department [R-S] Follow #7868. This PR uses `Cop::Base` API for almost `Style` department's R-S cops. It targets cop that names begin between R and S. And some R-S cops will be excluded from this PR target and addressed separately. --- lib/rubocop/cop/style/raise_args.rb | 37 +++++--------- lib/rubocop/cop/style/random_with_offset.rb | 31 ++++++------ lib/rubocop/cop/style/redundant_assignment.rb | 18 ++++--- lib/rubocop/cop/style/redundant_begin.rb | 16 +++---- lib/rubocop/cop/style/redundant_condition.rb | 11 ++--- .../cop/style/redundant_fetch_block.rb | 15 ++---- .../redundant_file_extension_in_require.rb | 16 +++---- lib/rubocop/cop/style/redundant_freeze.rb | 9 ++-- lib/rubocop/cop/style/regexp_literal.rb | 31 ++++-------- lib/rubocop/cop/style/return_nil.rb | 10 ++-- lib/rubocop/cop/style/safe_navigation.rb | 25 +++++----- lib/rubocop/cop/style/sample.rb | 23 ++++----- lib/rubocop/cop/style/self_assignment.rb | 48 ++++++++++--------- lib/rubocop/cop/style/semicolon.rb | 15 +++--- lib/rubocop/cop/style/send.rb | 4 +- lib/rubocop/cop/style/signal_exception.rb | 40 ++++++++-------- .../cop/style/single_line_block_params.rb | 6 ++- lib/rubocop/cop/style/single_line_methods.rb | 33 ++++++------- lib/rubocop/cop/style/slicing_with_range.rb | 11 ++--- lib/rubocop/cop/style/special_global_vars.rb | 25 ++++------ .../cop/style/stabby_lambda_parentheses.rb | 38 +++++++-------- lib/rubocop/cop/style/stderr_puts.rb | 10 ++-- lib/rubocop/cop/style/string_hash_keys.rb | 13 +++-- lib/rubocop/cop/style/string_methods.rb | 24 +++------- lib/rubocop/cop/style/strip.rb | 22 ++++----- lib/rubocop/cop/style/struct_inheritance.rb | 9 ++-- lib/rubocop/cop/style/symbol_literal.rb | 10 ++-- lib/rubocop/cop/style/symbol_proc.rb | 32 ++++++------- 28 files changed, 253 insertions(+), 329 deletions(-) diff --git a/lib/rubocop/cop/style/raise_args.rb b/lib/rubocop/cop/style/raise_args.rb index b0bd7f3f801..56d54c4b527 100644 --- a/lib/rubocop/cop/style/raise_args.rb +++ b/lib/rubocop/cop/style/raise_args.rb @@ -32,8 +32,9 @@ module Style # raise StandardError.new("message") # raise MyCustomError.new(arg1, arg2, arg3) # fail "message" - class RaiseArgs < Cop + class RaiseArgs < Base include ConfigurableEnforcedStyle + extend AutoCorrector EXPLODED_MSG = 'Provide an exception class and message ' \ 'as arguments to `%s`.' @@ -51,16 +52,6 @@ def on_send(node) end end - def autocorrect(node) - replacement = if style == :compact - correction_exploded_to_compact(node) - else - correction_compact_to_exploded(node) - end - - ->(corrector) { corrector.replace(node, replacement) } - end - private def correction_compact_to_exploded(node) @@ -91,8 +82,12 @@ def correction_exploded_to_compact(node) def check_compact(node) if node.arguments.size > 1 - add_offense(node) do - opposite_style_detected + return unless opposite_style_detected + + add_offense(node, message: format(COMPACT_MSG, method: node.method_name)) do |corrector| + replacement = correction_exploded_to_compact(node) + + corrector.replace(node, replacement) end else correct_style_detected @@ -105,11 +100,13 @@ def check_exploded(node) first_arg = node.first_argument return unless first_arg.send_type? && first_arg.method?(:new) - return if acceptable_exploded_args?(first_arg.arguments) + return unless opposite_style_detected - add_offense(node) do - opposite_style_detected + add_offense(node, message: format(EXPLODED_MSG, method: node.method_name)) do |corrector| + replacement = correction_compact_to_exploded(node) + + corrector.replace(node, replacement) end end @@ -131,14 +128,6 @@ def requires_parens?(parent) parent.and_type? || parent.or_type? || parent.if_type? && parent.ternary? end - - def message(node) - if style == :compact - format(COMPACT_MSG, method: node.method_name) - else - format(EXPLODED_MSG, method: node.method_name) - end - end end end end diff --git a/lib/rubocop/cop/style/random_with_offset.rb b/lib/rubocop/cop/style/random_with_offset.rb index e9ba9b06c83..255d2932856 100644 --- a/lib/rubocop/cop/style/random_with_offset.rb +++ b/lib/rubocop/cop/style/random_with_offset.rb @@ -23,7 +23,9 @@ module Style # # good # rand(1..6) # rand(1...7) - class RandomWithOffset < Cop + class RandomWithOffset < Base + extend AutoCorrector + MSG = 'Prefer ranges when generating random numbers instead of ' \ 'integers with offsets.' @@ -61,21 +63,8 @@ def on_send(node) rand_op_integer?(node) || rand_modified?(node) - add_offense(node) - end - - def autocorrect(node) - lambda do |corrector| - if integer_op_rand?(node) - corrector.replace(node, - corrected_integer_op_rand(node)) - elsif rand_op_integer?(node) - corrector.replace(node, - corrected_rand_op_integer(node)) - elsif rand_modified?(node) - corrector.replace(node, - corrected_rand_modified(node)) - end + add_offense(node) do |corrector| + autocorrect(corrector, node) end end @@ -86,6 +75,16 @@ def autocorrect(node) (send _ _ (send $_ _ $_))} PATTERN + def autocorrect(corrector, node) + if integer_op_rand?(node) + corrector.replace(node, corrected_integer_op_rand(node)) + elsif rand_op_integer?(node) + corrector.replace(node, corrected_rand_op_integer(node)) + elsif rand_modified?(node) + corrector.replace(node, corrected_rand_modified(node)) + end + end + def corrected_integer_op_rand(node) random_call(node) do |prefix_node, random_node| prefix = prefix_from_prefix_node(prefix_node) diff --git a/lib/rubocop/cop/style/redundant_assignment.rb b/lib/rubocop/cop/style/redundant_assignment.rb index 6b309e35cb1..1f11282dd53 100644 --- a/lib/rubocop/cop/style/redundant_assignment.rb +++ b/lib/rubocop/cop/style/redundant_assignment.rb @@ -37,7 +37,9 @@ module Style # end # end # - class RedundantAssignment < Cop + class RedundantAssignment < Base + extend AutoCorrector + MSG = 'Redundant assignment before returning detected.' def_node_matcher :redundant_assignment?, <<~PATTERN @@ -49,14 +51,6 @@ def on_def(node) end alias on_defs on_def - def autocorrect(node) - lambda do |corrector| - expression = node.children[1] - corrector.replace(node, expression.source) - corrector.remove(right_sibling_of(node)) - end - end - private def check_branch(node) @@ -97,7 +91,11 @@ def check_ensure_node(node) def check_begin_node(node) if (assignment = redundant_assignment?(node)) - add_offense(assignment) + add_offense(assignment) do |corrector| + expression = assignment.children[1] + corrector.replace(assignment, expression.source) + corrector.remove(right_sibling_of(assignment)) + end else last_expr = node.children.last check_branch(last_expr) diff --git a/lib/rubocop/cop/style/redundant_begin.rb b/lib/rubocop/cop/style/redundant_begin.rb index 1efe8c0eb5d..19bf39dcb62 100644 --- a/lib/rubocop/cop/style/redundant_begin.rb +++ b/lib/rubocop/cop/style/redundant_begin.rb @@ -54,7 +54,9 @@ module Style # baz # end # end - class RedundantBegin < Cop + class RedundantBegin < Base + extend AutoCorrector + MSG = 'Redundant `begin` block detected.' def on_def(node) @@ -71,19 +73,15 @@ def on_block(node) check(node) end - def autocorrect(node) - lambda do |corrector| - corrector.remove(node.loc.begin) - corrector.remove(node.loc.end) - end - end - private def check(node) return unless node.body&.kwbegin_type? - add_offense(node.body, location: :begin) + add_offense(node.body.loc.begin) do |corrector| + corrector.remove(node.body.loc.begin) + corrector.remove(node.body.loc.end) + end end end end diff --git a/lib/rubocop/cop/style/redundant_condition.rb b/lib/rubocop/cop/style/redundant_condition.rb index 065293b82e1..d6e5284ed83 100644 --- a/lib/rubocop/cop/style/redundant_condition.rb +++ b/lib/rubocop/cop/style/redundant_condition.rb @@ -30,8 +30,9 @@ module Style # c # end # - class RedundantCondition < Cop + class RedundantCondition < Base include RangeHelp + extend AutoCorrector MSG = 'Use double pipes `||` instead.' REDUNDANT_CONDITION = 'This condition is not needed.' @@ -40,11 +41,9 @@ def on_if(node) return if node.elsif_conditional? return unless offense?(node) - add_offense(node, location: range_of_offense(node)) - end + message = message(node) - def autocorrect(node) - lambda do |corrector| + add_offense(range_of_offense(node), message: message) do |corrector| if node.ternary? correct_ternary(corrector, node) elsif node.modifier_form? || !node.else_branch @@ -68,7 +67,7 @@ def message(node) end def range_of_offense(node) - return :expression unless node.ternary? + return node.loc.expression unless node.ternary? range_between(node.loc.question.begin_pos, node.loc.colon.end_pos) end diff --git a/lib/rubocop/cop/style/redundant_fetch_block.rb b/lib/rubocop/cop/style/redundant_fetch_block.rb index 9fef8f5073e..09686b43ea2 100644 --- a/lib/rubocop/cop/style/redundant_fetch_block.rb +++ b/lib/rubocop/cop/style/redundant_fetch_block.rb @@ -31,9 +31,10 @@ module Style # # good # ENV.fetch(:key, VALUE) # - class RedundantFetchBlock < Cop + class RedundantFetchBlock < Base include FrozenStringLiteral include RangeHelp + extend AutoCorrector MSG = 'Use `%s` instead of `%s`.' @@ -52,17 +53,7 @@ def on_block(node) good = build_good_method(send, body) bad = build_bad_method(send, body) - add_offense( - node, - location: range, - message: format(MSG, good: good, bad: bad) - ) - end - end - - def autocorrect(node) - redundant_fetch_block_candidate?(node) do |send, body| - lambda do |corrector| + add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector| receiver, _, key = send.children default_value = body ? body.source : 'nil' diff --git a/lib/rubocop/cop/style/redundant_file_extension_in_require.rb b/lib/rubocop/cop/style/redundant_file_extension_in_require.rb index f1abd515ed6..c4f17c32e98 100644 --- a/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +++ b/lib/rubocop/cop/style/redundant_file_extension_in_require.rb @@ -24,7 +24,9 @@ module Style # require_relative '../foo' # require_relative '../foo.so' # - class RedundantFileExtensionInRequire < Cop + class RedundantFileExtensionInRequire < Base + extend AutoCorrector + MSG = 'Redundant `.rb` file extension detected.' def_node_matcher :require_call?, <<~PATTERN @@ -33,15 +35,13 @@ class RedundantFileExtensionInRequire < Cop def on_send(node) require_call?(node) do |name_node| - add_offense(name_node) if name_node.value.end_with?('.rb') - end - end + return unless name_node.value.end_with?('.rb') - def autocorrect(node) - correction = node.value.sub(/\.rb\z/, '') + add_offense(name_node) do |corrector| + correction = name_node.value.sub(/\.rb\z/, '') - lambda do |corrector| - corrector.replace(node, "'#{correction}'") + corrector.replace(name_node, "'#{correction}'") + end end end end diff --git a/lib/rubocop/cop/style/redundant_freeze.rb b/lib/rubocop/cop/style/redundant_freeze.rb index 31c69b4550d..bbb2257dd7d 100644 --- a/lib/rubocop/cop/style/redundant_freeze.rb +++ b/lib/rubocop/cop/style/redundant_freeze.rb @@ -11,7 +11,8 @@ module Style # # # good # CONST = 1 - class RedundantFreeze < Cop + class RedundantFreeze < Base + extend AutoCorrector include FrozenStringLiteral MSG = 'Do not freeze immutable objects, as freezing them has no ' \ @@ -22,11 +23,7 @@ def on_send(node) (immutable_literal?(node.receiver) || operation_produces_immutable_object?(node.receiver)) - add_offense(node) - end - - def autocorrect(node) - lambda do |corrector| + add_offense(node) do |corrector| corrector.remove(node.loc.dot) corrector.remove(node.loc.selector) end diff --git a/lib/rubocop/cop/style/regexp_literal.rb b/lib/rubocop/cop/style/regexp_literal.rb index 51256ec4745..9469167f9b5 100644 --- a/lib/rubocop/cop/style/regexp_literal.rb +++ b/lib/rubocop/cop/style/regexp_literal.rb @@ -81,23 +81,24 @@ module Style # @example AllowInnerSlashes: true # # good # x =~ /home\// - class RegexpLiteral < Cop + class RegexpLiteral < Base include ConfigurableEnforcedStyle include RangeHelp + extend AutoCorrector MSG_USE_SLASHES = 'Use `//` around regular expression.' MSG_USE_PERCENT_R = 'Use `%r` around regular expression.' def on_regexp(node) - if slash_literal?(node) - check_slash_literal(node) - else - check_percent_r_literal(node) - end - end + message = if slash_literal?(node) + MSG_USE_PERCENT_R unless allowed_slash_literal?(node) + else + MSG_USE_SLASHES unless allowed_percent_r_literal?(node) + end + + return unless message - def autocorrect(node) - lambda do |corrector| + add_offense(node, message: message) do |corrector| correct_delimiters(node, corrector) correct_inner_slashes(node, corrector) end @@ -105,18 +106,6 @@ def autocorrect(node) private - def check_slash_literal(node) - return if allowed_slash_literal?(node) - - add_offense(node, message: MSG_USE_PERCENT_R) - end - - def check_percent_r_literal(node) - return if allowed_percent_r_literal?(node) - - add_offense(node, message: MSG_USE_SLASHES) - end - def allowed_slash_literal?(node) style == :slashes && !contains_disallowed_slash?(node) || allowed_mixed_slash?(node) diff --git a/lib/rubocop/cop/style/return_nil.rb b/lib/rubocop/cop/style/return_nil.rb index 980805c1626..29e4f82feaa 100644 --- a/lib/rubocop/cop/style/return_nil.rb +++ b/lib/rubocop/cop/style/return_nil.rb @@ -28,8 +28,9 @@ module Style # def foo(arg) # return nil if arg # end - class ReturnNil < Cop + class ReturnNil < Base include ConfigurableEnforcedStyle + extend AutoCorrector RETURN_MSG = 'Use `return` instead of `return nil`.' RETURN_NIL_MSG = 'Use `return nil` instead of `return`.' @@ -54,12 +55,11 @@ def on_return(node) return nil if chained_send?(send_node) end - add_offense(node) unless correct_style?(node) - end + return if correct_style?(node) - def autocorrect(node) - lambda do |corrector| + add_offense(node) do |corrector| corrected = style == :return ? 'return' : 'return nil' + corrector.replace(node, corrected) end end diff --git a/lib/rubocop/cop/style/safe_navigation.rb b/lib/rubocop/cop/style/safe_navigation.rb index d49abd7ca39..6e2be6f0d55 100644 --- a/lib/rubocop/cop/style/safe_navigation.rb +++ b/lib/rubocop/cop/style/safe_navigation.rb @@ -58,9 +58,10 @@ module Style # foo.baz = bar if foo # foo.baz + bar if foo # foo.bar > 2 if foo - class SafeNavigation < Cop + class SafeNavigation < Base include NilMethods include RangeHelp + extend AutoCorrector MSG = 'Use safe navigation (`&.`) instead of checking if an object ' \ 'exists before calling the method.' @@ -104,29 +105,29 @@ def check_node(node) return if chain_size(method_chain, method) > 1 return if unsafe_method_used?(method_chain, method) - add_offense(node) + add_offense(node) do |corrector| + autocorrect(corrector, node) + end end def use_var_only_in_unless_modifier?(node, variable) node.if_type? && node.unless? && !method_called?(variable) end - def autocorrect(node) + private + + def autocorrect(corrector, node) body = node.node_parts[1] method_call = method_call(node) - lambda do |corrector| - corrector.remove(begin_range(node, body)) - corrector.remove(end_range(node, body)) - corrector.insert_before(method_call.loc.dot, '&') - handle_comments(corrector, node, method_call) + corrector.remove(begin_range(node, body)) + corrector.remove(end_range(node, body)) + corrector.insert_before(method_call.loc.dot, '&') + handle_comments(corrector, node, method_call) - add_safe_nav_to_all_methods_in_chain(corrector, method_call, body) - end + add_safe_nav_to_all_methods_in_chain(corrector, method_call, body) end - private - def handle_comments(corrector, node, method_call) comments = comments(node) return if comments.empty? diff --git a/lib/rubocop/cop/style/sample.rb b/lib/rubocop/cop/style/sample.rb index 25af4ccc831..cc59190444f 100644 --- a/lib/rubocop/cop/style/sample.rb +++ b/lib/rubocop/cop/style/sample.rb @@ -27,7 +27,9 @@ module Style # [1, 2, 3].shuffle[1..3] # sample(3) might return a longer Array # [1, 2, 3].shuffle[foo, bar] # [1, 2, 3].shuffle(random: Random.new) - class Sample < Cop + class Sample < Base + extend AutoCorrector + MSG = 'Use `%s` instead of `%s`.' def_node_matcher :sample_candidate?, <<~PATTERN @@ -35,22 +37,17 @@ class Sample < Cop PATTERN def on_send(node) - sample_candidate?(node) do |shuffle, shuffle_arg, method, method_args| + sample_candidate?(node) do |shuffle_node, shuffle_arg, method, method_args| return unless offensive?(method, method_args) - range = source_range(shuffle, node) + range = source_range(shuffle_node, node) message = message(shuffle_arg, method, method_args, range) - add_offense(node, location: range, message: message) - end - end - - def autocorrect(node) - shuffle_node, shuffle_arg, method, method_args = - sample_candidate?(node) - lambda do |corrector| - corrector.replace(source_range(shuffle_node, node), - correction(shuffle_arg, method, method_args)) + add_offense(range, message: message) do |corrector| + corrector.replace( + source_range(shuffle_node, node), correction(shuffle_arg, method, method_args) + ) + end end end diff --git a/lib/rubocop/cop/style/self_assignment.rb b/lib/rubocop/cop/style/self_assignment.rb index c0f4b63b481..00b54a97ba8 100644 --- a/lib/rubocop/cop/style/self_assignment.rb +++ b/lib/rubocop/cop/style/self_assignment.rb @@ -12,7 +12,9 @@ module Style # # # good # x += 1 - class SelfAssignment < Cop + class SelfAssignment < Base + extend AutoCorrector + MSG = 'Use self-assignment shorthand `%s=`.' OPS = %i[+ - * ** / | &].freeze @@ -32,16 +34,6 @@ def on_cvasgn(node) check(node, :cvar) end - def autocorrect(node) - _var_name, rhs = *node - - if rhs.send_type? - autocorrect_send_node(node, rhs) - elsif %i[and or].include?(rhs.type) - autocorrect_boolean_node(node, rhs) - end - end - private def check(node, var_type) @@ -62,7 +54,9 @@ def check_send_node(node, rhs, var_name, var_type) target_node = s(var_type, var_name) return unless receiver == target_node - add_offense(node, message: format(MSG, method: method_name)) + add_offense(node, message: format(MSG, method: method_name)) do |corrector| + autocorrect(corrector, node) + end end def check_boolean_node(node, rhs, var_name, var_type) @@ -72,24 +66,34 @@ def check_boolean_node(node, rhs, var_name, var_type) return unless first_operand == target_node operator = rhs.loc.operator.source - add_offense(node, message: format(MSG, method: operator)) + add_offense(node, message: format(MSG, method: operator)) do |corrector| + autocorrect(corrector, node) + end end - def autocorrect_send_node(node, rhs) + def autocorrect(corrector, node) + _var_name, rhs = *node + + if rhs.send_type? + autocorrect_send_node(corrector, node, rhs) + elsif %i[and or].include?(rhs.type) + autocorrect_boolean_node(corrector, node, rhs) + end + end + + def autocorrect_send_node(corrector, node, rhs) _receiver, method_name, args = *rhs - apply_autocorrect(node, rhs, method_name.to_s, args) + apply_autocorrect(corrector, node, rhs, method_name.to_s, args) end - def autocorrect_boolean_node(node, rhs) + def autocorrect_boolean_node(corrector, node, rhs) _first_operand, second_operand = *rhs - apply_autocorrect(node, rhs, rhs.loc.operator.source, second_operand) + apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, second_operand) end - def apply_autocorrect(node, rhs, operator, new_rhs) - lambda do |corrector| - corrector.insert_before(node.loc.operator, operator) - corrector.replace(rhs, new_rhs.source) - end + def apply_autocorrect(corrector, node, rhs, operator, new_rhs) + corrector.insert_before(node.loc.operator, operator) + corrector.replace(rhs, new_rhs.source) end end end diff --git a/lib/rubocop/cop/style/semicolon.rb b/lib/rubocop/cop/style/semicolon.rb index 1b6b43552cd..e09fde2e657 100644 --- a/lib/rubocop/cop/style/semicolon.rb +++ b/lib/rubocop/cop/style/semicolon.rb @@ -26,12 +26,13 @@ module Style # @example AllowAsExpressionSeparator: true # # good # foo = 1; bar = 2 - class Semicolon < Cop + class Semicolon < Base include RangeHelp + extend AutoCorrector MSG = 'Do not use semicolons to terminate expressions.' - def investigate(processed_source) + def on_new_investigation return if processed_source.blank? @processed_source = processed_source @@ -66,12 +67,6 @@ def on_begin(node) # rubocop:todo Metrics/CyclomaticComplexity end end - def autocorrect(range) - return unless range - - ->(corrector) { corrector.remove(range) } - end - private def check_for_line_terminator_or_opener @@ -93,7 +88,9 @@ def convention_on(line, column, autocorrect) range = source_range(@processed_source.buffer, line, column) # Don't attempt to autocorrect if semicolon is separating statements # on the same line - add_offense(autocorrect ? range : nil, location: range) + add_offense(range) do |corrector| + corrector.remove(range) if autocorrect + end end end end diff --git a/lib/rubocop/cop/style/send.rb b/lib/rubocop/cop/style/send.rb index 6f09eac7483..84b3417968a 100644 --- a/lib/rubocop/cop/style/send.rb +++ b/lib/rubocop/cop/style/send.rb @@ -13,7 +13,7 @@ module Style # # good # Foo.__send__(:bar) # quuz.public_send(:fred) - class Send < Cop + class Send < Base MSG = 'Prefer `Object#__send__` or `Object#public_send` to ' \ '`send`.' @@ -22,7 +22,7 @@ class Send < Cop def on_send(node) return unless sending?(node) && node.arguments? - add_offense(node, location: :selector) + add_offense(node.loc.selector) end alias on_csend on_send end diff --git a/lib/rubocop/cop/style/signal_exception.rb b/lib/rubocop/cop/style/signal_exception.rb index c5aed00d722..21529ba1a83 100644 --- a/lib/rubocop/cop/style/signal_exception.rb +++ b/lib/rubocop/cop/style/signal_exception.rb @@ -104,8 +104,9 @@ module Style # # explicit_receiver.fail # explicit_receiver.raise - class SignalException < Cop + class SignalException < Base include ConfigurableEnforcedStyle + extend AutoCorrector FAIL_MSG = 'Use `fail` instead of `raise` to signal exceptions.' RAISE_MSG = 'Use `raise` instead of `fail` to ' \ @@ -115,7 +116,7 @@ class SignalException < Cop def_node_search :custom_fail_methods, '{(def :fail ...) (defs _ :fail ...)}' - def investigate(processed_source) + def on_new_investigation ast = processed_source.ast @custom_fail_defined = ast && custom_fail_methods(ast).any? end @@ -145,20 +146,6 @@ def on_send(node) end end - def autocorrect(node) - lambda do |corrector| - name = - case style - when :semantic - command_or_kernel_call?(:raise, node) ? 'fail' : 'raise' - when :only_raise then 'raise' - when :only_fail then 'fail' - end - - corrector.replace(node.loc.selector, name) - end - end - private def message(method_name) @@ -178,8 +165,9 @@ def check_scope(method_name, node) each_command_or_kernel_call(method_name, node) do |send_node| next if ignored_node?(send_node) - add_offense(send_node, - location: :selector, message: message(method_name)) + add_offense(send_node.loc.selector, message: message(method_name)) do |corrector| + autocorrect(corrector, send_node) + end ignore_node(send_node) end end @@ -187,7 +175,21 @@ def check_scope(method_name, node) def check_send(method_name, node) return unless node && command_or_kernel_call?(method_name, node) - add_offense(node, location: :selector, message: message(method_name)) + add_offense(node.loc.selector, message: message(method_name)) do |corrector| + autocorrect(corrector, node) + end + end + + def autocorrect(corrector, node) + name = + case style + when :semantic + command_or_kernel_call?(:raise, node) ? 'fail' : 'raise' + when :only_raise then 'raise' + when :only_fail then 'fail' + end + + corrector.replace(node.loc.selector, name) end def command_or_kernel_call?(name, node) diff --git a/lib/rubocop/cop/style/single_line_block_params.rb b/lib/rubocop/cop/style/single_line_block_params.rb index d9680f7568c..44ca44017a8 100644 --- a/lib/rubocop/cop/style/single_line_block_params.rb +++ b/lib/rubocop/cop/style/single_line_block_params.rb @@ -28,7 +28,7 @@ module Style # foo.reduce do |c, d| # c + d # end - class SingleLineBlockParams < Cop + class SingleLineBlockParams < Base MSG = 'Name `%s` block params `|%s|`.' def on_block(node) @@ -39,7 +39,9 @@ def on_block(node) return if args_match?(node.send_node.method_name, node.arguments) - add_offense(node.arguments) + message = message(node.arguments) + + add_offense(node.arguments, message: message) end private diff --git a/lib/rubocop/cop/style/single_line_methods.rb b/lib/rubocop/cop/style/single_line_methods.rb index 5cf2611978b..a0340cf1a53 100644 --- a/lib/rubocop/cop/style/single_line_methods.rb +++ b/lib/rubocop/cop/style/single_line_methods.rb @@ -24,8 +24,9 @@ module Style # # bad # def no_op; end # - class SingleLineMethods < Cop + class SingleLineMethods < Base include Alignment + extend AutoCorrector MSG = 'Avoid single-line method definitions.' @@ -33,29 +34,29 @@ def on_def(node) return unless node.single_line? return if allow_empty? && !node.body - add_offense(node) + add_offense(node) do |corrector| + autocorrect(corrector, node) + end end alias on_defs on_def - def autocorrect(node) - lambda do |corrector| - each_part(node.body) do |part| - LineBreakCorrector.break_line_before( - range: part, node: node, corrector: corrector, - configured_width: configured_indentation_width - ) - end + private + def autocorrect(corrector, node) + each_part(node.body) do |part| LineBreakCorrector.break_line_before( - range: node.loc.end, node: node, corrector: corrector, - indent_steps: 0, configured_width: configured_indentation_width + range: part, node: node, corrector: corrector, + configured_width: configured_indentation_width ) - - move_comment(node, corrector) end - end - private + LineBreakCorrector.break_line_before( + range: node.loc.end, node: node, corrector: corrector, + indent_steps: 0, configured_width: configured_indentation_width + ) + + move_comment(node, corrector) + end def allow_empty? cop_config['AllowIfMethodIsEmpty'] diff --git a/lib/rubocop/cop/style/slicing_with_range.rb b/lib/rubocop/cop/style/slicing_with_range.rb index de3769d9b8f..991b11785a6 100644 --- a/lib/rubocop/cop/style/slicing_with_range.rb +++ b/lib/rubocop/cop/style/slicing_with_range.rb @@ -12,7 +12,8 @@ module Style # # # good # items[1..] - class SlicingWithRange < Cop + class SlicingWithRange < Base + extend AutoCorrector extend TargetRubyVersion minimum_target_ruby_version 2.6 @@ -25,12 +26,8 @@ def on_send(node) return unless node.method?(:[]) && node.arguments.count == 1 return unless range_till_minus_one?(node.arguments.first) - add_offense(node.arguments.first) - end - - def autocorrect(node) - lambda do |corrector| - corrector.remove(node.end) + add_offense(node.first_argument) do |corrector| + corrector.remove(node.first_argument.end) end end end diff --git a/lib/rubocop/cop/style/special_global_vars.rb b/lib/rubocop/cop/style/special_global_vars.rb index 9158634afa4..28fdcd90fc0 100644 --- a/lib/rubocop/cop/style/special_global_vars.rb +++ b/lib/rubocop/cop/style/special_global_vars.rb @@ -56,8 +56,9 @@ module Style # puts $' # puts $+ # - class SpecialGlobalVars < Cop + class SpecialGlobalVars < Base include ConfigurableEnforcedStyle + extend AutoCorrector MSG_BOTH = 'Prefer `%s` from the stdlib \'English\' ' \ 'module (don\'t forget to require it) or `%s` over ' \ @@ -120,13 +121,14 @@ def on_gvar(node) correct_style_detected else opposite_style_detected - add_offense(node) + + add_offense(node, message: message(global_var)) do |corrector| + autocorrect(corrector, node, global_var) + end end end - def message(node) - global_var, = *node - + def message(global_var) if style == :use_english_names format_english_message(global_var) else @@ -136,17 +138,10 @@ def message(node) end end - def autocorrect(node) - lambda do |corrector| - global_var, = *node + def autocorrect(corrector, node, global_var) + node = node.parent while node.parent&.begin_type? && node.parent.children.one? - while node.parent&.begin_type? && - node.parent.children.one? - node = node.parent - end - - corrector.replace(node, replacement(node, global_var)) - end + corrector.replace(node, replacement(node, global_var)) end private diff --git a/lib/rubocop/cop/style/stabby_lambda_parentheses.rb b/lib/rubocop/cop/style/stabby_lambda_parentheses.rb index 304b3b9fe5d..70c2a8490bf 100644 --- a/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +++ b/lib/rubocop/cop/style/stabby_lambda_parentheses.rb @@ -19,26 +19,26 @@ module Style # # # good # ->a,b,c { a + b + c} - class StabbyLambdaParentheses < Cop + class StabbyLambdaParentheses < Base include ConfigurableEnforcedStyle + extend AutoCorrector MSG_REQUIRE = 'Wrap stabby lambda arguments with parentheses.' MSG_NO_REQUIRE = 'Do not wrap stabby lambda arguments ' \ 'with parentheses.' def on_send(node) return unless stabby_lambda_with_args?(node) - return unless redundant_parentheses?(node) || - missing_parentheses?(node) + return unless redundant_parentheses?(node) || missing_parentheses?(node) - add_offense(node.block_node.arguments) - end + arguments = node.block_node.arguments - def autocorrect(node) - case style - when :require_parentheses - missing_parentheses_corrector(node) - when :require_no_parentheses - unwanted_parentheses_corrector(node) + add_offense(arguments) do |corrector| + case style + when :require_parentheses + missing_parentheses_corrector(corrector, arguments) + when :require_no_parentheses + unwanted_parentheses_corrector(corrector, arguments) + end end end @@ -56,19 +56,15 @@ def message(_node) style == :require_parentheses ? MSG_REQUIRE : MSG_NO_REQUIRE end - def missing_parentheses_corrector(node) - lambda do |corrector| - corrector.wrap(node, '(', ')') - end + def missing_parentheses_corrector(corrector, node) + corrector.wrap(node, '(', ')') end - def unwanted_parentheses_corrector(node) - lambda do |corrector| - args_loc = node.loc + def unwanted_parentheses_corrector(corrector, node) + args_loc = node.loc - corrector.replace(args_loc.begin, '') - corrector.remove(args_loc.end) - end + corrector.replace(args_loc.begin, '') + corrector.remove(args_loc.end) end def stabby_lambda_with_args?(node) diff --git a/lib/rubocop/cop/style/stderr_puts.rb b/lib/rubocop/cop/style/stderr_puts.rb index e83403b2760..7aa28bf398e 100644 --- a/lib/rubocop/cop/style/stderr_puts.rb +++ b/lib/rubocop/cop/style/stderr_puts.rb @@ -14,8 +14,9 @@ module Style # # good # warn('hello') # - class StderrPuts < Cop + class StderrPuts < Base include RangeHelp + extend AutoCorrector MSG = 'Use `warn` instead of `%s` to allow such output to be disabled.' @@ -30,11 +31,8 @@ class StderrPuts < Cop def on_send(node) return unless stderr_puts?(node) - add_offense(node, location: stderr_puts_range(node)) - end - - def autocorrect(node) - lambda do |corrector| + message = message(node) + add_offense(stderr_puts_range(node), message: message) do |corrector| corrector.replace(stderr_puts_range(node), 'warn') end end diff --git a/lib/rubocop/cop/style/string_hash_keys.rb b/lib/rubocop/cop/style/string_hash_keys.rb index 2edaf6ee175..845e62941ab 100644 --- a/lib/rubocop/cop/style/string_hash_keys.rb +++ b/lib/rubocop/cop/style/string_hash_keys.rb @@ -12,7 +12,9 @@ module Style # # # good # { one: 1, two: 2, three: 3 } - class StringHashKeys < Cop + class StringHashKeys < Base + extend AutoCorrector + MSG = 'Prefer symbols instead of strings as hash keys.' def_node_matcher :string_hash_key?, <<~PATTERN @@ -35,13 +37,10 @@ def on_pair(node) return unless string_hash_key?(node) return if receive_environments_method?(node) - add_offense(node.key) - end + add_offense(node.key) do |corrector| + symbol_content = node.key.str_content.to_sym.inspect - def autocorrect(node) - lambda do |corrector| - symbol_content = node.str_content.to_sym.inspect - corrector.replace(node, symbol_content) + corrector.replace(node.key, symbol_content) end end end diff --git a/lib/rubocop/cop/style/string_methods.rb b/lib/rubocop/cop/style/string_methods.rb index a16e9229f6f..6b1d0f7d75c 100644 --- a/lib/rubocop/cop/style/string_methods.rb +++ b/lib/rubocop/cop/style/string_methods.rb @@ -14,32 +14,22 @@ module Style # # good # 'name'.to_sym # 'var'.preferred_method - class StringMethods < Cop + class StringMethods < Base include MethodPreference + extend AutoCorrector MSG = 'Prefer `%s` over `%s`.' def on_send(node) - return unless preferred_method(node.method_name) + return unless (preferred_method = preferred_method(node.method_name)) - add_offense(node, location: :selector) - end - alias on_csend on_send + message = format(MSG, prefer: preferred_method, current: node.method_name) - def autocorrect(node) - lambda do |corrector| - corrector.replace(node.loc.selector, - preferred_method(node.method_name)) + add_offense(node.loc.selector, message: message) do |corrector| + corrector.replace(node.loc.selector, preferred_method(node.method_name)) end end - - private - - def message(node) - format(MSG, - prefer: preferred_method(node.method_name), - current: node.method_name) - end + alias on_csend on_send end end end diff --git a/lib/rubocop/cop/style/strip.rb b/lib/rubocop/cop/style/strip.rb index 94759269c29..0e202de8f49 100644 --- a/lib/rubocop/cop/style/strip.rb +++ b/lib/rubocop/cop/style/strip.rb @@ -13,8 +13,9 @@ module Style # # # good # 'abc'.strip - class Strip < Cop + class Strip < Base include RangeHelp + extend AutoCorrector MSG = 'Use `strip` instead of `%s`.' @@ -25,20 +26,13 @@ class Strip < Cop def on_send(node) lstrip_rstrip(node) do |first_send, method_one, method_two| - range = range_between(first_send.loc.selector.begin_pos, - node.source_range.end_pos) - add_offense(node, - location: range, - message: format(MSG, - methods: "#{method_one}.#{method_two}")) - end - end + range = range_between(first_send.loc.selector.begin_pos, node.source_range.end_pos) + message = format(MSG, methods: "#{method_one}.#{method_two}") - def autocorrect(node) - range = range_between(node.receiver.loc.selector.begin_pos, - node.source_range.end_pos) - - ->(corrector) { corrector.replace(range, 'strip') } + add_offense(range, message: message) do |corrector| + corrector.replace(range, 'strip') + end + end end end end diff --git a/lib/rubocop/cop/style/struct_inheritance.rb b/lib/rubocop/cop/style/struct_inheritance.rb index 30c5609e6bd..4e823b770ff 100644 --- a/lib/rubocop/cop/style/struct_inheritance.rb +++ b/lib/rubocop/cop/style/struct_inheritance.rb @@ -19,8 +19,9 @@ module Style # 42 # end # end - class StructInheritance < Cop + class StructInheritance < Base include RangeHelp + extend AutoCorrector MSG = "Don't extend an instance initialized by `Struct.new`. " \ 'Use a block to customize the struct.' @@ -28,11 +29,7 @@ class StructInheritance < Cop def on_class(node) return unless struct_constructor?(node.parent_class) - add_offense(node, location: node.parent_class.source_range) - end - - def autocorrect(node) - lambda do |corrector| + add_offense(node.parent_class.source_range) do |corrector| corrector.remove(range_with_surrounding_space(range: node.loc.keyword, newlines: false)) corrector.replace(node.loc.operator, '=') diff --git a/lib/rubocop/cop/style/symbol_literal.rb b/lib/rubocop/cop/style/symbol_literal.rb index 606f9922ec4..37e16b17736 100644 --- a/lib/rubocop/cop/style/symbol_literal.rb +++ b/lib/rubocop/cop/style/symbol_literal.rb @@ -12,17 +12,15 @@ module Style # # # good # :symbol - class SymbolLiteral < Cop + class SymbolLiteral < Base + extend AutoCorrector + MSG = 'Do not use strings for word-like symbol literals.' def on_sym(node) return unless /\A:["'][A-Za-z_]\w*["']\z/.match?(node.source) - add_offense(node) - end - - def autocorrect(node) - lambda do |corrector| + add_offense(node) do |corrector| corrector.replace(node, node.source.delete(%q('"))) end end diff --git a/lib/rubocop/cop/style/symbol_proc.rb b/lib/rubocop/cop/style/symbol_proc.rb index eab782682a2..c7cbad1a556 100644 --- a/lib/rubocop/cop/style/symbol_proc.rb +++ b/lib/rubocop/cop/style/symbol_proc.rb @@ -11,9 +11,10 @@ module Style # # # good # something.map(&:upcase) - class SymbolProc < Cop + class SymbolProc < Base include RangeHelp include IgnoredMethods + extend AutoCorrector MSG = 'Pass `&:%s` as an argument to `%s` ' \ 'instead of a block.' @@ -49,30 +50,25 @@ def destructuring_block_argument?(argument_node) argument_node.one? && argument_node.source.include?(',') end - def autocorrect(node) - lambda do |corrector| - if node.send_node.arguments? - autocorrect_with_args(corrector, node, - node.send_node.arguments, - node.body.method_name) - else - autocorrect_without_args(corrector, node) - end - end - end - private def register_offense(node, method_name, block_method_name) block_start = node.loc.begin.begin_pos block_end = node.loc.end.end_pos range = range_between(block_start, block_end) + message = format(MSG, method: method_name, block_method: block_method_name) + + add_offense(range, message: message) do |corrector| + autocorrect(corrector, node) + end + end - add_offense(node, - location: range, - message: format(MSG, - method: method_name, - block_method: block_method_name)) + def autocorrect(corrector, node) + if node.send_node.arguments? + autocorrect_with_args(corrector, node, node.send_node.arguments, node.body.method_name) + else + autocorrect_without_args(corrector, node) + end end def autocorrect_without_args(corrector, node)