rubocop 1.43.0 → 1.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +1 -1
 - data/config/default.yml +64 -29
 - data/lib/rubocop/cli.rb +54 -8
 - data/lib/rubocop/config_loader.rb +12 -15
 - data/lib/rubocop/config_loader_resolver.rb +3 -4
 - data/lib/rubocop/cop/base.rb +27 -9
 - data/lib/rubocop/cop/commissioner.rb +8 -2
 - data/lib/rubocop/cop/cop.rb +23 -3
 - data/lib/rubocop/cop/corrector.rb +10 -2
 - data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
 - data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
 - data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
 - data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
 - data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
 - data/lib/rubocop/cop/layout/class_structure.rb +2 -16
 - data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
 - data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
 - data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
 - data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
 - data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
 - data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
 - data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
 - data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
 - data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
 - data/lib/rubocop/cop/lint/debugger.rb +8 -27
 - data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
 - data/lib/rubocop/cop/lint/else_layout.rb +2 -6
 - data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
 - data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
 - data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
 - data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
 - data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -5
 - data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
 - data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -4
 - data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
 - data/lib/rubocop/cop/lint/useless_rescue.rb +15 -1
 - data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
 - data/lib/rubocop/cop/lint/void.rb +19 -10
 - data/lib/rubocop/cop/metrics/block_length.rb +1 -1
 - data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
 - data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
 - data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +2 -5
 - data/lib/rubocop/cop/mixin/alignment.rb +1 -1
 - data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
 - data/lib/rubocop/cop/mixin/comments_help.rb +5 -3
 - data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +51 -25
 - data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
 - data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
 - data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
 - data/lib/rubocop/cop/naming/block_forwarding.rb +4 -0
 - data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
 - data/lib/rubocop/cop/registry.rb +12 -7
 - data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
 - data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -0
 - data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
 - data/lib/rubocop/cop/style/class_and_module_children.rb +3 -10
 - data/lib/rubocop/cop/style/command_literal.rb +1 -1
 - data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
 - data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
 - data/lib/rubocop/cop/style/documentation.rb +1 -1
 - data/lib/rubocop/cop/style/documentation_method.rb +6 -0
 - data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
 - data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
 - data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -5
 - data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
 - data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
 - data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
 - data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
 - data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
 - data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
 - data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
 - data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
 - data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
 - data/lib/rubocop/cop/style/parallel_assignment.rb +3 -1
 - data/lib/rubocop/cop/style/redundant_condition.rb +16 -1
 - data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
 - data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -10
 - data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
 - data/lib/rubocop/cop/style/require_order.rb +2 -9
 - data/lib/rubocop/cop/style/self_assignment.rb +2 -2
 - data/lib/rubocop/cop/style/semicolon.rb +24 -2
 - data/lib/rubocop/cop/style/symbol_array.rb +1 -1
 - data/lib/rubocop/cop/style/word_array.rb +1 -1
 - data/lib/rubocop/cop/style/yoda_condition.rb +12 -5
 - data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
 - data/lib/rubocop/cop/team.rb +19 -14
 - data/lib/rubocop/cop/variable_force/scope.rb +3 -3
 - data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
 - data/lib/rubocop/cop/variable_force.rb +1 -1
 - data/lib/rubocop/formatter.rb +0 -1
 - data/lib/rubocop/options.rb +22 -1
 - data/lib/rubocop/rspec/expect_offense.rb +6 -4
 - data/lib/rubocop/runner.rb +40 -4
 - data/lib/rubocop/server/cache.rb +10 -3
 - data/lib/rubocop/server/cli.rb +37 -18
 - data/lib/rubocop/server/client_command/exec.rb +1 -1
 - data/lib/rubocop/server/client_command/start.rb +6 -1
 - data/lib/rubocop/server/core.rb +23 -8
 - data/lib/rubocop/version.rb +1 -1
 - data/lib/rubocop.rb +4 -0
 - metadata +11 -27
 
| 
         @@ -0,0 +1,114 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Style
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Checks for usages of `unless` which can be replaced by `if` with inverted condition.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # Code without `unless` is easier to read, but that is subjective, so this cop
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # is disabled by default.
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # Methods that can be inverted should be defined in `InverseMethods`. Note that
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # the relationship of inverse methods needs to be defined in both directions.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # For example,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   InverseMethods:
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #     :!=: :==
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #     :even?: :odd?
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #     :odd?: :even?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #  will suggest both `even?` and `odd?` to be inverted, but only `!=` (and not `==`).
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # @safety
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #   This cop is unsafe because it cannot be guaranteed that the method
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #   and its inverse method are both defined on receiver, and also are
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #   actually inverse of each other.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   # bad (simple condition)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   foo unless !bar
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   foo unless x != y
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #   foo unless x >= 10
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #   foo unless x.even?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   foo if bar
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #   foo if x == y
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #   foo if x < 10
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   foo if x.odd?
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #   # bad (complex condition)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #   foo unless x != y || x.even?
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #   foo if x == y && x.odd?
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #   # good (if)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #   foo if !condition
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #
         
     | 
| 
      
 47 
     | 
    
         
            +
                  class InvertibleUnlessCondition < Base
         
     | 
| 
      
 48 
     | 
    
         
            +
                    extend AutoCorrector
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    MSG = 'Favor `if` with inverted condition over `unless`.'
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    def on_if(node)
         
     | 
| 
      
 53 
     | 
    
         
            +
                      return unless node.unless?
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                      condition = node.condition
         
     | 
| 
      
 56 
     | 
    
         
            +
                      return unless invertible?(condition)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      add_offense(node) do |corrector|
         
     | 
| 
      
 59 
     | 
    
         
            +
                        corrector.replace(node.loc.keyword, node.inverse_keyword)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        autocorrect(corrector, condition)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    private
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    def invertible?(node)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      case node.type
         
     | 
| 
      
 68 
     | 
    
         
            +
                      when :begin
         
     | 
| 
      
 69 
     | 
    
         
            +
                        invertible?(node.children.first)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      when :send
         
     | 
| 
      
 71 
     | 
    
         
            +
                        return if inheritance_check?(node)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                        node.method?(:!) || inverse_methods.key?(node.method_name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      when :or, :and
         
     | 
| 
      
 75 
     | 
    
         
            +
                        invertible?(node.lhs) && invertible?(node.rhs)
         
     | 
| 
      
 76 
     | 
    
         
            +
                      else
         
     | 
| 
      
 77 
     | 
    
         
            +
                        false
         
     | 
| 
      
 78 
     | 
    
         
            +
                      end
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    def inheritance_check?(node)
         
     | 
| 
      
 82 
     | 
    
         
            +
                      argument = node.first_argument
         
     | 
| 
      
 83 
     | 
    
         
            +
                      node.method?(:<) &&
         
     | 
| 
      
 84 
     | 
    
         
            +
                        (argument.const_type? && argument.short_name.to_s.upcase != argument.short_name.to_s)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    def autocorrect(corrector, node)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      case node.type
         
     | 
| 
      
 89 
     | 
    
         
            +
                      when :begin
         
     | 
| 
      
 90 
     | 
    
         
            +
                        autocorrect(corrector, node.children.first)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      when :send
         
     | 
| 
      
 92 
     | 
    
         
            +
                        autocorrect_send_node(corrector, node)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      when :or, :and
         
     | 
| 
      
 94 
     | 
    
         
            +
                        corrector.replace(node.loc.operator, node.inverse_operator)
         
     | 
| 
      
 95 
     | 
    
         
            +
                        autocorrect(corrector, node.lhs)
         
     | 
| 
      
 96 
     | 
    
         
            +
                        autocorrect(corrector, node.rhs)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    def autocorrect_send_node(corrector, node)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      if node.method?(:!)
         
     | 
| 
      
 102 
     | 
    
         
            +
                        corrector.remove(node.loc.selector)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      else
         
     | 
| 
      
 104 
     | 
    
         
            +
                        corrector.replace(node.loc.selector, inverse_methods[node.method_name])
         
     | 
| 
      
 105 
     | 
    
         
            +
                      end
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    def inverse_methods
         
     | 
| 
      
 109 
     | 
    
         
            +
                      @inverse_methods ||= cop_config['InverseMethods']
         
     | 
| 
      
 110 
     | 
    
         
            +
                    end
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -13,8 +13,7 @@ module RuboCop 
     | 
|
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                      private
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                      # rubocop:disable Metrics/PerceivedComplexity
         
     | 
| 
       17 
     | 
    
         
            -
                      def omit_parentheses(node)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      def omit_parentheses(node) # rubocop:disable Metrics/PerceivedComplexity
         
     | 
| 
       18 
17 
     | 
    
         
             
                        return unless node.parenthesized?
         
     | 
| 
       19 
18 
     | 
    
         
             
                        return if inside_endless_method_def?(node)
         
     | 
| 
       20 
19 
     | 
    
         
             
                        return if require_parentheses_for_hash_value_omission?(node)
         
     | 
| 
         @@ -28,7 +27,6 @@ module RuboCop 
     | 
|
| 
       28 
27 
     | 
    
         
             
                          autocorrect(corrector, node)
         
     | 
| 
       29 
28 
     | 
    
         
             
                        end
         
     | 
| 
       30 
29 
     | 
    
         
             
                      end
         
     | 
| 
       31 
     | 
    
         
            -
                      # rubocop:enable Metrics/PerceivedComplexity
         
     | 
| 
       32 
30 
     | 
    
         | 
| 
       33 
31 
     | 
    
         
             
                      def autocorrect(corrector, node)
         
     | 
| 
       34 
32 
     | 
    
         
             
                        if parentheses_at_the_end_of_multiline_call?(node)
         
     | 
| 
         @@ -90,7 +88,7 @@ module RuboCop 
     | 
|
| 
       90 
88 
     | 
    
         
             
                              .end_with?('(')
         
     | 
| 
       91 
89 
     | 
    
         
             
                      end
         
     | 
| 
       92 
90 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
                      def legitimate_call_with_parentheses?(node)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/PerceivedComplexity
         
     | 
| 
       94 
92 
     | 
    
         
             
                        call_in_literals?(node) ||
         
     | 
| 
       95 
93 
     | 
    
         
             
                          call_with_ambiguous_arguments?(node) ||
         
     | 
| 
       96 
94 
     | 
    
         
             
                          call_in_logical_operators?(node) ||
         
     | 
| 
         @@ -98,7 +96,8 @@ module RuboCop 
     | 
|
| 
       98 
96 
     | 
    
         
             
                          call_in_single_line_inheritance?(node) ||
         
     | 
| 
       99 
97 
     | 
    
         
             
                          allowed_multiline_call_with_parentheses?(node) ||
         
     | 
| 
       100 
98 
     | 
    
         
             
                          allowed_chained_call_with_parentheses?(node) ||
         
     | 
| 
       101 
     | 
    
         
            -
                          assignment_in_condition?(node)
         
     | 
| 
      
 99 
     | 
    
         
            +
                          assignment_in_condition?(node) ||
         
     | 
| 
      
 100 
     | 
    
         
            +
                          forwards_anonymous_rest_arguments?(node)
         
     | 
| 
       102 
101 
     | 
    
         
             
                      end
         
     | 
| 
       103 
102 
     | 
    
         | 
| 
       104 
103 
     | 
    
         
             
                      def call_in_literals?(node)
         
     | 
| 
         @@ -216,6 +215,13 @@ module RuboCop 
     | 
|
| 
       216 
215 
     | 
    
         | 
| 
       217 
216 
     | 
    
         
             
                        parent.assignment? && (grandparent.conditional? || grandparent.when_type?)
         
     | 
| 
       218 
217 
     | 
    
         
             
                      end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                      def forwards_anonymous_rest_arguments?(node)
         
     | 
| 
      
 220 
     | 
    
         
            +
                        return false unless (last_argument = node.last_argument)
         
     | 
| 
      
 221 
     | 
    
         
            +
                        return true if last_argument.forwarded_restarg_type?
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                        last_argument.hash_type? && last_argument.children.first&.forwarded_kwrestarg_type?
         
     | 
| 
      
 224 
     | 
    
         
            +
                      end
         
     | 
| 
       219 
225 
     | 
    
         
             
                    end
         
     | 
| 
       220 
226 
     | 
    
         
             
                    # rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
         
     | 
| 
       221 
227 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -36,6 +36,7 @@ module RuboCop 
     | 
|
| 
       36 
36 
     | 
    
         
             
                  #
         
     | 
| 
       37 
37 
     | 
    
         
             
                  class MinMaxComparison < Base
         
     | 
| 
       38 
38 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
      
 39 
     | 
    
         
            +
                    include RangeHelp
         
     | 
| 
       39 
40 
     | 
    
         | 
| 
       40 
41 
     | 
    
         
             
                    MSG = 'Use `%<prefer>s` instead.'
         
     | 
| 
       41 
42 
     | 
    
         
             
                    GRATER_OPERATORS = %i[> >=].freeze
         
     | 
| 
         @@ -54,7 +55,7 @@ module RuboCop 
     | 
|
| 
       54 
55 
     | 
    
         
             
                      replacement = "[#{lhs.source}, #{rhs.source}].#{preferred_method}"
         
     | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
57 
     | 
    
         
             
                      add_offense(node, message: format(MSG, prefer: replacement)) do |corrector|
         
     | 
| 
       57 
     | 
    
         
            -
                        corrector 
     | 
| 
      
 58 
     | 
    
         
            +
                        autocorrect(corrector, node, replacement)
         
     | 
| 
       58 
59 
     | 
    
         
             
                      end
         
     | 
| 
       59 
60 
     | 
    
         
             
                    end
         
     | 
| 
       60 
61 
     | 
    
         | 
| 
         @@ -67,6 +68,15 @@ module RuboCop 
     | 
|
| 
       67 
68 
     | 
    
         
             
                        LESS_OPERATORS.include?(operator) ? 'max' : 'min'
         
     | 
| 
       68 
69 
     | 
    
         
             
                      end
         
     | 
| 
       69 
70 
     | 
    
         
             
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    def autocorrect(corrector, node, replacement)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      if node.elsif?
         
     | 
| 
      
 74 
     | 
    
         
            +
                        corrector.remove(range_between(node.parent.loc.else.begin_pos, node.loc.else.begin_pos))
         
     | 
| 
      
 75 
     | 
    
         
            +
                        corrector.replace(node.else_branch, replacement)
         
     | 
| 
      
 76 
     | 
    
         
            +
                      else
         
     | 
| 
      
 77 
     | 
    
         
            +
                        corrector.replace(node, replacement)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      end
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
       70 
80 
     | 
    
         
             
                  end
         
     | 
| 
       71 
81 
     | 
    
         
             
                end
         
     | 
| 
       72 
82 
     | 
    
         
             
              end
         
     | 
| 
         @@ -40,10 +40,6 @@ module RuboCop 
     | 
|
| 
       40 
40 
     | 
    
         
             
                      [condition, indented_body, indented_end].join("\n")
         
     | 
| 
       41 
41 
     | 
    
         
             
                    end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                    def configured_indentation_width
         
     | 
| 
       44 
     | 
    
         
            -
                      super || 2
         
     | 
| 
       45 
     | 
    
         
            -
                    end
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
43 
     | 
    
         
             
                    def indented_body(body, node)
         
     | 
| 
       48 
44 
     | 
    
         
             
                      body_source = "#{offset(node)}#{body.source}"
         
     | 
| 
       49 
45 
     | 
    
         
             
                      body_source.each_line.map do |line|
         
     | 
| 
         @@ -31,6 +31,7 @@ module RuboCop 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  #     baz
         
     | 
| 
       32 
32 
     | 
    
         
             
                  #   )
         
     | 
| 
       33 
33 
     | 
    
         
             
                  class MultilineMemoization < Base
         
     | 
| 
      
 34 
     | 
    
         
            +
                    include Alignment
         
     | 
| 
       34 
35 
     | 
    
         
             
                    include ConfigurableEnforcedStyle
         
     | 
| 
       35 
36 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
       36 
37 
     | 
    
         | 
| 
         @@ -75,11 +76,10 @@ module RuboCop 
     | 
|
| 
       75 
76 
     | 
    
         
             
                    end
         
     | 
| 
       76 
77 
     | 
    
         | 
| 
       77 
78 
     | 
    
         
             
                    def keyword_begin_str(node, node_buf)
         
     | 
| 
       78 
     | 
    
         
            -
                      indent = config.for_cop('Layout/IndentationWidth')['Width'] || 2
         
     | 
| 
       79 
79 
     | 
    
         
             
                      if node_buf.source[node.loc.begin.end_pos] == "\n"
         
     | 
| 
       80 
80 
     | 
    
         
             
                        'begin'
         
     | 
| 
       81 
81 
     | 
    
         
             
                      else
         
     | 
| 
       82 
     | 
    
         
            -
                        "begin\n#{' ' * (node.loc.column +  
     | 
| 
      
 82 
     | 
    
         
            +
                        "begin\n#{' ' * (node.loc.column + configured_indentation_width)}"
         
     | 
| 
       83 
83 
     | 
    
         
             
                      end
         
     | 
| 
       84 
84 
     | 
    
         
             
                    end
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
         @@ -34,6 +34,7 @@ module RuboCop 
     | 
|
| 
       34 
34 
     | 
    
         
             
                  #   return cond ? b : c
         
     | 
| 
       35 
35 
     | 
    
         
             
                  #
         
     | 
| 
       36 
36 
     | 
    
         
             
                  class MultilineTernaryOperator < Base
         
     | 
| 
      
 37 
     | 
    
         
            +
                    include CommentsHelp
         
     | 
| 
       37 
38 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
       39 
40 
     | 
    
         
             
                    MSG_IF = 'Avoid multi-line ternary operators, use `if` or `unless` instead.'
         
     | 
| 
         @@ -46,9 +47,7 @@ module RuboCop 
     | 
|
| 
       46 
47 
     | 
    
         
             
                      message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
                      add_offense(node, message: message) do |corrector|
         
     | 
| 
       49 
     | 
    
         
            -
                         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                        corrector.replace(node, replacement(node))
         
     | 
| 
      
 50 
     | 
    
         
            +
                        autocorrect(corrector, node)
         
     | 
| 
       52 
51 
     | 
    
         
             
                      end
         
     | 
| 
       53 
52 
     | 
    
         
             
                    end
         
     | 
| 
       54 
53 
     | 
    
         | 
| 
         @@ -58,6 +57,16 @@ module RuboCop 
     | 
|
| 
       58 
57 
     | 
    
         
             
                      node.ternary? && node.multiline?
         
     | 
| 
       59 
58 
     | 
    
         
             
                    end
         
     | 
| 
       60 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                    def autocorrect(corrector, node)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      return unless offense?(node)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      corrector.replace(node, replacement(node))
         
     | 
| 
      
 64 
     | 
    
         
            +
                      return unless (parent = node.parent)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      return unless (comments_in_condition = comments_in_condition(node))
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                      corrector.insert_before(parent, comments_in_condition)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       61 
70 
     | 
    
         
             
                    def replacement(node)
         
     | 
| 
       62 
71 
     | 
    
         
             
                      if enforce_single_line_ternary_operator?(node)
         
     | 
| 
       63 
72 
     | 
    
         
             
                        "#{node.condition.source} ? #{node.if_branch.source} : #{node.else_branch.source}"
         
     | 
| 
         @@ -72,6 +81,12 @@ module RuboCop 
     | 
|
| 
       72 
81 
     | 
    
         
             
                      end
         
     | 
| 
       73 
82 
     | 
    
         
             
                    end
         
     | 
| 
       74 
83 
     | 
    
         | 
| 
      
 84 
     | 
    
         
            +
                    def comments_in_condition(node)
         
     | 
| 
      
 85 
     | 
    
         
            +
                      comments_in_range(node).map do |comment|
         
     | 
| 
      
 86 
     | 
    
         
            +
                        "#{comment.loc.expression.source}\n"
         
     | 
| 
      
 87 
     | 
    
         
            +
                      end.join
         
     | 
| 
      
 88 
     | 
    
         
            +
                    end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
       75 
90 
     | 
    
         
             
                    def enforce_single_line_ternary_operator?(node)
         
     | 
| 
       76 
91 
     | 
    
         
             
                      SINGLE_LINE_TYPES.include?(node.parent&.type) && !use_assignment_method?(node.parent)
         
     | 
| 
       77 
92 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -103,11 +103,7 @@ module RuboCop 
     | 
|
| 
       103 
103 
     | 
    
         
             
                      if node.if_branch.nil?
         
     | 
| 
       104 
104 
     | 
    
         
             
                        corrector.remove(range_by_whole_lines(node.loc.else, include_final_newline: true))
         
     | 
| 
       105 
105 
     | 
    
         
             
                      else
         
     | 
| 
       106 
     | 
    
         
            -
                        if_range  
     | 
| 
       107 
     | 
    
         
            -
                        else_range = else_range(node)
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                        corrector.replace(if_range, else_range.source)
         
     | 
| 
       110 
     | 
    
         
            -
                        corrector.replace(else_range, if_range.source)
         
     | 
| 
      
 106 
     | 
    
         
            +
                        corrector.swap(if_range(node), else_range(node))
         
     | 
| 
       111 
107 
     | 
    
         
             
                      end
         
     | 
| 
       112 
108 
     | 
    
         
             
                    end
         
     | 
| 
       113 
109 
     | 
    
         | 
| 
         @@ -12,10 +12,11 @@ module RuboCop 
     | 
|
| 
       12 
12 
     | 
    
         
             
                  #
         
     | 
| 
       13 
13 
     | 
    
         
             
                  # @example Max: 1 (default)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  #   # bad
         
     | 
| 
       15 
     | 
    
         
            -
                  #    
     | 
| 
      
 15 
     | 
    
         
            +
                  #   use_multiple_numbered_parameters { _1.call(_2, _3, _4) }
         
     | 
| 
       16 
16 
     | 
    
         
             
                  #
         
     | 
| 
       17 
17 
     | 
    
         
             
                  #   # good
         
     | 
| 
       18 
     | 
    
         
            -
                  #    
     | 
| 
      
 18 
     | 
    
         
            +
                  #   array.each { use_array_element_as_numbered_parameter(_1) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #   hash.each { use_only_hash_value_as_numbered_parameter(_2) }
         
     | 
| 
       19 
20 
     | 
    
         
             
                  class NumberedParametersLimit < Base
         
     | 
| 
       20 
21 
     | 
    
         
             
                    extend TargetRubyVersion
         
     | 
| 
       21 
22 
     | 
    
         
             
                    extend ExcludeLimit
         
     | 
| 
         @@ -26,9 +27,10 @@ module RuboCop 
     | 
|
| 
       26 
27 
     | 
    
         
             
                    exclude_limit 'Max'
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
       28 
29 
     | 
    
         
             
                    MSG = 'Avoid using more than %<max>i numbered %<parameter>s; %<count>i detected.'
         
     | 
| 
      
 30 
     | 
    
         
            +
                    NUMBERED_PARAMETER_PATTERN = /\A_[1-9]\z/.freeze
         
     | 
| 
       29 
31 
     | 
    
         | 
| 
       30 
32 
     | 
    
         
             
                    def on_numblock(node)
         
     | 
| 
       31 
     | 
    
         
            -
                       
     | 
| 
      
 33 
     | 
    
         
            +
                      param_count = numbered_parameter_nodes(node).uniq.count
         
     | 
| 
       32 
34 
     | 
    
         
             
                      return if param_count <= max_count
         
     | 
| 
       33 
35 
     | 
    
         | 
| 
       34 
36 
     | 
    
         
             
                      parameter = max_count > 1 ? 'parameters' : 'parameter'
         
     | 
| 
         @@ -38,6 +40,12 @@ module RuboCop 
     | 
|
| 
       38 
40 
     | 
    
         | 
| 
       39 
41 
     | 
    
         
             
                    private
         
     | 
| 
       40 
42 
     | 
    
         | 
| 
      
 43 
     | 
    
         
            +
                    def numbered_parameter_nodes(node)
         
     | 
| 
      
 44 
     | 
    
         
            +
                      node.each_descendant(:lvar).select do |lvar_node|
         
     | 
| 
      
 45 
     | 
    
         
            +
                        lvar_node.source.match?(NUMBERED_PARAMETER_PATTERN)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
       41 
49 
     | 
    
         
             
                    def max_count
         
     | 
| 
       42 
50 
     | 
    
         
             
                      max = cop_config.fetch('Max', DEFAULT_MAX_VALUE)
         
     | 
| 
       43 
51 
     | 
    
         | 
| 
         @@ -31,6 +31,7 @@ module RuboCop 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  #     baz
         
     | 
| 
       32 
32 
     | 
    
         
             
                  #   end
         
     | 
| 
       33 
33 
     | 
    
         
             
                  class OneLineConditional < Base
         
     | 
| 
      
 34 
     | 
    
         
            +
                    include Alignment
         
     | 
| 
       34 
35 
     | 
    
         
             
                    include ConfigurableEnforcedStyle
         
     | 
| 
       35 
36 
     | 
    
         
             
                    include OnNormalIfUnless
         
     | 
| 
       36 
37 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
         @@ -57,7 +58,7 @@ module RuboCop 
     | 
|
| 
       57 
58 
     | 
    
         | 
| 
       58 
59 
     | 
    
         
             
                    def autocorrect(corrector, node)
         
     | 
| 
       59 
60 
     | 
    
         
             
                      if always_multiline? || cannot_replace_to_ternary?(node)
         
     | 
| 
       60 
     | 
    
         
            -
                        IfThenCorrector.new(node, indentation:  
     | 
| 
      
 61 
     | 
    
         
            +
                        IfThenCorrector.new(node, indentation: configured_indentation_width).call(corrector)
         
     | 
| 
       61 
62 
     | 
    
         
             
                      else
         
     | 
| 
       62 
63 
     | 
    
         
             
                        corrector.replace(node, ternary_correction(node))
         
     | 
| 
       63 
64 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -67,7 +68,7 @@ module RuboCop 
     | 
|
| 
       67 
68 
     | 
    
         
             
                      replaced_node = ternary_replacement(node)
         
     | 
| 
       68 
69 
     | 
    
         | 
| 
       69 
70 
     | 
    
         
             
                      return replaced_node unless node.parent
         
     | 
| 
       70 
     | 
    
         
            -
                      return "(#{replaced_node})" if  
     | 
| 
      
 71 
     | 
    
         
            +
                      return "(#{replaced_node})" if node.parent.operator_keyword?
         
     | 
| 
       71 
72 
     | 
    
         
             
                      return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
         
     | 
| 
       72 
73 
     | 
    
         | 
| 
       73 
74 
     | 
    
         
             
                      replaced_node
         
     | 
| 
         @@ -116,10 +117,6 @@ module RuboCop 
     | 
|
| 
       116 
117 
     | 
    
         | 
| 
       117 
118 
     | 
    
         
             
                      node.respond_to?(:arguments?) && node.arguments? && !node.parenthesized_call?
         
     | 
| 
       118 
119 
     | 
    
         
             
                    end
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
                    def indentation_width
         
     | 
| 
       121 
     | 
    
         
            -
                      @config.for_cop('Layout/IndentationWidth')['Width']
         
     | 
| 
       122 
     | 
    
         
            -
                    end
         
     | 
| 
       123 
120 
     | 
    
         
             
                  end
         
     | 
| 
       124 
121 
     | 
    
         
             
                end
         
     | 
| 
       125 
122 
     | 
    
         
             
              end
         
     | 
| 
         @@ -25,7 +25,7 @@ module RuboCop 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       27 
27 
     | 
    
         
             
                      return unless (dot = node.loc.dot)
         
     | 
| 
       28 
     | 
    
         
            -
                      return if node.receiver.const_type?
         
     | 
| 
      
 28 
     | 
    
         
            +
                      return if node.receiver.const_type? || !node.arguments.one?
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                      _lhs, _op, rhs = *node
         
     | 
| 
       31 
31 
     | 
    
         
             
                      return if !rhs || method_call_with_parenthesized_arg?(rhs) || anonymous_forwarding?(rhs)
         
     | 
| 
         @@ -47,7 +47,7 @@ module RuboCop 
     | 
|
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                    def anonymous_forwarding?(argument)
         
     | 
| 
       49 
49 
     | 
    
         
             
                      return true if argument.forwarded_args_type? || argument.forwarded_restarg_type?
         
     | 
| 
       50 
     | 
    
         
            -
                      return true if argument.children.first&.forwarded_kwrestarg_type?
         
     | 
| 
      
 50 
     | 
    
         
            +
                      return true if argument.hash_type? && argument.children.first&.forwarded_kwrestarg_type?
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
                      argument.block_pass_type? && argument.source == '&'
         
     | 
| 
       53 
53 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -172,7 +172,9 @@ module RuboCop 
     | 
|
| 
       172 
172 
     | 
    
         
             
                    end
         
     | 
| 
       173 
173 
     | 
    
         | 
| 
       174 
174 
     | 
    
         
             
                    def modifier_statement?(node)
         
     | 
| 
       175 
     | 
    
         
            -
                       
     | 
| 
      
 175 
     | 
    
         
            +
                      return false unless node
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                      node.basic_conditional? && node.modifier_form?
         
     | 
| 
       176 
178 
     | 
    
         
             
                    end
         
     | 
| 
       177 
179 
     | 
    
         | 
| 
       178 
180 
     | 
    
         
             
                    # An internal class for correcting parallel assignment
         
     | 
| 
         @@ -36,6 +36,9 @@ module RuboCop 
     | 
|
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                    MSG = 'Use double pipes `||` instead.'
         
     | 
| 
       38 
38 
     | 
    
         
             
                    REDUNDANT_CONDITION = 'This condition is not needed.'
         
     | 
| 
      
 39 
     | 
    
         
            +
                    ARGUMENT_WITH_OPERATOR_TYPES = %i[
         
     | 
| 
      
 40 
     | 
    
         
            +
                      splat block_pass forwarded_restarg forwarded_kwrestarg forwarded_args
         
     | 
| 
      
 41 
     | 
    
         
            +
                    ].freeze
         
     | 
| 
       39 
42 
     | 
    
         | 
| 
       40 
43 
     | 
    
         
             
                    def on_if(node)
         
     | 
| 
       41 
44 
     | 
    
         
             
                      return if node.elsif_conditional?
         
     | 
| 
         @@ -150,13 +153,25 @@ module RuboCop 
     | 
|
| 
       150 
153 
     | 
    
         
             
                    end
         
     | 
| 
       151 
154 
     | 
    
         | 
| 
       152 
155 
     | 
    
         
             
                    def single_argument_method?(node)
         
     | 
| 
       153 
     | 
    
         
            -
                      node.send_type?  
     | 
| 
      
 156 
     | 
    
         
            +
                      return false if !node.send_type? || node.method?(:[]) || !node.arguments.one?
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                      !argument_with_operator?(node.first_argument)
         
     | 
| 
       154 
159 
     | 
    
         
             
                    end
         
     | 
| 
       155 
160 
     | 
    
         | 
| 
       156 
161 
     | 
    
         
             
                    def same_method?(if_branch, else_branch)
         
     | 
| 
       157 
162 
     | 
    
         
             
                      if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
         
     | 
| 
       158 
163 
     | 
    
         
             
                    end
         
     | 
| 
       159 
164 
     | 
    
         | 
| 
      
 165 
     | 
    
         
            +
                    # If the argument is using an operator, it is an invalid syntax.
         
     | 
| 
      
 166 
     | 
    
         
            +
                    # e.g. `foo || *bar`, `foo || **bar`, and `foo || &bar`.
         
     | 
| 
      
 167 
     | 
    
         
            +
                    def argument_with_operator?(argument)
         
     | 
| 
      
 168 
     | 
    
         
            +
                      return true if ARGUMENT_WITH_OPERATOR_TYPES.include?(argument.type)
         
     | 
| 
      
 169 
     | 
    
         
            +
                      return false unless argument.hash_type?
         
     | 
| 
      
 170 
     | 
    
         
            +
                      return false unless (node = argument.children.first)
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                      node.kwsplat_type? || node.forwarded_kwrestarg_type?
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
       160 
175 
     | 
    
         
             
                    def if_source(if_branch, arithmetic_operation)
         
     | 
| 
       161 
176 
     | 
    
         
             
                      if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
         
     | 
| 
       162 
177 
     | 
    
         
             
                        if_branch.source.delete_suffix(')')
         
     | 
| 
         @@ -18,21 +18,27 @@ module RuboCop 
     | 
|
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                    MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                    # @!method double_splat_hash_braces?(node)
         
     | 
| 
       22 
     | 
    
         
            -
                    def_node_matcher :double_splat_hash_braces?, <<~PATTERN
         
     | 
| 
       23 
     | 
    
         
            -
                      (hash (kwsplat (hash ...)))
         
     | 
| 
       24 
     | 
    
         
            -
                    PATTERN
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
21 
     | 
    
         
             
                    def on_hash(node)
         
     | 
| 
       27 
22 
     | 
    
         
             
                      return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      return unless (parent = node.parent)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      return unless parent.kwsplat_type?
         
     | 
| 
       28 
25 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
                       
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                        corrector.replace(grandparent, node.children.map(&:source).join(', '))
         
     | 
| 
      
 26 
     | 
    
         
            +
                      add_offense(parent) do |corrector|
         
     | 
| 
      
 27 
     | 
    
         
            +
                        corrector.remove(parent.loc.operator)
         
     | 
| 
      
 28 
     | 
    
         
            +
                        corrector.remove(opening_brace(node))
         
     | 
| 
      
 29 
     | 
    
         
            +
                        corrector.remove(closing_brace(node))
         
     | 
| 
       34 
30 
     | 
    
         
             
                      end
         
     | 
| 
       35 
31 
     | 
    
         
             
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    def opening_brace(node)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      node.loc.begin.join(node.children.first.loc.expression.begin)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def closing_brace(node)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      node.children.last.loc.expression.end.join(node.loc.end)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
       36 
42 
     | 
    
         
             
                  end
         
     | 
| 
       37 
43 
     | 
    
         
             
                end
         
     | 
| 
       38 
44 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Style
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Checks for redundant heredoc delimiter quotes.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #   do_something(<<~'EOS')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #     no string interpolation style text
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   EOS
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   do_something(<<~EOS)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #     no string interpolation style text
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   EOS
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #   do_something(<<~'EOS')
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #     #{string_interpolation_style_text_not_evaluated}
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #   EOS
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #   do_something(<<~'EOS')
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #     Preserve \
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #     newlines
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   EOS
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  class RedundantHeredocDelimiterQuotes < Base
         
     | 
| 
      
 30 
     | 
    
         
            +
                    include Heredoc
         
     | 
| 
      
 31 
     | 
    
         
            +
                    extend AutoCorrector
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    MSG = 'Remove the redundant heredoc delimiter quotes, use `%<replacement>s` instead.'
         
     | 
| 
      
 34 
     | 
    
         
            +
                    STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN = /#(\{|@|\$)|\\/.freeze
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    def on_heredoc(node)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      return if need_heredoc_delimiter_quotes?(node)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      replacement = "#{heredoc_type(node)}#{delimiter_string(node)}"
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                      add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
         
     | 
| 
      
 42 
     | 
    
         
            +
                        corrector.replace(node, replacement)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    private
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    def need_heredoc_delimiter_quotes?(node)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      heredoc_delimiter = node.source.delete(heredoc_type(node))
         
     | 
| 
      
 50 
     | 
    
         
            +
                      return true unless heredoc_delimiter.start_with?("'", '"')
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                      node.loc.heredoc_end.source.strip.match?(/\W/) ||
         
     | 
| 
      
 53 
     | 
    
         
            +
                        node.loc.heredoc_body.source.match?(STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -88,10 +88,9 @@ module RuboCop 
     | 
|
| 
       88 
88 
     | 
    
         
             
                      return unless previous_older_sibling
         
     | 
| 
       89 
89 
     | 
    
         | 
| 
       90 
90 
     | 
    
         
             
                      add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
         
     | 
| 
       91 
     | 
    
         
            -
                        swap(
         
     | 
| 
      
 91 
     | 
    
         
            +
                        corrector.swap(
         
     | 
| 
       92 
92 
     | 
    
         
             
                          range_with_comments_and_lines(previous_older_sibling),
         
     | 
| 
       93 
     | 
    
         
            -
                          range_with_comments_and_lines(node.parent.if_type? ? node.parent : node) 
     | 
| 
       94 
     | 
    
         
            -
                          corrector: corrector
         
     | 
| 
      
 93 
     | 
    
         
            +
                          range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
         
     | 
| 
       95 
94 
     | 
    
         
             
                        )
         
     | 
| 
       96 
95 
     | 
    
         
             
                      end
         
     | 
| 
       97 
96 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -130,12 +129,6 @@ module RuboCop 
     | 
|
| 
       130 
129 
     | 
    
         
             
                        end_pos: node2.location.expression.end_pos
         
     | 
| 
       131 
130 
     | 
    
         
             
                      ).source.include?("\n\n")
         
     | 
| 
       132 
131 
     | 
    
         
             
                    end
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                    def swap(range1, range2, corrector:)
         
     | 
| 
       135 
     | 
    
         
            -
                      inserted = range2.source
         
     | 
| 
       136 
     | 
    
         
            -
                      corrector.insert_before(range1, inserted)
         
     | 
| 
       137 
     | 
    
         
            -
                      corrector.remove(range2)
         
     | 
| 
       138 
     | 
    
         
            -
                    end
         
     | 
| 
       139 
132 
     | 
    
         
             
                  end
         
     | 
| 
       140 
133 
     | 
    
         
             
                end
         
     | 
| 
       141 
134 
     | 
    
         
             
              end
         
     | 
| 
         @@ -42,7 +42,7 @@ module RuboCop 
     | 
|
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
                      if rhs.send_type?
         
     | 
| 
       44 
44 
     | 
    
         
             
                        check_send_node(node, rhs, var_name, var_type)
         
     | 
| 
       45 
     | 
    
         
            -
                      elsif  
     | 
| 
      
 45 
     | 
    
         
            +
                      elsif rhs.operator_keyword?
         
     | 
| 
       46 
46 
     | 
    
         
             
                        check_boolean_node(node, rhs, var_name, var_type)
         
     | 
| 
       47 
47 
     | 
    
         
             
                      end
         
     | 
| 
       48 
48 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -76,7 +76,7 @@ module RuboCop 
     | 
|
| 
       76 
76 
     | 
    
         | 
| 
       77 
77 
     | 
    
         
             
                      if rhs.send_type?
         
     | 
| 
       78 
78 
     | 
    
         
             
                        autocorrect_send_node(corrector, node, rhs)
         
     | 
| 
       79 
     | 
    
         
            -
                      elsif  
     | 
| 
      
 79 
     | 
    
         
            +
                      elsif rhs.operator_keyword?
         
     | 
| 
       80 
80 
     | 
    
         
             
                        autocorrect_boolean_node(corrector, node, rhs)
         
     | 
| 
       81 
81 
     | 
    
         
             
                      end
         
     | 
| 
       82 
82 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -72,8 +72,10 @@ module RuboCop 
     | 
|
| 
       72 
72 
     | 
    
         | 
| 
       73 
73 
     | 
    
         
             
                    def each_semicolon
         
     | 
| 
       74 
74 
     | 
    
         
             
                      tokens_for_lines.each do |line, tokens|
         
     | 
| 
       75 
     | 
    
         
            -
                         
     | 
| 
       76 
     | 
    
         
            -
                         
     | 
| 
      
 75 
     | 
    
         
            +
                        semicolon_pos = semicolon_position(tokens)
         
     | 
| 
      
 76 
     | 
    
         
            +
                        after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                        yield line, tokens[semicolon_pos].column, tokens[after_expr_pos] if semicolon_pos
         
     | 
| 
       77 
79 
     | 
    
         
             
                      end
         
     | 
| 
       78 
80 
     | 
    
         
             
                    end
         
     | 
| 
       79 
81 
     | 
    
         | 
| 
         @@ -81,6 +83,26 @@ module RuboCop 
     | 
|
| 
       81 
83 
     | 
    
         
             
                      processed_source.tokens.group_by(&:line)
         
     | 
| 
       82 
84 
     | 
    
         
             
                    end
         
     | 
| 
       83 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
                    def semicolon_position(tokens)
         
     | 
| 
      
 87 
     | 
    
         
            +
                      if tokens.last.semicolon?
         
     | 
| 
      
 88 
     | 
    
         
            +
                        -1
         
     | 
| 
      
 89 
     | 
    
         
            +
                      elsif tokens.first.semicolon?
         
     | 
| 
      
 90 
     | 
    
         
            +
                        0
         
     | 
| 
      
 91 
     | 
    
         
            +
                      elsif exist_semicolon_before_right_curly_brace?(tokens)
         
     | 
| 
      
 92 
     | 
    
         
            +
                        -3
         
     | 
| 
      
 93 
     | 
    
         
            +
                      elsif exist_semicolon_after_left_curly_brace?(tokens)
         
     | 
| 
      
 94 
     | 
    
         
            +
                        2
         
     | 
| 
      
 95 
     | 
    
         
            +
                      end
         
     | 
| 
      
 96 
     | 
    
         
            +
                    end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                    def exist_semicolon_before_right_curly_brace?(tokens)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
         
     | 
| 
      
 100 
     | 
    
         
            +
                    end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    def exist_semicolon_after_left_curly_brace?(tokens)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
       84 
106 
     | 
    
         
             
                    def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
         
     | 
| 
       85 
107 
     | 
    
         
             
                      range = source_range(processed_source.buffer, line, column)
         
     | 
| 
       86 
108 
     | 
    
         |