rubocop 1.80.2 → 1.81.7
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 +14 -2
 - data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
 - data/lib/rubocop/cli.rb +1 -2
 - data/lib/rubocop/config_loader.rb +3 -1
 - data/lib/rubocop/config_loader_resolver.rb +5 -4
 - data/lib/rubocop/config_store.rb +5 -0
 - data/lib/rubocop/cop/autocorrect_logic.rb +4 -4
 - data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
 - data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
 - data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
 - data/lib/rubocop/cop/layout/class_structure.rb +1 -1
 - data/lib/rubocop/cop/layout/dot_position.rb +1 -1
 - data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
 - data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
 - data/lib/rubocop/cop/layout/line_length.rb +9 -1
 - data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
 - data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +8 -0
 - data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
 - data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
 - data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
 - data/lib/rubocop/cop/lint/debugger.rb +0 -2
 - data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
 - data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
 - data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
 - data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
 - data/lib/rubocop/cop/lint/self_assignment.rb +1 -1
 - data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
 - data/lib/rubocop/cop/lint/void.rb +7 -0
 - data/lib/rubocop/cop/message_annotator.rb +1 -1
 - data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
 - data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
 - data/lib/rubocop/cop/naming/method_name.rb +3 -1
 - data/lib/rubocop/cop/naming/predicate_method.rb +16 -4
 - data/lib/rubocop/cop/security/json_load.rb +33 -11
 - data/lib/rubocop/cop/style/array_intersect.rb +2 -2
 - data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
 - data/lib/rubocop/cop/style/conditional_assignment.rb +7 -3
 - data/lib/rubocop/cop/style/constant_visibility.rb +14 -9
 - data/lib/rubocop/cop/style/double_negation.rb +1 -1
 - data/lib/rubocop/cop/style/endless_method.rb +15 -2
 - data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
 - data/lib/rubocop/cop/style/float_division.rb +15 -1
 - data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
 - data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
 - data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
 - data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
 - data/lib/rubocop/cop/style/redundant_format.rb +26 -5
 - data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
 - data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -0
 - data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
 - data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
 - data/lib/rubocop/cop/style/semicolon.rb +23 -7
 - data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
 - data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
 - data/lib/rubocop/cop/style/unless_else.rb +10 -9
 - data/lib/rubocop/cop/utils/format_string.rb +10 -0
 - data/lib/rubocop/cops_documentation_generator.rb +4 -4
 - data/lib/rubocop/lsp/diagnostic.rb +21 -20
 - data/lib/rubocop/lsp/routes.rb +36 -9
 - data/lib/rubocop/lsp/runtime.rb +2 -2
 - data/lib/rubocop/lsp/server.rb +2 -2
 - data/lib/rubocop/lsp/stdin_runner.rb +0 -16
 - data/lib/rubocop/target_ruby.rb +10 -1
 - data/lib/rubocop/version.rb +1 -1
 - data/lib/rubocop.rb +1 -0
 - data/lib/ruby_lsp/rubocop/addon.rb +23 -8
 - data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
 - metadata +7 -6
 
| 
         @@ -16,6 +16,12 @@ module RuboCop 
     | 
|
| 
       16 
16 
     | 
    
         
             
                  # enumerator.each { |item| item >= 2 } #=> [2, 3]
         
     | 
| 
       17 
17 
     | 
    
         
             
                  # ----
         
     | 
| 
       18 
18 
     | 
    
         
             
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # NOTE: Return values in assignment method definitions such as `def foo=(arg)` are
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # detected because they are in a void context. However, autocorrection does not remove
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # the return value, as that would change behavior. In such cases, whether to remove
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # the return value or rename the method to something more appropriate should be left to
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # the user.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
       19 
25 
     | 
    
         
             
                  # @example CheckForMethodsWithNoSideEffects: false (default)
         
     | 
| 
       20 
26 
     | 
    
         
             
                  #   # bad
         
     | 
| 
       21 
27 
     | 
    
         
             
                  #   def some_method
         
     | 
| 
         @@ -233,6 +239,7 @@ module RuboCop 
     | 
|
| 
       233 
239 
     | 
    
         | 
| 
       234 
240 
     | 
    
         
             
                    def autocorrect_void_expression(corrector, node)
         
     | 
| 
       235 
241 
     | 
    
         
             
                      return if node.parent.if_type?
         
     | 
| 
      
 242 
     | 
    
         
            +
                      return if (def_node = node.each_ancestor(:any_def).first) && def_node.assignment_method?
         
     | 
| 
       236 
243 
     | 
    
         | 
| 
       237 
244 
     | 
    
         
             
                      corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
         
     | 
| 
       238 
245 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -140,7 +140,7 @@ module RuboCop 
     | 
|
| 
       140 
140 
     | 
    
         
             
                  end
         
     | 
| 
       141 
141 
     | 
    
         | 
| 
       142 
142 
     | 
    
         
             
                  def last_item_precedes_newline?(node)
         
     | 
| 
       143 
     | 
    
         
            -
                    after_last_item = node.children.last.source_range.end.join(node. 
     | 
| 
      
 143 
     | 
    
         
            +
                    after_last_item = node.children.last.source_range.end.join(node.source_range.end)
         
     | 
| 
       144 
144 
     | 
    
         | 
| 
       145 
145 
     | 
    
         
             
                    after_last_item.source.start_with?(/,?\s*(#.*)?\n/)
         
     | 
| 
       146 
146 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -147,7 +147,9 @@ module RuboCop 
     | 
|
| 
       147 
147 
     | 
    
         
             
                    alias on_defs on_def
         
     | 
| 
       148 
148 
     | 
    
         | 
| 
       149 
149 
     | 
    
         
             
                    def on_alias(node)
         
     | 
| 
       150 
     | 
    
         
            -
                       
     | 
| 
      
 150 
     | 
    
         
            +
                      return unless (new_identifier = node.new_identifier).sym_type?
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                      handle_method_name(new_identifier, new_identifier.value)
         
     | 
| 
       151 
153 
     | 
    
         
             
                    end
         
     | 
| 
       152 
154 
     | 
    
         | 
| 
       153 
155 
     | 
    
         
             
                    private
         
     | 
| 
         @@ -113,6 +113,18 @@ module RuboCop 
     | 
|
| 
       113 
113 
     | 
    
         
             
                  #     true
         
     | 
| 
       114 
114 
     | 
    
         
             
                  #   end
         
     | 
| 
       115 
115 
     | 
    
         
             
                  #
         
     | 
| 
      
 116 
     | 
    
         
            +
                  # @example AllowedMethods: [call] (default)
         
     | 
| 
      
 117 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 118 
     | 
    
         
            +
                  #   def call
         
     | 
| 
      
 119 
     | 
    
         
            +
                  #     foo == bar
         
     | 
| 
      
 120 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  #
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # @example AllowedPatterns: [\Afoo]
         
     | 
| 
      
 123 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 124 
     | 
    
         
            +
                  #   def foo?
         
     | 
| 
      
 125 
     | 
    
         
            +
                  #     'foo'
         
     | 
| 
      
 126 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  #
         
     | 
| 
       116 
128 
     | 
    
         
             
                  # @example AllowBangMethods: false (default)
         
     | 
| 
       117 
129 
     | 
    
         
             
                  #   # bad
         
     | 
| 
       118 
130 
     | 
    
         
             
                  #   def save!
         
     | 
| 
         @@ -181,8 +193,7 @@ module RuboCop 
     | 
|
| 
       181 
193 
     | 
    
         
             
                        return_values << extract_return_value(return_node)
         
     | 
| 
       182 
194 
     | 
    
         
             
                      end
         
     | 
| 
       183 
195 
     | 
    
         | 
| 
       184 
     | 
    
         
            -
                       
     | 
| 
       185 
     | 
    
         
            -
                      return_values << last_value if last_value
         
     | 
| 
      
 196 
     | 
    
         
            +
                      return_values << last_value(node)
         
     | 
| 
       186 
197 
     | 
    
         | 
| 
       187 
198 
     | 
    
         
             
                      process_return_values(return_values)
         
     | 
| 
       188 
199 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -235,8 +246,9 @@ module RuboCop 
     | 
|
| 
       235 
246 
     | 
    
         
             
                    end
         
     | 
| 
       236 
247 
     | 
    
         | 
| 
       237 
248 
     | 
    
         
             
                    def last_value(node)
         
     | 
| 
       238 
     | 
    
         
            -
                      value = node.begin_type? ? node.children.last : node
         
     | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
      
 249 
     | 
    
         
            +
                      value = node.begin_type? ? node.children.last || s(:nil) : node
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                      value.return_type? ? extract_return_value(value) : value
         
     | 
| 
       240 
252 
     | 
    
         
             
                    end
         
     | 
| 
       241 
253 
     | 
    
         | 
| 
       242 
254 
     | 
    
         
             
                    def process_return_values(return_values)
         
     | 
| 
         @@ -6,22 +6,40 @@ module RuboCop 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  # Checks for the use of JSON class methods which have potential
         
     | 
| 
       7 
7 
     | 
    
         
             
                  # security issues.
         
     | 
| 
       8 
8 
     | 
    
         
             
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # `JSON.load` and similar methods allow deserialization of arbitrary ruby objects:
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # [source,ruby]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # ----
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # require 'json/add/string'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # result = JSON.load('{ "json_class": "String", "raw": [72, 101, 108, 108, 111] }')
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # pp result # => "Hello"
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # ----
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # Never use `JSON.load` for untrusted user input. Prefer `JSON.parse` unless you have
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # a concrete use-case for `JSON.load`.
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # NOTE: Starting with `json` gem version 2.8.0, triggering this behavior without explicitly
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # passing the `create_additions` keyword argument emits a deprecation warning, with the
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # goal of being secure by default in the next major version 3.0.0.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
       9 
25 
     | 
    
         
             
                  # @safety
         
     | 
| 
       10 
26 
     | 
    
         
             
                  #   This cop's autocorrection is unsafe because it's potentially dangerous.
         
     | 
| 
       11 
     | 
    
         
            -
                  #   If using a stream, like `JSON.load(open('file'))`,  
     | 
| 
      
 27 
     | 
    
         
            +
                  #   If using a stream, like `JSON.load(open('file'))`, you will need to call
         
     | 
| 
       12 
28 
     | 
    
         
             
                  #   `#read` manually, like `JSON.parse(open('file').read)`.
         
     | 
| 
       13 
     | 
    
         
            -
                  #   If reading single values (rather than proper JSON objects), like
         
     | 
| 
       14 
     | 
    
         
            -
                  #   `JSON.load('false')`, it will need to pass the `quirks_mode: true`
         
     | 
| 
       15 
     | 
    
         
            -
                  #   option, like `JSON.parse('false', quirks_mode: true)`.
         
     | 
| 
       16 
29 
     | 
    
         
             
                  #   Other similar issues may apply.
         
     | 
| 
       17 
30 
     | 
    
         
             
                  #
         
     | 
| 
       18 
31 
     | 
    
         
             
                  # @example
         
     | 
| 
       19 
32 
     | 
    
         
             
                  #   # bad
         
     | 
| 
       20 
     | 
    
         
            -
                  #   JSON.load( 
     | 
| 
       21 
     | 
    
         
            -
                  #   JSON.restore( 
     | 
| 
      
 33 
     | 
    
         
            +
                  #   JSON.load('{}')
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #   JSON.restore('{}')
         
     | 
| 
       22 
35 
     | 
    
         
             
                  #
         
     | 
| 
       23 
36 
     | 
    
         
             
                  #   # good
         
     | 
| 
       24 
     | 
    
         
            -
                  #   JSON.parse( 
     | 
| 
      
 37 
     | 
    
         
            +
                  #   JSON.parse('{}')
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #   JSON.unsafe_load('{}')
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   # good - explicit use of `create_additions` option
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #   JSON.load('{}', create_additions: true)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #   JSON.load('{}', create_additions: false)
         
     | 
| 
       25 
43 
     | 
    
         
             
                  #
         
     | 
| 
       26 
44 
     | 
    
         
             
                  class JSONLoad < Base
         
     | 
| 
       27 
45 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
         @@ -29,13 +47,17 @@ module RuboCop 
     | 
|
| 
       29 
47 
     | 
    
         
             
                    MSG = 'Prefer `JSON.parse` over `JSON.%<method>s`.'
         
     | 
| 
       30 
48 
     | 
    
         
             
                    RESTRICT_ON_SEND = %i[load restore].freeze
         
     | 
| 
       31 
49 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                    # @!method  
     | 
| 
       33 
     | 
    
         
            -
                    def_node_matcher : 
     | 
| 
       34 
     | 
    
         
            -
                      ( 
     | 
| 
      
 50 
     | 
    
         
            +
                    # @!method insecure_json_load(node)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    def_node_matcher :insecure_json_load, <<~PATTERN
         
     | 
| 
      
 52 
     | 
    
         
            +
                      (
         
     | 
| 
      
 53 
     | 
    
         
            +
                        send (const {nil? cbase} :JSON) ${:load :restore}
         
     | 
| 
      
 54 
     | 
    
         
            +
                        ...
         
     | 
| 
      
 55 
     | 
    
         
            +
                        !(hash `(sym $:create_additions))
         
     | 
| 
      
 56 
     | 
    
         
            +
                      )
         
     | 
| 
       35 
57 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       36 
58 
     | 
    
         | 
| 
       37 
59 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       38 
     | 
    
         
            -
                       
     | 
| 
      
 60 
     | 
    
         
            +
                      insecure_json_load(node) do |method|
         
     | 
| 
       39 
61 
     | 
    
         
             
                        add_offense(node.loc.selector, message: format(MSG, method: method)) do |corrector|
         
     | 
| 
       40 
62 
     | 
    
         
             
                          corrector.replace(node.loc.selector, 'parse')
         
     | 
| 
       41 
63 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -95,7 +95,7 @@ module RuboCop 
     | 
|
| 
       95 
95 
     | 
    
         
             
                      $(call
         
     | 
| 
       96 
96 
     | 
    
         
             
                        {
         
     | 
| 
       97 
97 
     | 
    
         
             
                          (begin (send $_ :& $_))
         
     | 
| 
       98 
     | 
    
         
            -
                          (call  
     | 
| 
      
 98 
     | 
    
         
            +
                          (call $!nil? :intersection $_)
         
     | 
| 
       99 
99 
     | 
    
         
             
                        }
         
     | 
| 
       100 
100 
     | 
    
         
             
                        $%1
         
     | 
| 
       101 
101 
     | 
    
         
             
                      )
         
     | 
| 
         @@ -107,7 +107,7 @@ module RuboCop 
     | 
|
| 
       107 
107 
     | 
    
         
             
                        $(call
         
     | 
| 
       108 
108 
     | 
    
         
             
                          {
         
     | 
| 
       109 
109 
     | 
    
         
             
                            (begin (send $_ :& $_))
         
     | 
| 
       110 
     | 
    
         
            -
                            (call  
     | 
| 
      
 110 
     | 
    
         
            +
                            (call $!nil? :intersection $_)
         
     | 
| 
       111 
111 
     | 
    
         
             
                          }
         
     | 
| 
       112 
112 
     | 
    
         
             
                          %ARRAY_SIZE_METHODS
         
     | 
| 
       113 
113 
     | 
    
         
             
                        )
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Style
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use `include?(element)` instead of `intersect?([element])`.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @safety
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #   The receiver might not be an array.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   array.intersect?([element])
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   array.include?(element)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  class ArrayIntersectWithSingleElement < Base
         
     | 
| 
      
 18 
     | 
    
         
            +
                    extend AutoCorrector
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    MSG = 'Use `include?(element)` instead of `intersect?([element])`.'
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[intersect?].freeze
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    # @!method single_element(node)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    def_node_matcher :single_element, <<~PATTERN
         
     | 
| 
      
 26 
     | 
    
         
            +
                      (send _ _ $(array $_))
         
     | 
| 
      
 27 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def on_send(node)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      array, element = single_element(node)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      return unless array
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                      add_offense(
         
     | 
| 
      
 34 
     | 
    
         
            +
                        node.source_range.with(begin_pos: node.loc.selector.begin_pos)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      ) do |corrector|
         
     | 
| 
      
 36 
     | 
    
         
            +
                        corrector.replace(node.loc.selector, 'include?')
         
     | 
| 
      
 37 
     | 
    
         
            +
                        corrector.replace(
         
     | 
| 
      
 38 
     | 
    
         
            +
                          array,
         
     | 
| 
      
 39 
     | 
    
         
            +
                          array.percent_literal? ? element.value.inspect : element.source
         
     | 
| 
      
 40 
     | 
    
         
            +
                        )
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    alias on_csend on_send
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -444,7 +444,7 @@ module RuboCop 
     | 
|
| 
       444 
444 
     | 
    
         
             
                        next if child.parent.dstr_type?
         
     | 
| 
       445 
445 
     | 
    
         | 
| 
       446 
446 
     | 
    
         
             
                        white_space = white_space_range(child, column)
         
     | 
| 
       447 
     | 
    
         
            -
                        corrector.remove(white_space) if white_space 
     | 
| 
      
 447 
     | 
    
         
            +
                        corrector.remove(white_space) if white_space
         
     | 
| 
       448 
448 
     | 
    
         
             
                      end
         
     | 
| 
       449 
449 
     | 
    
         | 
| 
       450 
450 
     | 
    
         
             
                      if condition.loc.else && !same_line?(condition.else_branch, condition)
         
     | 
| 
         @@ -465,9 +465,13 @@ module RuboCop 
     | 
|
| 
       465 
465 
     | 
    
         | 
| 
       466 
466 
     | 
    
         
             
                    def white_space_range(node, column)
         
     | 
| 
       467 
467 
     | 
    
         
             
                      expression = node.source_range
         
     | 
| 
       468 
     | 
    
         
            -
                       
     | 
| 
      
 468 
     | 
    
         
            +
                      end_pos = expression.begin_pos
         
     | 
| 
      
 469 
     | 
    
         
            +
                      begin_pos = end_pos - (expression.column - column - 2)
         
     | 
| 
       469 
470 
     | 
    
         | 
| 
       470 
     | 
    
         
            -
                       
     | 
| 
      
 471 
     | 
    
         
            +
                      return nil if begin_pos > end_pos
         
     | 
| 
      
 472 
     | 
    
         
            +
             
     | 
| 
      
 473 
     | 
    
         
            +
                      white_space = Parser::Source::Range.new(expression.source_buffer, begin_pos, end_pos)
         
     | 
| 
      
 474 
     | 
    
         
            +
                      white_space if white_space.source.strip.empty?
         
     | 
| 
       471 
475 
     | 
    
         
             
                    end
         
     | 
| 
       472 
476 
     | 
    
         | 
| 
       473 
477 
     | 
    
         
             
                    def assignment(node)
         
     | 
| 
         @@ -48,6 +48,11 @@ module RuboCop 
     | 
|
| 
       48 
48 
     | 
    
         
             
                    MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
         
     | 
| 
       49 
49 
     | 
    
         
             
                          'either `#public_constant` or `#private_constant`.'
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
      
 51 
     | 
    
         
            +
                    # @!method visibility_declaration_for(node)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    def_node_matcher :visibility_declaration_for, <<~PATTERN
         
     | 
| 
      
 53 
     | 
    
         
            +
                      (send nil? {:public_constant :private_constant} $...)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
       51 
56 
     | 
    
         
             
                    def on_casgn(node)
         
     | 
| 
       52 
57 
     | 
    
         
             
                      return unless class_or_module_scope?(node)
         
     | 
| 
       53 
58 
     | 
    
         
             
                      return if visibility_declaration?(node)
         
     | 
| 
         @@ -77,20 +82,20 @@ module RuboCop 
     | 
|
| 
       77 
82 
     | 
    
         
             
                      end
         
     | 
| 
       78 
83 
     | 
    
         
             
                    end
         
     | 
| 
       79 
84 
     | 
    
         | 
| 
      
 85 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize
         
     | 
| 
       80 
86 
     | 
    
         
             
                    def visibility_declaration?(node)
         
     | 
| 
       81 
87 
     | 
    
         
             
                      node.parent.each_child_node(:send).any? do |child|
         
     | 
| 
       82 
     | 
    
         
            -
                        visibility_declaration_for 
     | 
| 
       83 
     | 
    
         
            -
                      end
         
     | 
| 
       84 
     | 
    
         
            -
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
                        next false unless (arguments = visibility_declaration_for(child))
         
     | 
| 
       85 
89 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
                        arguments = arguments.first.children.first.to_a if arguments.first&.splat_type?
         
     | 
| 
      
 91 
     | 
    
         
            +
                        constant_values = arguments.map do |argument|
         
     | 
| 
      
 92 
     | 
    
         
            +
                          argument.value.to_sym if argument.respond_to?(:value)
         
     | 
| 
      
 93 
     | 
    
         
            +
                        end
         
     | 
| 
       90 
94 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                       
     | 
| 
      
 95 
     | 
    
         
            +
                        constant_values.include?(node.name)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      end
         
     | 
| 
       93 
97 
     | 
    
         
             
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    # rubocop:enable Metrics/AbcSize
         
     | 
| 
       94 
99 
     | 
    
         
             
                  end
         
     | 
| 
       95 
100 
     | 
    
         
             
                end
         
     | 
| 
       96 
101 
     | 
    
         
             
              end
         
     | 
| 
         @@ -144,7 +144,7 @@ module RuboCop 
     | 
|
| 
       144 
144 
     | 
    
         
             
                    MSG_REQUIRE_ALWAYS = 'Use endless method definitions.'
         
     | 
| 
       145 
145 
     | 
    
         | 
| 
       146 
146 
     | 
    
         
             
                    def on_def(node)
         
     | 
| 
       147 
     | 
    
         
            -
                      return if node.assignment_method?
         
     | 
| 
      
 147 
     | 
    
         
            +
                      return if node.assignment_method? || use_heredoc?(node)
         
     | 
| 
       148 
148 
     | 
    
         | 
| 
       149 
149 
     | 
    
         
             
                      case style
         
     | 
| 
       150 
150 
     | 
    
         
             
                      when :allow_single_line, :allow_always
         
     | 
| 
         @@ -198,6 +198,13 @@ module RuboCop 
     | 
|
| 
       198 
198 
     | 
    
         
             
                      add_offense(node) { |corrector| correct_to_multiline(corrector, node) }
         
     | 
| 
       199 
199 
     | 
    
         
             
                    end
         
     | 
| 
       200 
200 
     | 
    
         | 
| 
      
 201 
     | 
    
         
            +
                    def use_heredoc?(node)
         
     | 
| 
      
 202 
     | 
    
         
            +
                      return false unless (body = node.body)
         
     | 
| 
      
 203 
     | 
    
         
            +
                      return true if body.str_type? && body.heredoc?
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                      body.each_descendant(:str).any?(&:heredoc?)
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
       201 
208 
     | 
    
         
             
                    def correct_to_multiline(corrector, node)
         
     | 
| 
       202 
209 
     | 
    
         
             
                      replacement = <<~RUBY.strip
         
     | 
| 
       203 
210 
     | 
    
         
             
                        def #{node.method_name}#{arguments(node)}
         
     | 
| 
         @@ -225,7 +232,13 @@ module RuboCop 
     | 
|
| 
       225 
232 
     | 
    
         
             
                    def too_long_when_made_endless?(node)
         
     | 
| 
       226 
233 
     | 
    
         
             
                      return false unless config.cop_enabled?('Layout/LineLength')
         
     | 
| 
       227 
234 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                       
     | 
| 
      
 235 
     | 
    
         
            +
                      offset = modifier_offset(node)
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                      endless_replacement(node).length + offset > config.for_cop('Layout/LineLength')['Max']
         
     | 
| 
      
 238 
     | 
    
         
            +
                    end
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                    def modifier_offset(node)
         
     | 
| 
      
 241 
     | 
    
         
            +
                      same_line?(node.parent, node) ? node.loc.column - node.parent.loc.column : 0
         
     | 
| 
       229 
242 
     | 
    
         
             
                    end
         
     | 
| 
       230 
243 
     | 
    
         
             
                  end
         
     | 
| 
       231 
244 
     | 
    
         
             
                end
         
     | 
| 
         @@ -7,9 +7,12 @@ module RuboCop 
     | 
|
| 
       7 
7 
     | 
    
         
             
                  # It is recommended to either always use `fdiv` or coerce one side only.
         
     | 
| 
       8 
8 
     | 
    
         
             
                  # This cop also provides other options for code consistency.
         
     | 
| 
       9 
9 
     | 
    
         
             
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # For `Regexp.last_match` and nth reference (e.g., `$1`), it assumes that the value
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # is a string matched by a regular expression, and allows conversion with `#to_f`.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
       10 
13 
     | 
    
         
             
                  # @safety
         
     | 
| 
       11 
14 
     | 
    
         
             
                  #   This cop is unsafe, because if the operand variable is a string object
         
     | 
| 
       12 
     | 
    
         
            -
                  #   then  
     | 
| 
      
 15 
     | 
    
         
            +
                  #   then `#to_f` will be removed and an error will occur.
         
     | 
| 
       13 
16 
     | 
    
         
             
                  #
         
     | 
| 
       14 
17 
     | 
    
         
             
                  #   [source,ruby]
         
     | 
| 
       15 
18 
     | 
    
         
             
                  #   ----
         
     | 
| 
         @@ -84,6 +87,14 @@ module RuboCop 
     | 
|
| 
       84 
87 
     | 
    
         
             
                      (send !nil? :to_f)
         
     | 
| 
       85 
88 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       86 
89 
     | 
    
         | 
| 
      
 90 
     | 
    
         
            +
                    # @!method regexp_last_match?(node)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    def_node_matcher :regexp_last_match?, <<~PATTERN
         
     | 
| 
      
 92 
     | 
    
         
            +
                      {
         
     | 
| 
      
 93 
     | 
    
         
            +
                        (send (const {nil? cbase} :Regexp) :last_match int)
         
     | 
| 
      
 94 
     | 
    
         
            +
                        (:nth_ref _)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      }
         
     | 
| 
      
 96 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
       87 
98 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       88 
99 
     | 
    
         
             
                      return unless offense_condition?(node)
         
     | 
| 
       89 
100 
     | 
    
         | 
| 
         @@ -104,6 +115,9 @@ module RuboCop 
     | 
|
| 
       104 
115 
     | 
    
         
             
                    private
         
     | 
| 
       105 
116 
     | 
    
         | 
| 
       106 
117 
     | 
    
         
             
                    def offense_condition?(node)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      return false if regexp_last_match?(node.receiver.receiver) ||
         
     | 
| 
      
 119 
     | 
    
         
            +
                                      regexp_last_match?(node.first_argument.receiver)
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
       107 
121 
     | 
    
         
             
                      case style
         
     | 
| 
       108 
122 
     | 
    
         
             
                      when :left_coerce
         
     | 
| 
       109 
123 
     | 
    
         
             
                        right_coerce?(node)
         
     | 
| 
         @@ -43,24 +43,26 @@ module RuboCop 
     | 
|
| 
       43 
43 
     | 
    
         
             
                    # @!method nil_check?(node)
         
     | 
| 
       44 
44 
     | 
    
         
             
                    def_node_matcher :nil_check?, '(send _ :nil?)'
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize
         
     | 
| 
       46 
47 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       47 
48 
     | 
    
         
             
                      return unless node.receiver
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
50 
     | 
    
         
             
                      style_check?(node) do
         
     | 
| 
       50 
51 
     | 
    
         
             
                        add_offense(node.loc.selector) do |corrector|
         
     | 
| 
       51 
     | 
    
         
            -
                           
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                           
     | 
| 
      
 52 
     | 
    
         
            +
                          if prefer_comparison?
         
     | 
| 
      
 53 
     | 
    
         
            +
                            range = node.loc.dot.join(node.loc.selector.end)
         
     | 
| 
      
 54 
     | 
    
         
            +
                            corrector.replace(range, ' == nil')
         
     | 
| 
      
 55 
     | 
    
         
            +
                          else
         
     | 
| 
      
 56 
     | 
    
         
            +
                            range = node.receiver.source_range.end.join(node.source_range.end)
         
     | 
| 
      
 57 
     | 
    
         
            +
                            corrector.replace(range, '.nil?')
         
     | 
| 
      
 58 
     | 
    
         
            +
                          end
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
                          parent = node.parent
         
     | 
| 
       60 
61 
     | 
    
         
             
                          corrector.wrap(node, '(', ')') if parent.respond_to?(:method?) && parent.method?(:!)
         
     | 
| 
       61 
62 
     | 
    
         
             
                        end
         
     | 
| 
       62 
63 
     | 
    
         
             
                      end
         
     | 
| 
       63 
64 
     | 
    
         
             
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    # rubocop:enable Metrics/AbcSize
         
     | 
| 
       64 
66 
     | 
    
         | 
| 
       65 
67 
     | 
    
         
             
                    private
         
     | 
| 
       66 
68 
     | 
    
         | 
| 
         @@ -55,19 +55,21 @@ module RuboCop 
     | 
|
| 
       55 
55 
     | 
    
         
             
                    include OnNormalIfUnless
         
     | 
| 
       56 
56 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                    MSG_SUFFIX = 'over single-line `%<keyword>s/then/else/end` constructs.'
         
     | 
| 
      
 59 
     | 
    
         
            +
                    MSG_TERNARY = "Favor the ternary operator (`?:`) #{MSG_SUFFIX}"
         
     | 
| 
      
 60 
     | 
    
         
            +
                    MSG_MULTILINE = "Favor multi-line `%<keyword>s` #{MSG_SUFFIX}"
         
     | 
| 
       60 
61 
     | 
    
         | 
| 
       61 
62 
     | 
    
         
             
                    def on_normal_if_unless(node)
         
     | 
| 
       62 
63 
     | 
    
         
             
                      return unless node.single_line?
         
     | 
| 
       63 
64 
     | 
    
         
             
                      return unless node.else_branch
         
     | 
| 
       64 
65 
     | 
    
         
             
                      return if node.elsif? || node.if_branch&.begin_type?
         
     | 
| 
       65 
66 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                       
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
      
 67 
     | 
    
         
            +
                      multiline = multiline?(node)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                      add_offense(node, message: message(node, multiline)) do |corrector|
         
     | 
| 
       68 
70 
     | 
    
         
             
                        next if part_of_ignored_node?(node)
         
     | 
| 
       69 
71 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
                        autocorrect(corrector, node)
         
     | 
| 
      
 72 
     | 
    
         
            +
                        autocorrect(corrector, node, multiline)
         
     | 
| 
       71 
73 
     | 
    
         | 
| 
       72 
74 
     | 
    
         
             
                        ignore_node(node)
         
     | 
| 
       73 
75 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -75,12 +77,18 @@ module RuboCop 
     | 
|
| 
       75 
77 
     | 
    
         | 
| 
       76 
78 
     | 
    
         
             
                    private
         
     | 
| 
       77 
79 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                    def  
     | 
| 
       79 
     | 
    
         
            -
                       
     | 
| 
      
 80 
     | 
    
         
            +
                    def multiline?(node)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      always_multiline? || cannot_replace_to_ternary?(node)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    def message(node, multiline)
         
     | 
| 
      
 85 
     | 
    
         
            +
                      template = multiline ? MSG_MULTILINE : MSG_TERNARY
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                      format(template, keyword: node.keyword)
         
     | 
| 
       80 
88 
     | 
    
         
             
                    end
         
     | 
| 
       81 
89 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                    def autocorrect(corrector, node)
         
     | 
| 
       83 
     | 
    
         
            -
                      if  
     | 
| 
      
 90 
     | 
    
         
            +
                    def autocorrect(corrector, node, multiline)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      if multiline
         
     | 
| 
       84 
92 
     | 
    
         
             
                        IfThenCorrector.new(node, indentation: configured_indentation_width).call(corrector)
         
     | 
| 
       85 
93 
     | 
    
         
             
                      else
         
     | 
| 
       86 
94 
     | 
    
         
             
                        corrector.replace(node, ternary_correction(node))
         
     | 
| 
         @@ -89,7 +89,7 @@ module RuboCop 
     | 
|
| 
       89 
89 
     | 
    
         | 
| 
       90 
90 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       91 
91 
     | 
    
         
             
                      format_without_additional_args?(node) do |value|
         
     | 
| 
       92 
     | 
    
         
            -
                        replacement = value.source
         
     | 
| 
      
 92 
     | 
    
         
            +
                        replacement = escape_control_chars(value.source)
         
     | 
| 
       93 
93 
     | 
    
         | 
| 
       94 
94 
     | 
    
         
             
                        add_offense(node, message: message(node, replacement)) do |corrector|
         
     | 
| 
       95 
95 
     | 
    
         
             
                          corrector.replace(node, replacement)
         
     | 
| 
         @@ -134,6 +134,7 @@ module RuboCop 
     | 
|
| 
       134 
134 
     | 
    
         
             
                      end
         
     | 
| 
       135 
135 
     | 
    
         
             
                    end
         
     | 
| 
       136 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         
     | 
| 
       137 
138 
     | 
    
         
             
                    def all_fields_literal?(string, arguments)
         
     | 
| 
       138 
139 
     | 
    
         
             
                      count = 0
         
     | 
| 
       139 
140 
     | 
    
         
             
                      sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
         
     | 
| 
         @@ -141,29 +142,44 @@ module RuboCop 
     | 
|
| 
       141 
142 
     | 
    
         | 
| 
       142 
143 
     | 
    
         
             
                      sequences.each do |sequence|
         
     | 
| 
       143 
144 
     | 
    
         
             
                        next if sequence.percent?
         
     | 
| 
      
 145 
     | 
    
         
            +
                        next if unknown_variable_width?(sequence, arguments)
         
     | 
| 
       144 
146 
     | 
    
         | 
| 
       145 
147 
     | 
    
         
             
                        hash = arguments.detect(&:hash_type?)
         
     | 
| 
       146 
148 
     | 
    
         
             
                        next unless (argument = find_argument(sequence, arguments, hash))
         
     | 
| 
       147 
149 
     | 
    
         
             
                        next unless matching_argument?(sequence, argument)
         
     | 
| 
      
 150 
     | 
    
         
            +
                        next if (sequence.width || sequence.precision) && argument.dstr_type?
         
     | 
| 
       148 
151 
     | 
    
         | 
| 
       149 
152 
     | 
    
         
             
                        count += 1
         
     | 
| 
       150 
153 
     | 
    
         
             
                      end
         
     | 
| 
       151 
154 
     | 
    
         | 
| 
       152 
155 
     | 
    
         
             
                      sequences.size == count
         
     | 
| 
       153 
156 
     | 
    
         
             
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         
     | 
| 
       154 
158 
     | 
    
         | 
| 
      
 159 
     | 
    
         
            +
                    # If the sequence has a variable (`*`) width, it cannot be autocorrected
         
     | 
| 
      
 160 
     | 
    
         
            +
                    # if the width is not given as a numeric literal argument
         
     | 
| 
      
 161 
     | 
    
         
            +
                    def unknown_variable_width?(sequence, arguments)
         
     | 
| 
      
 162 
     | 
    
         
            +
                      return false unless sequence.variable_width?
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                      argument = arguments[sequence.variable_width_argument_number - 1]
         
     | 
| 
      
 165 
     | 
    
         
            +
                      !numeric?(argument)
         
     | 
| 
      
 166 
     | 
    
         
            +
                    end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize
         
     | 
| 
       155 
169 
     | 
    
         
             
                    def find_argument(sequence, arguments, hash)
         
     | 
| 
       156 
170 
     | 
    
         
             
                      if hash && (sequence.annotated? || sequence.template?)
         
     | 
| 
       157 
171 
     | 
    
         
             
                        find_hash_value_node(hash, sequence.name.to_sym).first
         
     | 
| 
      
 172 
     | 
    
         
            +
                      elsif sequence.variable_width?
         
     | 
| 
      
 173 
     | 
    
         
            +
                        # If the specifier contains `*`, the argument for the width can be ignored.
         
     | 
| 
      
 174 
     | 
    
         
            +
                        arguments.delete_at(sequence.variable_width_argument_number - 1)
         
     | 
| 
      
 175 
     | 
    
         
            +
                        arguments.shift
         
     | 
| 
       158 
176 
     | 
    
         
             
                      elsif sequence.arg_number
         
     | 
| 
       159 
177 
     | 
    
         
             
                        arguments[sequence.arg_number.to_i - 1]
         
     | 
| 
       160 
178 
     | 
    
         
             
                      else
         
     | 
| 
       161 
     | 
    
         
            -
                        # If the specifier contains `*`, the following arguments will be used
         
     | 
| 
       162 
     | 
    
         
            -
                        # to specify the width and can be ignored.
         
     | 
| 
       163 
     | 
    
         
            -
                        (sequence.arity - 1).times { arguments.shift }
         
     | 
| 
       164 
179 
     | 
    
         
             
                        arguments.shift
         
     | 
| 
       165 
180 
     | 
    
         
             
                      end
         
     | 
| 
       166 
181 
     | 
    
         
             
                    end
         
     | 
| 
      
 182 
     | 
    
         
            +
                    # rubocop:enable Metrics/AbcSize
         
     | 
| 
       167 
183 
     | 
    
         | 
| 
       168 
184 
     | 
    
         
             
                    def matching_argument?(sequence, argument)
         
     | 
| 
       169 
185 
     | 
    
         
             
                      # Template specifiers don't give a type, any acceptable literal type is ok.
         
     | 
| 
         @@ -214,7 +230,12 @@ module RuboCop 
     | 
|
| 
       214 
230 
     | 
    
         
             
                        end
         
     | 
| 
       215 
231 
     | 
    
         
             
                      end
         
     | 
| 
       216 
232 
     | 
    
         | 
| 
       217 
     | 
    
         
            -
                      "#{start_delimiter}#{string}#{end_delimiter}"
         
     | 
| 
      
 233 
     | 
    
         
            +
                      "#{start_delimiter}#{escape_control_chars(string)}#{end_delimiter}"
         
     | 
| 
      
 234 
     | 
    
         
            +
                    end
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
                    # Escape any control characters in the string (eg. `\t` or `\n` become `\\t` or `\\n`)
         
     | 
| 
      
 237 
     | 
    
         
            +
                    def escape_control_chars(string)
         
     | 
| 
      
 238 
     | 
    
         
            +
                      string.gsub(/\p{Cc}/) { |s| s.dump[1..-2] }
         
     | 
| 
       218 
239 
     | 
    
         
             
                    end
         
     | 
| 
       219 
240 
     | 
    
         | 
| 
       220 
241 
     | 
    
         
             
                    def argument_values(arguments)
         
     | 
| 
         @@ -49,9 +49,10 @@ module RuboCop 
     | 
|
| 
       49 
49 
     | 
    
         
             
                    def on_dstr(node)
         
     | 
| 
       50 
50 
     | 
    
         
             
                      return unless single_interpolation?(node)
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                       
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
      
 52 
     | 
    
         
            +
                      embedded_node = node.children.first
         
     | 
| 
      
 53 
     | 
    
         
            +
                      return if use_match_pattern?(embedded_node)
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
      
 55 
     | 
    
         
            +
                      add_offense(node) do |corrector|
         
     | 
| 
       55 
56 
     | 
    
         
             
                        if variable_interpolation?(embedded_node)
         
     | 
| 
       56 
57 
     | 
    
         
             
                          autocorrect_variable_interpolation(corrector, embedded_node, node)
         
     | 
| 
       57 
58 
     | 
    
         
             
                        elsif single_variable_interpolation?(embedded_node)
         
     | 
| 
         @@ -71,6 +72,14 @@ module RuboCop 
     | 
|
| 
       71 
72 
     | 
    
         
             
                        !embedded_in_percent_array?(node)
         
     | 
| 
       72 
73 
     | 
    
         
             
                    end
         
     | 
| 
       73 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
                    def use_match_pattern?(node)
         
     | 
| 
      
 76 
     | 
    
         
            +
                      return false if target_ruby_version <= 2.7
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                      node.children.any? do |child|
         
     | 
| 
      
 79 
     | 
    
         
            +
                        child.respond_to?(:match_pattern_type?) && child.match_pattern_type?
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
                    end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
       74 
83 
     | 
    
         
             
                    def single_variable_interpolation?(node)
         
     | 
| 
       75 
84 
     | 
    
         
             
                      return false unless node.children.one?
         
     | 
| 
       76 
85 
     | 
    
         | 
| 
         @@ -202,6 +202,7 @@ module RuboCop 
     | 
|
| 
       202 
202 
     | 
    
         
             
                      return false unless node.rescue_type?
         
     | 
| 
       203 
203 
     | 
    
         
             
                      return false unless (parent = begin_node.parent)
         
     | 
| 
       204 
204 
     | 
    
         
             
                      return false if parent.if_type? && parent.ternary?
         
     | 
| 
      
 205 
     | 
    
         
            +
                      return false if parent.conditional? && parent.condition == begin_node
         
     | 
| 
       205 
206 
     | 
    
         | 
| 
       206 
207 
     | 
    
         
             
                      !parent.type?(:call, :array, :pair)
         
     | 
| 
       207 
208 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -66,6 +66,7 @@ module RuboCop 
     | 
|
| 
       66 
66 
     | 
    
         
             
                      DETERMINISTIC_REGEX.match?(regexp_node.source)
         
     | 
| 
       67 
67 
     | 
    
         
             
                    end
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
      
 69 
     | 
    
         
            +
                    # rubocop:disable Metrics/MethodLength
         
     | 
| 
       69 
70 
     | 
    
         
             
                    def preferred_argument(regexp_node)
         
     | 
| 
       70 
71 
     | 
    
         
             
                      new_argument = replacement(regexp_node)
         
     | 
| 
       71 
72 
     | 
    
         | 
| 
         @@ -73,6 +74,8 @@ module RuboCop 
     | 
|
| 
       73 
74 
     | 
    
         
             
                        new_argument.gsub!("'", "\\\\'")
         
     | 
| 
       74 
75 
     | 
    
         
             
                        new_argument.gsub!('\"', '"')
         
     | 
| 
       75 
76 
     | 
    
         
             
                        quote = "'"
         
     | 
| 
      
 77 
     | 
    
         
            +
                      elsif new_argument.include?("\\'")
         
     | 
| 
      
 78 
     | 
    
         
            +
                        quote = "'"
         
     | 
| 
       76 
79 
     | 
    
         
             
                      elsif new_argument.include?('\'')
         
     | 
| 
       77 
80 
     | 
    
         
             
                        new_argument.gsub!("'", "\\\\'")
         
     | 
| 
       78 
81 
     | 
    
         
             
                        quote = "'"
         
     | 
| 
         @@ -84,6 +87,7 @@ module RuboCop 
     | 
|
| 
       84 
87 
     | 
    
         | 
| 
       85 
88 
     | 
    
         
             
                      "#{quote}#{new_argument}#{quote}"
         
     | 
| 
       86 
89 
     | 
    
         
             
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    # rubocop:enable Metrics/MethodLength
         
     | 
| 
       87 
91 
     | 
    
         | 
| 
       88 
92 
     | 
    
         
             
                    def replacement(regexp_node)
         
     | 
| 
       89 
93 
     | 
    
         
             
                      regexp_content = regexp_node.content
         
     |