rubocop 1.58.0 → 1.60.0
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/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/config/default.yml +9 -1
- data/lib/rubocop/config.rb +0 -2
- data/lib/rubocop/config_loader.rb +0 -1
- data/lib/rubocop/config_validator.rb +0 -2
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +5 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +16 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -1
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -0
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +23 -2
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/self_assignment.rb +1 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/syntax.rb +6 -3
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
- data/lib/rubocop/cop/naming/block_forwarding.rb +10 -2
- data/lib/rubocop/cop/naming/constant_name.rb +1 -2
- data/lib/rubocop/cop/registry.rb +4 -4
- data/lib/rubocop/cop/security/open.rb +2 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +16 -3
- data/lib/rubocop/cop/style/array_first_last.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +11 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/eval_with_location.rb +0 -11
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +29 -4
- data/lib/rubocop/cop/style/hash_except.rb +2 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +4 -1
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +39 -2
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +9 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +14 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -3
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -3
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +1 -0
- data/lib/rubocop/cop/style/redundant_each.rb +7 -4
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +8 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -7
- data/lib/rubocop/cop/style/redundant_self.rb +17 -2
- data/lib/rubocop/cop/style/redundant_sort.rb +8 -7
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/sample.rb +2 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +6 -5
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -2
- data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/string_chars.rb +1 -0
- data/lib/rubocop/cop/style/strip.rb +7 -4
- data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cops_documentation_generator.rb +11 -1
- data/lib/rubocop/ext/regexp_node.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/options.rb +0 -8
- data/lib/rubocop/rspec/shared_contexts.rb +6 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/server/cache.rb +0 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +8 -7
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
| @@ -186,12 +186,12 @@ module RuboCop | |
| 186 186 | 
             
                      rest_arg, kwrest_arg, _block_arg = *forwardable_args
         | 
| 187 187 |  | 
| 188 188 | 
             
                      send_classifications.each do |send_node, _c, forward_rest, forward_kwrest|
         | 
| 189 | 
            -
                        if forward_rest
         | 
| 189 | 
            +
                        if outside_block?(forward_rest)
         | 
| 190 190 | 
             
                          register_forward_args_offense(def_node.arguments, rest_arg)
         | 
| 191 191 | 
             
                          register_forward_args_offense(send_node, forward_rest)
         | 
| 192 192 | 
             
                        end
         | 
| 193 193 |  | 
| 194 | 
            -
                        if forward_kwrest
         | 
| 194 | 
            +
                        if outside_block?(forward_kwrest)
         | 
| 195 195 | 
             
                          register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
         | 
| 196 196 | 
             
                          register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
         | 
| 197 197 | 
             
                        end
         | 
| @@ -250,6 +250,12 @@ module RuboCop | |
| 250 250 | 
             
                      redundant_arg_names.include?(arg.source) ? arg : nil
         | 
| 251 251 | 
             
                    end
         | 
| 252 252 |  | 
| 253 | 
            +
                    def outside_block?(node)
         | 
| 254 | 
            +
                      return false unless node
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                      node.each_ancestor(:block, :numblock).none?
         | 
| 257 | 
            +
                    end
         | 
| 258 | 
            +
             | 
| 253 259 | 
             
                    def register_forward_args_offense(def_arguments_or_send, rest_arg_or_splat)
         | 
| 254 260 | 
             
                      add_offense(rest_arg_or_splat, message: ARGS_MSG) do |corrector|
         | 
| 255 261 | 
             
                        add_parens_if_missing(def_arguments_or_send, corrector)
         | 
| @@ -340,7 +346,7 @@ module RuboCop | |
| 340 346 | 
             
                      end
         | 
| 341 347 |  | 
| 342 348 | 
             
                      def classification
         | 
| 343 | 
            -
                        return nil unless forwarded_rest_arg || forwarded_kwrest_arg
         | 
| 349 | 
            +
                        return nil unless forwarded_rest_arg || forwarded_kwrest_arg || forwarded_block_arg
         | 
| 344 350 |  | 
| 345 351 | 
             
                        if can_forward_all?
         | 
| 346 352 | 
             
                          :all
         | 
| @@ -424,9 +430,16 @@ module RuboCop | |
| 424 430 | 
             
                      def no_additional_args?
         | 
| 425 431 | 
             
                        forwardable_count = [@rest_arg, @kwrest_arg, @block_arg].compact.size
         | 
| 426 432 |  | 
| 433 | 
            +
                        return false if missing_rest_arg_or_kwrest_arg?
         | 
| 434 | 
            +
             | 
| 427 435 | 
             
                        @def_node.arguments.size == forwardable_count &&
         | 
| 428 436 | 
             
                          @send_node.arguments.size == forwardable_count
         | 
| 429 437 | 
             
                      end
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                      def missing_rest_arg_or_kwrest_arg?
         | 
| 440 | 
            +
                        (@rest_arg_name && !forwarded_rest_arg) ||
         | 
| 441 | 
            +
                          (@kwrest_arg_name && !forwarded_kwrest_arg)
         | 
| 442 | 
            +
                      end
         | 
| 430 443 | 
             
                    end
         | 
| 431 444 | 
             
                  end
         | 
| 432 445 | 
             
                end
         | 
| @@ -4,7 +4,7 @@ module RuboCop | |
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module Style
         | 
| 6 6 | 
             
                  # Identifies usages of `arr[0]` and `arr[-1]` and suggests to change
         | 
| 7 | 
            -
                  # them to use `arr.first` and `arr.instead | 
| 7 | 
            +
                  # them to use `arr.first` and `arr.last` instead.
         | 
| 8 8 | 
             
                  #
         | 
| 9 9 | 
             
                  # The cop is disabled by default due to safety concerns.
         | 
| 10 10 | 
             
                  #
         | 
| @@ -53,7 +53,7 @@ module RuboCop | |
| 53 53 |  | 
| 54 54 | 
             
                    # @!method reject_method_with_block_pass?(node)
         | 
| 55 55 | 
             
                    def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
         | 
| 56 | 
            -
                      ( | 
| 56 | 
            +
                      (call !nil? {:reject :delete_if :reject!}
         | 
| 57 57 | 
             
                        (block_pass
         | 
| 58 58 | 
             
                          (sym :nil?)))
         | 
| 59 59 | 
             
                    PATTERN
         | 
| @@ -61,21 +61,21 @@ module RuboCop | |
| 61 61 | 
             
                    # @!method reject_method?(node)
         | 
| 62 62 | 
             
                    def_node_matcher :reject_method?, <<~PATTERN
         | 
| 63 63 | 
             
                      (block
         | 
| 64 | 
            -
                        ( | 
| 64 | 
            +
                        (call
         | 
| 65 65 | 
             
                          !nil? {:reject :delete_if :reject!})
         | 
| 66 66 | 
             
                        $(args ...)
         | 
| 67 | 
            -
                        ( | 
| 67 | 
            +
                        (call
         | 
| 68 68 | 
             
                          $(lvar _) :nil?))
         | 
| 69 69 | 
             
                    PATTERN
         | 
| 70 70 |  | 
| 71 71 | 
             
                    # @!method select_method?(node)
         | 
| 72 72 | 
             
                    def_node_matcher :select_method?, <<~PATTERN
         | 
| 73 73 | 
             
                      (block
         | 
| 74 | 
            -
                        ( | 
| 74 | 
            +
                        (call
         | 
| 75 75 | 
             
                          !nil? {:select :select!})
         | 
| 76 76 | 
             
                        $(args ...)
         | 
| 77 | 
            -
                        ( | 
| 78 | 
            -
                          ( | 
| 77 | 
            +
                        (call
         | 
| 78 | 
            +
                          (call
         | 
| 79 79 | 
             
                            $(lvar _) :nil?) :!))
         | 
| 80 80 | 
             
                    PATTERN
         | 
| 81 81 |  | 
| @@ -91,6 +91,7 @@ module RuboCop | |
| 91 91 |  | 
| 92 92 | 
             
                      add_offense(range, message: message) { |corrector| corrector.replace(range, good) }
         | 
| 93 93 | 
             
                    end
         | 
| 94 | 
            +
                    alias on_csend on_send
         | 
| 94 95 |  | 
| 95 96 | 
             
                    private
         | 
| 96 97 |  | 
| @@ -105,6 +105,17 @@ module RuboCop | |
| 105 105 | 
             
                    def combine_with_left_sibling(corrector, node)
         | 
| 106 106 | 
             
                      corrector.remove(node.left_sibling.body.source_range.end.join(node.left_sibling.loc.end))
         | 
| 107 107 | 
             
                      corrector.remove(node.source_range.begin.join(node.body.source_range.begin))
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                      correct_end_of_block(corrector, node)
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    def correct_end_of_block(corrector, node)
         | 
| 113 | 
            +
                      return unless node.left_sibling.respond_to?(:braces?)
         | 
| 114 | 
            +
                      return if node.right_sibling&.block_type? || node.right_sibling&.numblock_type?
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                      end_of_block = node.left_sibling.braces? ? '}' : ' end'
         | 
| 117 | 
            +
                      corrector.remove(node.loc.end)
         | 
| 118 | 
            +
                      corrector.insert_before(node.source_range.end, end_of_block)
         | 
| 108 119 | 
             
                    end
         | 
| 109 120 | 
             
                  end
         | 
| 110 121 | 
             
                end
         | 
| @@ -49,12 +49,12 @@ module RuboCop | |
| 49 49 | 
             
                  class DateTime < Base
         | 
| 50 50 | 
             
                    extend AutoCorrector
         | 
| 51 51 |  | 
| 52 | 
            -
                    CLASS_MSG = 'Prefer Time over DateTime | 
| 53 | 
            -
                    COERCION_MSG = 'Do not use  | 
| 52 | 
            +
                    CLASS_MSG = 'Prefer `Time` over `DateTime`.'
         | 
| 53 | 
            +
                    COERCION_MSG = 'Do not use `#to_datetime`.'
         | 
| 54 54 |  | 
| 55 55 | 
             
                    # @!method date_time?(node)
         | 
| 56 56 | 
             
                    def_node_matcher :date_time?, <<~PATTERN
         | 
| 57 | 
            -
                      ( | 
| 57 | 
            +
                      (call (const {nil? (cbase)} :DateTime) ...)
         | 
| 58 58 | 
             
                    PATTERN
         | 
| 59 59 |  | 
| 60 60 | 
             
                    # @!method historic_date?(node)
         | 
| @@ -64,7 +64,7 @@ module RuboCop | |
| 64 64 |  | 
| 65 65 | 
             
                    # @!method to_datetime?(node)
         | 
| 66 66 | 
             
                    def_node_matcher :to_datetime?, <<~PATTERN
         | 
| 67 | 
            -
                      ( | 
| 67 | 
            +
                      (call _ :to_datetime)
         | 
| 68 68 | 
             
                    PATTERN
         | 
| 69 69 |  | 
| 70 70 | 
             
                    def on_send(node)
         | 
| @@ -75,6 +75,7 @@ module RuboCop | |
| 75 75 |  | 
| 76 76 | 
             
                      add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
         | 
| 77 77 | 
             
                    end
         | 
| 78 | 
            +
                    alias on_csend on_send
         | 
| 78 79 |  | 
| 79 80 | 
             
                    private
         | 
| 80 81 |  | 
| @@ -32,27 +32,27 @@ module RuboCop | |
| 32 32 |  | 
| 33 33 | 
             
                      send_node = node.send_node
         | 
| 34 34 |  | 
| 35 | 
            -
                       | 
| 36 | 
            -
             | 
| 37 | 
            -
                      add_offense(range) do |corrector|
         | 
| 35 | 
            +
                      add_offense(send_node) do |corrector|
         | 
| 38 36 | 
             
                        range_type, min, max = each_range(node)
         | 
| 39 37 |  | 
| 40 38 | 
             
                        max += 1 if range_type == :irange
         | 
| 41 39 |  | 
| 42 | 
            -
                        corrector.replace( | 
| 40 | 
            +
                        corrector.replace(send_node, "#{max - min}.times")
         | 
| 43 41 | 
             
                      end
         | 
| 44 42 | 
             
                    end
         | 
| 45 43 |  | 
| 46 44 | 
             
                    private
         | 
| 47 45 |  | 
| 48 46 | 
             
                    def offending?(node)
         | 
| 47 | 
            +
                      return false unless node.arguments.empty?
         | 
| 48 | 
            +
             | 
| 49 49 | 
             
                      each_range_with_zero_origin?(node) || each_range_without_block_argument?(node)
         | 
| 50 50 | 
             
                    end
         | 
| 51 51 |  | 
| 52 52 | 
             
                    # @!method each_range(node)
         | 
| 53 53 | 
             
                    def_node_matcher :each_range, <<~PATTERN
         | 
| 54 54 | 
             
                      (block
         | 
| 55 | 
            -
                        ( | 
| 55 | 
            +
                        (call
         | 
| 56 56 | 
             
                          (begin
         | 
| 57 57 | 
             
                            (${irange erange}
         | 
| 58 58 | 
             
                              (int $_) (int $_)))
         | 
| @@ -64,7 +64,7 @@ module RuboCop | |
| 64 64 | 
             
                    # @!method each_range_with_zero_origin?(node)
         | 
| 65 65 | 
             
                    def_node_matcher :each_range_with_zero_origin?, <<~PATTERN
         | 
| 66 66 | 
             
                      (block
         | 
| 67 | 
            -
                        ( | 
| 67 | 
            +
                        (call
         | 
| 68 68 | 
             
                          (begin
         | 
| 69 69 | 
             
                            ({irange erange}
         | 
| 70 70 | 
             
                              (int 0) (int _)))
         | 
| @@ -76,7 +76,7 @@ module RuboCop | |
| 76 76 | 
             
                    # @!method each_range_without_block_argument?(node)
         | 
| 77 77 | 
             
                    def_node_matcher :each_range_without_block_argument?, <<~PATTERN
         | 
| 78 78 | 
             
                      (block
         | 
| 79 | 
            -
                        ( | 
| 79 | 
            +
                        (call
         | 
| 80 80 | 
             
                          (begin
         | 
| 81 81 | 
             
                            ({irange erange}
         | 
| 82 82 | 
             
                              (int _) (int _)))
         | 
| @@ -58,12 +58,12 @@ module RuboCop | |
| 58 58 |  | 
| 59 59 | 
             
                    # @!method each_with_object_block_candidate?(node)
         | 
| 60 60 | 
             
                    def_node_matcher :each_with_object_block_candidate?, <<~PATTERN
         | 
| 61 | 
            -
                      (block $( | 
| 61 | 
            +
                      (block $(call _ {:inject :reduce} _) $_ $_)
         | 
| 62 62 | 
             
                    PATTERN
         | 
| 63 63 |  | 
| 64 64 | 
             
                    # @!method each_with_object_numblock_candidate?(node)
         | 
| 65 65 | 
             
                    def_node_matcher :each_with_object_numblock_candidate?, <<~PATTERN
         | 
| 66 | 
            -
                      (numblock $( | 
| 66 | 
            +
                      (numblock $(call _ {:inject :reduce} _) 2 $_)
         | 
| 67 67 | 
             
                    PATTERN
         | 
| 68 68 |  | 
| 69 69 | 
             
                    def autocorrect_block(corrector, node, return_value)
         | 
| @@ -128,17 +128,6 @@ module RuboCop | |
| 128 128 | 
             
                      node.method?(:eval) ? node.arguments.size >= 2 : true
         | 
| 129 129 | 
             
                    end
         | 
| 130 130 |  | 
| 131 | 
            -
                    # FIXME: It's a Style/ConditionalAssignment's false positive.
         | 
| 132 | 
            -
                    # rubocop:disable Style/ConditionalAssignment
         | 
| 133 | 
            -
                    def with_lineno?(node)
         | 
| 134 | 
            -
                      if node.method?(:eval)
         | 
| 135 | 
            -
                        node.arguments.size == 4
         | 
| 136 | 
            -
                      else
         | 
| 137 | 
            -
                        node.arguments.size == 3
         | 
| 138 | 
            -
                      end
         | 
| 139 | 
            -
                    end
         | 
| 140 | 
            -
                    # rubocop:enable Style/ConditionalAssignment
         | 
| 141 | 
            -
             | 
| 142 131 | 
             
                    def add_offense_for_incorrect_line(method_name, line_node, sign, line_diff)
         | 
| 143 132 | 
             
                      expected = expected_line(sign, line_diff)
         | 
| 144 133 | 
             
                      message = format(MSG_INCORRECT_LINE,
         | 
| @@ -30,7 +30,7 @@ module RuboCop | |
| 30 30 |  | 
| 31 31 | 
             
                    # @!method exact_regexp_match(node)
         | 
| 32 32 | 
             
                    def_node_matcher :exact_regexp_match, <<~PATTERN
         | 
| 33 | 
            -
                      ( | 
| 33 | 
            +
                      (call
         | 
| 34 34 | 
             
                        _ {:=~ :=== :!~ :match :match?}
         | 
| 35 35 | 
             
                        (regexp
         | 
| 36 36 | 
             
                          (str $_)
         | 
| @@ -49,6 +49,7 @@ module RuboCop | |
| 49 49 | 
             
                        corrector.replace(node, prefer)
         | 
| 50 50 | 
             
                      end
         | 
| 51 51 | 
             
                    end
         | 
| 52 | 
            +
                    alias on_csend on_send
         | 
| 52 53 |  | 
| 53 54 | 
             
                    private
         | 
| 54 55 |  | 
| @@ -58,18 +58,20 @@ module RuboCop | |
| 58 58 |  | 
| 59 59 | 
             
                    # rubocop:disable Metrics/AbcSize
         | 
| 60 60 | 
             
                    def on_block(node)
         | 
| 61 | 
            +
                      return unless handleable?(node)
         | 
| 62 | 
            +
             | 
| 61 63 | 
             
                      kv_each(node) do |target, method|
         | 
| 62 64 | 
             
                        register_kv_offense(target, method) and return
         | 
| 63 65 | 
             
                      end
         | 
| 64 66 |  | 
| 65 67 | 
             
                      return unless (key, value = each_arguments(node))
         | 
| 66 68 |  | 
| 67 | 
            -
                      if unused_block_arg_exist?(node, value | 
| 69 | 
            +
                      if unused_block_arg_exist?(node, value)
         | 
| 68 70 | 
             
                        message = message('each_key', node.method_name, value.source)
         | 
| 69 71 | 
             
                        unused_range = key.source_range.end.join(value.source_range.end)
         | 
| 70 72 |  | 
| 71 73 | 
             
                        register_each_args_offense(node, message, 'each_key', unused_range)
         | 
| 72 | 
            -
                      elsif unused_block_arg_exist?(node, key | 
| 74 | 
            +
                      elsif unused_block_arg_exist?(node, key)
         | 
| 73 75 | 
             
                        message = message('each_value', node.method_name, key.source)
         | 
| 74 76 | 
             
                        unused_range = key.source_range.begin.join(value.source_range.begin)
         | 
| 75 77 |  | 
| @@ -88,6 +90,12 @@ module RuboCop | |
| 88 90 |  | 
| 89 91 | 
             
                    private
         | 
| 90 92 |  | 
| 93 | 
            +
                    def handleable?(node)
         | 
| 94 | 
            +
                      return false unless (root_receiver = root_receiver(node))
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                      !root_receiver.literal? || root_receiver.hash_type?
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
             | 
| 91 99 | 
             
                    def register_kv_offense(target, method)
         | 
| 92 100 | 
             
                      return unless (parent_receiver = target.receiver.receiver)
         | 
| 93 101 | 
             
                      return if allowed_receiver?(parent_receiver)
         | 
| @@ -99,8 +107,16 @@ module RuboCop | |
| 99 107 | 
             
                      end
         | 
| 100 108 | 
             
                    end
         | 
| 101 109 |  | 
| 102 | 
            -
                    def unused_block_arg_exist?(node,  | 
| 103 | 
            -
                      node.body.each_descendant(:lvar).map(&:source) | 
| 110 | 
            +
                    def unused_block_arg_exist?(node, block_arg)
         | 
| 111 | 
            +
                      lvar_sources = node.body.each_descendant(:lvar).map(&:source)
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                      if block_arg.mlhs_type?
         | 
| 114 | 
            +
                        block_arg.each_descendant(:arg, :restarg).all? do |block_arg|
         | 
| 115 | 
            +
                          lvar_sources.none?(block_arg.source.delete_prefix('*'))
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
                      else
         | 
| 118 | 
            +
                        lvar_sources.none?(block_arg.source.delete_prefix('*'))
         | 
| 119 | 
            +
                      end
         | 
| 104 120 | 
             
                    end
         | 
| 105 121 |  | 
| 106 122 | 
             
                    def message(prefer, method_name, unused_code)
         | 
| @@ -127,6 +143,15 @@ module RuboCop | |
| 127 143 | 
             
                      end
         | 
| 128 144 | 
             
                    end
         | 
| 129 145 |  | 
| 146 | 
            +
                    def root_receiver(node)
         | 
| 147 | 
            +
                      receiver = node.receiver
         | 
| 148 | 
            +
                      if receiver&.receiver
         | 
| 149 | 
            +
                        root_receiver(receiver)
         | 
| 150 | 
            +
                      else
         | 
| 151 | 
            +
                        receiver
         | 
| 152 | 
            +
                      end
         | 
| 153 | 
            +
                    end
         | 
| 154 | 
            +
             | 
| 130 155 | 
             
                    def format_message(method_name, current)
         | 
| 131 156 | 
             
                      format(MSG, prefer: "each_#{method_name[0..-2]}", current: current)
         | 
| 132 157 | 
             
                    end
         | 
| @@ -43,7 +43,7 @@ module RuboCop | |
| 43 43 | 
             
                    # @!method bad_method_with_poro?(node)
         | 
| 44 44 | 
             
                    def_node_matcher :bad_method_with_poro?, <<~PATTERN
         | 
| 45 45 | 
             
                      (block
         | 
| 46 | 
            -
                        ( | 
| 46 | 
            +
                        (call _ _)
         | 
| 47 47 | 
             
                        (args
         | 
| 48 48 | 
             
                          $(arg _)
         | 
| 49 49 | 
             
                          (arg _))
         | 
| @@ -86,6 +86,7 @@ module RuboCop | |
| 86 86 | 
             
                        corrector.replace(range, preferred_method)
         | 
| 87 87 | 
             
                      end
         | 
| 88 88 | 
             
                    end
         | 
| 89 | 
            +
                    alias on_csend on_send
         | 
| 89 90 |  | 
| 90 91 | 
             
                    private
         | 
| 91 92 |  | 
| @@ -158,7 +158,10 @@ module RuboCop | |
| 158 158 | 
             
                      if head.assignment?
         | 
| 159 159 | 
             
                        # The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
         | 
| 160 160 | 
             
                        # https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
         | 
| 161 | 
            -
                         | 
| 161 | 
            +
                        #
         | 
| 162 | 
            +
                        # FIXME: It would be better to update `RuboCop::AST::OpAsgnNode` or its subclasses to
         | 
| 163 | 
            +
                        # handle `self.foo ||= value` as a solution, instead of using `head.node_parts[0].to_s`.
         | 
| 164 | 
            +
                        assigned_value = head.send_type? ? head.receiver.source : head.node_parts[0].to_s
         | 
| 162 165 |  | 
| 163 166 | 
             
                        return if condition_variable == assigned_value
         | 
| 164 167 | 
             
                      end
         | 
| @@ -51,7 +51,7 @@ module RuboCop | |
| 51 51 | 
             
                  class InvertibleUnlessCondition < Base
         | 
| 52 52 | 
             
                    extend AutoCorrector
         | 
| 53 53 |  | 
| 54 | 
            -
                    MSG = ' | 
| 54 | 
            +
                    MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
         | 
| 55 55 |  | 
| 56 56 | 
             
                    def on_if(node)
         | 
| 57 57 | 
             
                      return unless node.unless?
         | 
| @@ -59,7 +59,10 @@ module RuboCop | |
| 59 59 | 
             
                      condition = node.condition
         | 
| 60 60 | 
             
                      return unless invertible?(condition)
         | 
| 61 61 |  | 
| 62 | 
            -
                       | 
| 62 | 
            +
                      message = format(MSG, prefer: "#{node.inverse_keyword} #{preferred_condition(condition)}",
         | 
| 63 | 
            +
                                            current: "#{node.keyword} #{condition.source}")
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                      add_offense(node, message: message) do |corrector|
         | 
| 63 66 | 
             
                        corrector.replace(node.loc.keyword, node.inverse_keyword)
         | 
| 64 67 | 
             
                        autocorrect(corrector, condition)
         | 
| 65 68 | 
             
                      end
         | 
| @@ -88,6 +91,40 @@ module RuboCop | |
| 88 91 | 
             
                        (argument.const_type? && argument.short_name.to_s.upcase != argument.short_name.to_s)
         | 
| 89 92 | 
             
                    end
         | 
| 90 93 |  | 
| 94 | 
            +
                    def preferred_condition(node)
         | 
| 95 | 
            +
                      case node.type
         | 
| 96 | 
            +
                      when :begin    then "(#{preferred_condition(node.children.first)})"
         | 
| 97 | 
            +
                      when :send     then preferred_send_condition(node)
         | 
| 98 | 
            +
                      when :or, :and then preferred_logical_condition(node)
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    def preferred_send_condition(node)
         | 
| 103 | 
            +
                      receiver_source = node.receiver.source
         | 
| 104 | 
            +
                      return receiver_source if node.method?(:!)
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                      inverse_method_name = inverse_methods[node.method_name]
         | 
| 107 | 
            +
                      return "#{receiver_source}.#{inverse_method_name}" unless node.arguments?
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                      argument_list = node.arguments.map(&:source).join(', ')
         | 
| 110 | 
            +
                      if node.operator_method?
         | 
| 111 | 
            +
                        return "#{receiver_source} #{inverse_method_name} #{argument_list}"
         | 
| 112 | 
            +
                      end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                      if node.parenthesized?
         | 
| 115 | 
            +
                        return "#{receiver_source}.#{inverse_method_name}(#{argument_list})"
         | 
| 116 | 
            +
                      end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                      "#{receiver_source}.#{inverse_method_name} #{argument_list}"
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                    def preferred_logical_condition(node)
         | 
| 122 | 
            +
                      preferred_lhs = preferred_condition(node.lhs)
         | 
| 123 | 
            +
                      preferred_rhs = preferred_condition(node.rhs)
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                      "#{preferred_lhs} #{node.inverse_operator} #{preferred_rhs}"
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 91 128 | 
             
                    def autocorrect(corrector, node)
         | 
| 92 129 | 
             
                      case node.type
         | 
| 93 130 | 
             
                      when :begin
         | 
| @@ -44,9 +44,9 @@ module RuboCop | |
| 44 44 |  | 
| 45 45 | 
             
                    # @!method map_and_compact?(node)
         | 
| 46 46 | 
             
                    def_node_matcher :map_and_compact?, <<~RUBY
         | 
| 47 | 
            -
                      ( | 
| 47 | 
            +
                      (call
         | 
| 48 48 | 
             
                        (block
         | 
| 49 | 
            -
                          ( | 
| 49 | 
            +
                          (call _ :map)
         | 
| 50 50 | 
             
                          (args
         | 
| 51 51 | 
             
                            $(arg _))
         | 
| 52 52 | 
             
                          {
         | 
| @@ -85,6 +85,7 @@ module RuboCop | |
| 85 85 | 
             
                        end
         | 
| 86 86 | 
             
                      end
         | 
| 87 87 | 
             
                    end
         | 
| 88 | 
            +
                    alias on_csend on_send
         | 
| 88 89 |  | 
| 89 90 | 
             
                    private
         | 
| 90 91 |  | 
| @@ -37,8 +37,8 @@ module RuboCop | |
| 37 37 | 
             
                    MSG = 'Pass a block to `to_h` instead of calling `%<method>s%<dot>sto_h`.'
         | 
| 38 38 | 
             
                    RESTRICT_ON_SEND = %i[to_h].freeze
         | 
| 39 39 |  | 
| 40 | 
            -
                    # @!method map_to_h | 
| 41 | 
            -
                    def_node_matcher :map_to_h | 
| 40 | 
            +
                    # @!method map_to_h(node)
         | 
| 41 | 
            +
                    def_node_matcher :map_to_h, <<~PATTERN
         | 
| 42 42 | 
             
                      {
         | 
| 43 43 | 
             
                        $(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
         | 
| 44 44 | 
             
                        $(call $(call _ {:map :collect} (block_pass sym)) :to_h)
         | 
| @@ -50,9 +50,9 @@ module RuboCop | |
| 50 50 | 
             
                    end
         | 
| 51 51 |  | 
| 52 52 | 
             
                    def on_send(node)
         | 
| 53 | 
            -
                      return unless (to_h_node, map_node = map_to_h | 
| 53 | 
            +
                      return unless (to_h_node, map_node = map_to_h(node))
         | 
| 54 54 |  | 
| 55 | 
            -
                      message = format(MSG, method: map_node.loc.selector.source, dot:  | 
| 55 | 
            +
                      message = format(MSG, method: map_node.loc.selector.source, dot: to_h_node.loc.dot.source)
         | 
| 56 56 | 
             
                      add_offense(map_node.loc.selector, message: message) do |corrector|
         | 
| 57 57 | 
             
                        # If the `to_h` call already has a block, do not autocorrect.
         | 
| 58 58 | 
             
                        next if to_h_node.block_node
         | 
| @@ -64,12 +64,17 @@ module RuboCop | |
| 64 64 |  | 
| 65 65 | 
             
                    private
         | 
| 66 66 |  | 
| 67 | 
            +
                    # rubocop:disable Metrics/AbcSize
         | 
| 67 68 | 
             
                    def autocorrect(corrector, to_h, map)
         | 
| 68 69 | 
             
                      removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)
         | 
| 69 70 |  | 
| 70 71 | 
             
                      corrector.remove(range_with_surrounding_space(removal_range, side: :left))
         | 
| 72 | 
            +
                      if (map_dot = map.loc.dot)
         | 
| 73 | 
            +
                        corrector.replace(map_dot, to_h.loc.dot.source)
         | 
| 74 | 
            +
                      end
         | 
| 71 75 | 
             
                      corrector.replace(map.loc.selector, 'to_h')
         | 
| 72 76 | 
             
                    end
         | 
| 77 | 
            +
                    # rubocop:enable Metrics/AbcSize
         | 
| 73 78 | 
             
                  end
         | 
| 74 79 | 
             
                end
         | 
| 75 80 | 
             
              end
         | 
| @@ -86,6 +86,7 @@ module RuboCop | |
| 86 86 |  | 
| 87 87 | 
             
                      def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/PerceivedComplexity
         | 
| 88 88 | 
             
                        call_in_literals?(node) ||
         | 
| 89 | 
            +
                          node.parent&.when_type? ||
         | 
| 89 90 | 
             
                          call_with_ambiguous_arguments?(node) ||
         | 
| 90 91 | 
             
                          call_in_logical_operators?(node) ||
         | 
| 91 92 | 
             
                          call_in_optional_arguments?(node) ||
         | 
| @@ -126,23 +127,31 @@ module RuboCop | |
| 126 127 |  | 
| 127 128 | 
             
                      def call_with_ambiguous_arguments?(node) # rubocop:disable Metrics/PerceivedComplexity
         | 
| 128 129 | 
             
                        call_with_braced_block?(node) ||
         | 
| 130 | 
            +
                          call_in_argument_with_block?(node) ||
         | 
| 129 131 | 
             
                          call_as_argument_or_chain?(node) ||
         | 
| 130 132 | 
             
                          call_in_match_pattern?(node) ||
         | 
| 131 133 | 
             
                          hash_literal_in_arguments?(node) ||
         | 
| 132 134 | 
             
                          node.descendants.any? do |n|
         | 
| 133 | 
            -
                            n.forwarded_args_type? ||  | 
| 134 | 
            -
                               | 
| 135 | 
            +
                            n.forwarded_args_type? || n.block_type? ||
         | 
| 136 | 
            +
                              ambiguous_literal?(n) || logical_operator?(n)
         | 
| 135 137 | 
             
                          end
         | 
| 136 138 | 
             
                      end
         | 
| 137 139 |  | 
| 138 140 | 
             
                      def call_with_braced_block?(node)
         | 
| 139 | 
            -
                        (node. | 
| 141 | 
            +
                        (node.call_type? || node.super_type?) && node.block_node&.braces?
         | 
| 142 | 
            +
                      end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                      def call_in_argument_with_block?(node)
         | 
| 145 | 
            +
                        parent = node.parent&.block_type? && node.parent&.parent
         | 
| 146 | 
            +
                        return false unless parent
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                        parent.call_type? || parent.super_type? || parent.yield_type?
         | 
| 140 149 | 
             
                      end
         | 
| 141 150 |  | 
| 142 151 | 
             
                      def call_as_argument_or_chain?(node)
         | 
| 143 152 | 
             
                        node.parent &&
         | 
| 144 | 
            -
                          ( | 
| 145 | 
            -
                           | 
| 153 | 
            +
                          (node.parent.call_type? || node.parent.super_type? || node.parent.yield_type?) &&
         | 
| 154 | 
            +
                          !assigned_before?(node.parent, node)
         | 
| 146 155 | 
             
                      end
         | 
| 147 156 |  | 
| 148 157 | 
             
                      def call_in_match_pattern?(node)
         | 
| @@ -218,15 +218,13 @@ module RuboCop | |
| 218 218 | 
             
                      send(style, node) # call require_parentheses or omit_parentheses
         | 
| 219 219 | 
             
                    end
         | 
| 220 220 | 
             
                    alias on_csend on_send
         | 
| 221 | 
            -
                    alias on_super on_send
         | 
| 222 221 | 
             
                    alias on_yield on_send
         | 
| 223 222 |  | 
| 224 223 | 
             
                    private
         | 
| 225 224 |  | 
| 226 225 | 
             
                    def args_begin(node)
         | 
| 227 226 | 
             
                      loc = node.loc
         | 
| 228 | 
            -
                      selector =
         | 
| 229 | 
            -
                        node.super_type? || node.yield_type? ? loc.keyword : loc.selector
         | 
| 227 | 
            +
                      selector = node.yield_type? ? loc.keyword : loc.selector
         | 
| 230 228 |  | 
| 231 229 | 
             
                      resize_by = args_parenthesized?(node) ? 2 : 1
         | 
| 232 230 | 
             
                      selector.end.resize(resize_by)
         | 
| @@ -8,6 +8,9 @@ module RuboCop | |
| 8 8 | 
             
                  # This cop can be customized allowed methods with `AllowedMethods`.
         | 
| 9 9 | 
             
                  # By default, there are no methods to allowed.
         | 
| 10 10 | 
             
                  #
         | 
| 11 | 
            +
                  # NOTE: This cop allows the use of `it()` without arguments in blocks,
         | 
| 12 | 
            +
                  # as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop.
         | 
| 13 | 
            +
                  #
         | 
| 11 14 | 
             
                  # @example
         | 
| 12 15 | 
             
                  #   # bad
         | 
| 13 16 | 
             
                  #   object.some_method()
         | 
| @@ -30,15 +33,18 @@ module RuboCop | |
| 30 33 |  | 
| 31 34 | 
             
                    MSG = 'Do not use parentheses for method calls with no arguments.'
         | 
| 32 35 |  | 
| 36 | 
            +
                    # rubocop:disable Metrics/CyclomaticComplexity
         | 
| 33 37 | 
             
                    def on_send(node)
         | 
| 34 38 | 
             
                      return unless !node.arguments? && node.parenthesized?
         | 
| 35 39 | 
             
                      return if ineligible_node?(node)
         | 
| 36 40 | 
             
                      return if default_argument?(node)
         | 
| 37 41 | 
             
                      return if allowed_method_name?(node.method_name)
         | 
| 38 42 | 
             
                      return if same_name_assignment?(node)
         | 
| 43 | 
            +
                      return if parenthesized_it_method_in_block?(node)
         | 
| 39 44 |  | 
| 40 45 | 
             
                      register_offense(node)
         | 
| 41 46 | 
             
                    end
         | 
| 47 | 
            +
                    # rubocop:enable Metrics/CyclomaticComplexity
         | 
| 42 48 |  | 
| 43 49 | 
             
                    private
         | 
| 44 50 |  | 
| @@ -71,6 +77,20 @@ module RuboCop | |
| 71 77 | 
             
                      end
         | 
| 72 78 | 
             
                    end
         | 
| 73 79 |  | 
| 80 | 
            +
                    # Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
         | 
| 81 | 
            +
                    #
         | 
| 82 | 
            +
                    # $ ruby -e '0.times { begin; it; end }'
         | 
| 83 | 
            +
                    # -e:1: warning: `it` calls without arguments will refer to the first block param in
         | 
| 84 | 
            +
                    # Ruby 3.4; use it() or self.it
         | 
| 85 | 
            +
                    #
         | 
| 86 | 
            +
                    def parenthesized_it_method_in_block?(node)
         | 
| 87 | 
            +
                      return false unless node.method?(:it)
         | 
| 88 | 
            +
                      return false unless (block_node = node.each_ancestor(:block).first)
         | 
| 89 | 
            +
                      return false unless block_node.arguments.empty_and_without_delimiters?
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      !node.receiver && node.arguments.empty? && !node.block_literal?
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
             | 
| 74 94 | 
             
                    def any_assignment?(node)
         | 
| 75 95 | 
             
                      node.each_ancestor(*AST::Node::ASSIGNMENTS).any? do |asgn_node|
         | 
| 76 96 | 
             
                        # `obj.method = value` parses as (send ... :method= ...), and will
         | 
| @@ -54,12 +54,10 @@ module RuboCop | |
| 54 54 | 
             
                    private
         | 
| 55 55 |  | 
| 56 56 | 
             
                    def offense?(node)
         | 
| 57 | 
            -
                      node.ternary? && node.multiline?
         | 
| 57 | 
            +
                      node.ternary? && node.multiline? && node.source != replacement(node)
         | 
| 58 58 | 
             
                    end
         | 
| 59 59 |  | 
| 60 60 | 
             
                    def autocorrect(corrector, node)
         | 
| 61 | 
            -
                      return unless offense?(node)
         | 
| 62 | 
            -
             | 
| 63 61 | 
             
                      corrector.replace(node, replacement(node))
         | 
| 64 62 | 
             
                      return unless (parent = node.parent)
         | 
| 65 63 | 
             
                      return unless (comments_in_condition = comments_in_condition(node))
         |