rubocop 1.35.1 → 1.37.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/README.md +1 -1
- data/config/default.yml +32 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +14 -12
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -2
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -2
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +46 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +17 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +2 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +10 -5
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +13 -5
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -5
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/case_equality.rb +40 -10
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +40 -5
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +6 -5
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -2
- data/lib/rubocop.rb +3 -0
- metadata +10 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e928a8547def9cafd9cddc36b5a407aef7d46fdf9825941c7906073492d88668
         | 
| 4 | 
            +
              data.tar.gz: 3ef9727850f93815ba310b7c3a8cf74e53a0ee18a0fcf6731fd97a3640ffe28d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f57e5d25375fe47734a6e198924db74b341501762dc8f54277a888788ab821215c96847940cec1af4d90673fe79ab906b451bf25bec90f9c8c080e78efc01111
         | 
| 7 | 
            +
              data.tar.gz: 69cafbca956eaa49887596d255f6888057ede94f3621349398de95da5c477201f7bee7eae074ab4750ce0131dcb26d6dfdc77c31f5fcb478d2fc25d5ca73e68c
         | 
    
        data/README.md
    CHANGED
    
    | @@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi | |
| 53 53 | 
             
            in your `Gemfile`:
         | 
| 54 54 |  | 
| 55 55 | 
             
            ```rb
         | 
| 56 | 
            -
            gem 'rubocop', '~> 1. | 
| 56 | 
            +
            gem 'rubocop', '~> 1.37', require: false
         | 
| 57 57 | 
             
            ```
         | 
| 58 58 |  | 
| 59 59 | 
             
            See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
         | 
    
        data/config/default.yml
    CHANGED
    
    | @@ -1707,6 +1707,11 @@ Lint/DuplicateHashKey: | |
| 1707 1707 | 
             
              VersionAdded: '0.34'
         | 
| 1708 1708 | 
             
              VersionChanged: '0.77'
         | 
| 1709 1709 |  | 
| 1710 | 
            +
            Lint/DuplicateMagicComment:
         | 
| 1711 | 
            +
              Description: 'Check for duplicated magic comments.'
         | 
| 1712 | 
            +
              Enabled: pending
         | 
| 1713 | 
            +
              VersionAdded: '1.37'
         | 
| 1714 | 
            +
             | 
| 1710 1715 | 
             
            Lint/DuplicateMethods:
         | 
| 1711 1716 | 
             
              Description: 'Check for duplicate method definitions.'
         | 
| 1712 1717 | 
             
              Enabled: true
         | 
| @@ -1957,6 +1962,8 @@ Lint/NestedMethodDefinition: | |
| 1957 1962 | 
             
              Description: 'Do not use nested method definitions.'
         | 
| 1958 1963 | 
             
              StyleGuide: '#no-nested-methods'
         | 
| 1959 1964 | 
             
              Enabled: true
         | 
| 1965 | 
            +
              AllowedMethods: []
         | 
| 1966 | 
            +
              AllowedPatterns: []
         | 
| 1960 1967 | 
             
              VersionAdded: '0.32'
         | 
| 1961 1968 |  | 
| 1962 1969 | 
             
            Lint/NestedPercentLiteral:
         | 
| @@ -2021,7 +2028,9 @@ Lint/OrAssignmentToConstant: | |
| 2021 2028 | 
             
            Lint/OrderedMagicComments:
         | 
| 2022 2029 | 
             
              Description: 'Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.'
         | 
| 2023 2030 | 
             
              Enabled: true
         | 
| 2031 | 
            +
              SafeAutoCorrect: false
         | 
| 2024 2032 | 
             
              VersionAdded: '0.53'
         | 
| 2033 | 
            +
              VersionChanged: '1.37'
         | 
| 2025 2034 |  | 
| 2026 2035 | 
             
            Lint/OutOfRangeRegexpRef:
         | 
| 2027 2036 | 
             
              Description: 'Checks for out of range reference for Regexp because it always returns nil.'
         | 
| @@ -2794,6 +2803,7 @@ Naming/MethodParameterName: | |
| 2794 2803 | 
             
              AllowNamesEndingInNumbers: true
         | 
| 2795 2804 | 
             
              # Allowed names that will not register an offense
         | 
| 2796 2805 | 
             
              AllowedNames:
         | 
| 2806 | 
            +
                - as
         | 
| 2797 2807 | 
             
                - at
         | 
| 2798 2808 | 
             
                - by
         | 
| 2799 2809 | 
             
                - db
         | 
| @@ -2948,6 +2958,7 @@ Style/AccessModifierDeclarations: | |
| 2948 2958 | 
             
                - inline
         | 
| 2949 2959 | 
             
                - group
         | 
| 2950 2960 | 
             
              AllowModifiersOnSymbols: true
         | 
| 2961 | 
            +
              SafeAutoCorrect: false
         | 
| 2951 2962 |  | 
| 2952 2963 | 
             
            Style/AccessorGrouping:
         | 
| 2953 2964 | 
             
              Description: 'Checks for grouping of accessors in `class` and `module` bodies.'
         | 
| @@ -3186,6 +3197,15 @@ Style/CaseEquality: | |
| 3186 3197 | 
             
              #   # good
         | 
| 3187 3198 | 
             
              #   String === "string"
         | 
| 3188 3199 | 
             
              AllowOnConstant: false
         | 
| 3200 | 
            +
              # If `AllowOnSelfClass` option is enabled, the cop will ignore violations when the receiver of
         | 
| 3201 | 
            +
              # the case equality operator is `self.class`.
         | 
| 3202 | 
            +
              #
         | 
| 3203 | 
            +
              #   # bad
         | 
| 3204 | 
            +
              #   some_class === object
         | 
| 3205 | 
            +
              #
         | 
| 3206 | 
            +
              #   # good
         | 
| 3207 | 
            +
              #   self.class === object
         | 
| 3208 | 
            +
              AllowOnSelfClass: false
         | 
| 3189 3209 |  | 
| 3190 3210 | 
             
            Style/CaseLikeIf:
         | 
| 3191 3211 | 
             
              Description: 'Identifies places where `if-elsif` constructions can be replaced with `case-when`.'
         | 
| @@ -3839,7 +3859,7 @@ Style/HashSyntax: | |
| 3839 3859 | 
             
                - never
         | 
| 3840 3860 | 
             
                # accepts both shorthand and explicit use of hash literal value.
         | 
| 3841 3861 | 
             
                - either
         | 
| 3842 | 
            -
                # like " | 
| 3862 | 
            +
                # like "either", but will avoid mixing styles in a single hash
         | 
| 3843 3863 | 
             
                - consistent
         | 
| 3844 3864 | 
             
              # Force hashes that have a symbol value to use hash rockets
         | 
| 3845 3865 | 
             
              UseHashRocketsWithSymbolValues: false
         | 
| @@ -4487,6 +4507,12 @@ Style/OpenStructUse: | |
| 4487 4507 | 
             
              Enabled: pending
         | 
| 4488 4508 | 
             
              VersionAdded: '1.23'
         | 
| 4489 4509 |  | 
| 4510 | 
            +
            Style/OperatorMethodCall:
         | 
| 4511 | 
            +
              Description: 'Checks for redundant dot before operator method call.'
         | 
| 4512 | 
            +
              StyleGuide: '#operator-method-call'
         | 
| 4513 | 
            +
              Enabled: pending
         | 
| 4514 | 
            +
              VersionAdded: '1.37'
         | 
| 4515 | 
            +
             | 
| 4490 4516 | 
             
            Style/OptionHash:
         | 
| 4491 4517 | 
             
              Description: "Don't use option hashes when you can use keyword arguments."
         | 
| 4492 4518 | 
             
              Enabled: false
         | 
| @@ -4781,6 +4807,11 @@ Style/RedundantSortBy: | |
| 4781 4807 | 
             
              Enabled: true
         | 
| 4782 4808 | 
             
              VersionAdded: '0.36'
         | 
| 4783 4809 |  | 
| 4810 | 
            +
            Style/RedundantStringEscape:
         | 
| 4811 | 
            +
              Description: 'Checks for redundant escapes in string literals.'
         | 
| 4812 | 
            +
              Enabled: pending
         | 
| 4813 | 
            +
              VersionAdded: '1.37'
         | 
| 4814 | 
            +
             | 
| 4784 4815 | 
             
            Style/RegexpLiteral:
         | 
| 4785 4816 | 
             
              Description: 'Use / or %r around regular expressions.'
         | 
| 4786 4817 | 
             
              StyleGuide: '#percent-r'
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module RuboCop
         | 
| 4 | 
            +
              # This is a class that reads optional command line arguments to rubocop from environment variable.
         | 
| 5 | 
            +
              # @api private
         | 
| 6 | 
            +
              class ArgumentsEnv
         | 
| 7 | 
            +
                def self.read_as_arguments
         | 
| 8 | 
            +
                  if (arguments = ENV.fetch('RUBOCOP_OPTS', '')).empty?
         | 
| 9 | 
            +
                    []
         | 
| 10 | 
            +
                  else
         | 
| 11 | 
            +
                    require 'shellwords'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    Shellwords.split(arguments)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module RuboCop
         | 
| 4 | 
            +
              # This is a class that reads optional command line arguments to rubocop from .rubocop file.
         | 
| 5 | 
            +
              # @api private
         | 
| 6 | 
            +
              class ArgumentsFile
         | 
| 7 | 
            +
                def self.read_as_arguments
         | 
| 8 | 
            +
                  if File.exist?('.rubocop') && !File.directory?('.rubocop')
         | 
| 9 | 
            +
                    require 'shellwords'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    File.read('.rubocop').shellsplit
         | 
| 12 | 
            +
                  else
         | 
| 13 | 
            +
                    []
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -41,13 +41,13 @@ module RuboCop | |
| 41 41 |  | 
| 42 42 | 
             
                    def with_redirect
         | 
| 43 43 | 
             
                      if @options[:stderr]
         | 
| 44 | 
            -
                        orig_stdout = $stdout | 
| 45 | 
            -
                         | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                         | 
| 44 | 
            +
                        orig_stdout = $stdout
         | 
| 45 | 
            +
                        begin
         | 
| 46 | 
            +
                          $stdout = $stderr
         | 
| 47 | 
            +
                          yield
         | 
| 48 | 
            +
                        ensure
         | 
| 49 | 
            +
                          $stdout = orig_stdout
         | 
| 50 | 
            +
                        end
         | 
| 51 51 | 
             
                      else
         | 
| 52 52 | 
             
                        yield
         | 
| 53 53 | 
             
                      end
         | 
| @@ -206,9 +206,8 @@ module RuboCop | |
| 206 206 | 
             
                  end
         | 
| 207 207 |  | 
| 208 208 | 
             
                  def snake_case(camel_case_string)
         | 
| 209 | 
            -
                    return 'rspec' if camel_case_string == 'RSpec'
         | 
| 210 | 
            -
             | 
| 211 209 | 
             
                    camel_case_string
         | 
| 210 | 
            +
                      .gsub('RSpec', 'Rspec')
         | 
| 212 211 | 
             
                      .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
         | 
| 213 212 | 
             
                      .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
         | 
| 214 213 | 
             
                      .downcase
         | 
| @@ -22,23 +22,24 @@ module RuboCop | |
| 22 22 | 
             
                  #   # bad
         | 
| 23 23 | 
             
                  #
         | 
| 24 24 | 
             
                  #   foo.bar
         | 
| 25 | 
            -
                  # | 
| 26 | 
            -
                  # | 
| 27 | 
            -
                  # | 
| 25 | 
            +
                  #     .each do
         | 
| 26 | 
            +
                  #       baz
         | 
| 27 | 
            +
                  #         end
         | 
| 28 28 | 
             
                  #
         | 
| 29 29 | 
             
                  #   # good
         | 
| 30 30 | 
             
                  #
         | 
| 31 | 
            -
                  #    | 
| 32 | 
            -
                  #      | 
| 31 | 
            +
                  #   foo.bar
         | 
| 32 | 
            +
                  #     .each do
         | 
| 33 | 
            +
                  #       baz
         | 
| 33 34 | 
             
                  #   end
         | 
| 34 35 | 
             
                  #
         | 
| 35 36 | 
             
                  # @example EnforcedStyleAlignWith: start_of_block
         | 
| 36 37 | 
             
                  #   # bad
         | 
| 37 38 | 
             
                  #
         | 
| 38 39 | 
             
                  #   foo.bar
         | 
| 39 | 
            -
                  # | 
| 40 | 
            -
                  # | 
| 41 | 
            -
                  # | 
| 40 | 
            +
                  #     .each do
         | 
| 41 | 
            +
                  #       baz
         | 
| 42 | 
            +
                  #         end
         | 
| 42 43 | 
             
                  #
         | 
| 43 44 | 
             
                  #   # good
         | 
| 44 45 | 
             
                  #
         | 
| @@ -51,16 +52,17 @@ module RuboCop | |
| 51 52 | 
             
                  #   # bad
         | 
| 52 53 | 
             
                  #
         | 
| 53 54 | 
             
                  #   foo.bar
         | 
| 54 | 
            -
                  # | 
| 55 | 
            -
                  # | 
| 56 | 
            -
                  # | 
| 55 | 
            +
                  #     .each do
         | 
| 56 | 
            +
                  #       baz
         | 
| 57 | 
            +
                  #         end
         | 
| 57 58 | 
             
                  #
         | 
| 58 59 | 
             
                  #   # good
         | 
| 59 60 | 
             
                  #
         | 
| 60 61 | 
             
                  #   foo.bar
         | 
| 61 62 | 
             
                  #     .each do
         | 
| 62 | 
            -
                  # | 
| 63 | 
            +
                  #       baz
         | 
| 63 64 | 
             
                  #   end
         | 
| 65 | 
            +
                  #
         | 
| 64 66 | 
             
                  class BlockAlignment < Base
         | 
| 65 67 | 
             
                    include ConfigurableEnforcedStyle
         | 
| 66 68 | 
             
                    include RangeHelp
         | 
| @@ -148,7 +148,9 @@ module RuboCop | |
| 148 148 | 
             
                        check_indentation(in_pattern_node.loc.keyword, in_pattern_node.body)
         | 
| 149 149 | 
             
                      end
         | 
| 150 150 |  | 
| 151 | 
            -
                       | 
| 151 | 
            +
                      else_branch = case_match.else_branch&.empty_else_type? ? nil : case_match.else_branch
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                      check_indentation(case_match.in_pattern_branches.last.loc.keyword, else_branch)
         | 
| 152 154 | 
             
                    end
         | 
| 153 155 |  | 
| 154 156 | 
             
                    def on_if(node, base = node)
         | 
| @@ -341,7 +343,7 @@ module RuboCop | |
| 341 343 | 
             
                    end
         | 
| 342 344 |  | 
| 343 345 | 
             
                    def skip_check?(base_loc, body_node)
         | 
| 344 | 
            -
                      return true if  | 
| 346 | 
            +
                      return true if allowed_line?(base_loc)
         | 
| 345 347 | 
             
                      return true unless body_node
         | 
| 346 348 |  | 
| 347 349 | 
             
                      # Don't check if expression is on same line as "then" keyword, etc.
         | 
| @@ -169,19 +169,22 @@ module RuboCop | |
| 169 169 |  | 
| 170 170 | 
             
                    def qualifies_for_compact?(node, token, side: :right)
         | 
| 171 171 | 
             
                      if side == :right
         | 
| 172 | 
            -
                        multi_dimensional_array?(node, token) &&  | 
| 172 | 
            +
                        multi_dimensional_array?(node, token) && token.space_before?
         | 
| 173 173 | 
             
                      else
         | 
| 174 | 
            -
                        multi_dimensional_array?(node, token, side: :left) &&
         | 
| 175 | 
            -
                          !next_to_bracket?(token, side: :left)
         | 
| 174 | 
            +
                        multi_dimensional_array?(node, token, side: :left) && token.space_after?
         | 
| 176 175 | 
             
                      end
         | 
| 177 176 | 
             
                    end
         | 
| 178 177 |  | 
| 179 178 | 
             
                    def multi_dimensional_array?(node, token, side: :right)
         | 
| 180 | 
            -
                       | 
| 179 | 
            +
                      offset = side == :right ? -1 : +1
         | 
| 180 | 
            +
                      i = index_for(node, token) + offset
         | 
| 181 | 
            +
                      # TODO: change this type check once
         | 
| 182 | 
            +
                      # https://github.com/rubocop/rubocop-ast/pull/240 is merged
         | 
| 183 | 
            +
                      i += offset while processed_source.tokens_within(node)[i].new_line?
         | 
| 181 184 | 
             
                      if side == :right
         | 
| 182 | 
            -
                        processed_source.tokens_within(node)[i | 
| 185 | 
            +
                        processed_source.tokens_within(node)[i].right_bracket?
         | 
| 183 186 | 
             
                      else
         | 
| 184 | 
            -
                        processed_source.tokens_within(node)[i | 
| 187 | 
            +
                        processed_source.tokens_within(node)[i].left_array_bracket?
         | 
| 185 188 | 
             
                      end
         | 
| 186 189 | 
             
                    end
         | 
| 187 190 |  | 
| @@ -200,12 +203,13 @@ module RuboCop | |
| 200 203 | 
             
                    end
         | 
| 201 204 |  | 
| 202 205 | 
             
                    def compact_corrections(corrector, node, left, right)
         | 
| 203 | 
            -
                      if  | 
| 206 | 
            +
                      if multi_dimensional_array?(node, left, side: :left)
         | 
| 204 207 | 
             
                        compact(corrector, left, :right)
         | 
| 205 208 | 
             
                      elsif !left.space_after?
         | 
| 206 209 | 
             
                        corrector.insert_after(left.pos, ' ')
         | 
| 207 210 | 
             
                      end
         | 
| 208 | 
            -
             | 
| 211 | 
            +
             | 
| 212 | 
            +
                      if multi_dimensional_array?(node, right)
         | 
| 209 213 | 
             
                        compact(corrector, right, :left)
         | 
| 210 214 | 
             
                      elsif !right.space_before?
         | 
| 211 215 | 
             
                        corrector.insert_before(right.pos, ' ')
         | 
| @@ -213,7 +217,7 @@ module RuboCop | |
| 213 217 | 
             
                    end
         | 
| 214 218 |  | 
| 215 219 | 
             
                    def compact(corrector, bracket, side)
         | 
| 216 | 
            -
                      range = side_space_range(range: bracket.pos, side: side)
         | 
| 220 | 
            +
                      range = side_space_range(range: bracket.pos, side: side, include_newlines: true)
         | 
| 217 221 | 
             
                      corrector.remove(range)
         | 
| 218 222 | 
             
                    end
         | 
| 219 223 | 
             
                  end
         | 
| @@ -131,7 +131,7 @@ module RuboCop | |
| 131 131 | 
             
                      args_delimiter = node.arguments.loc.begin if node.block_type? # Can be ( | or nil.
         | 
| 132 132 |  | 
| 133 133 | 
             
                      check_left_brace(inner, node.loc.begin, args_delimiter)
         | 
| 134 | 
            -
                      check_right_brace(inner, node.loc.begin, node.loc.end, node.single_line?)
         | 
| 134 | 
            +
                      check_right_brace(node, inner, node.loc.begin, node.loc.end, node.single_line?)
         | 
| 135 135 | 
             
                    end
         | 
| 136 136 |  | 
| 137 137 | 
             
                    def check_left_brace(inner, left_brace, args_delimiter)
         | 
| @@ -142,14 +142,15 @@ module RuboCop | |
| 142 142 | 
             
                      end
         | 
| 143 143 | 
             
                    end
         | 
| 144 144 |  | 
| 145 | 
            -
                    def check_right_brace(inner, left_brace, right_brace, single_line)
         | 
| 145 | 
            +
                    def check_right_brace(node, inner, left_brace, right_brace, single_line)
         | 
| 146 146 | 
             
                      if single_line && /\S$/.match?(inner)
         | 
| 147 147 | 
             
                        no_space(right_brace.begin_pos, right_brace.end_pos, 'Space missing inside }.')
         | 
| 148 148 | 
             
                      else
         | 
| 149 | 
            +
                        column = node.loc.expression.column
         | 
| 149 150 | 
             
                        return if multiline_block?(left_brace, right_brace) &&
         | 
| 150 | 
            -
                                  aligned_braces?( | 
| 151 | 
            +
                                  aligned_braces?(inner, right_brace, column)
         | 
| 151 152 |  | 
| 152 | 
            -
                        space_inside_right_brace(right_brace)
         | 
| 153 | 
            +
                        space_inside_right_brace(inner, right_brace, column)
         | 
| 153 154 | 
             
                      end
         | 
| 154 155 | 
             
                    end
         | 
| 155 156 |  | 
| @@ -157,8 +158,12 @@ module RuboCop | |
| 157 158 | 
             
                      left_brace.first_line != right_brace.first_line
         | 
| 158 159 | 
             
                    end
         | 
| 159 160 |  | 
| 160 | 
            -
                    def aligned_braces?( | 
| 161 | 
            -
                       | 
| 161 | 
            +
                    def aligned_braces?(inner, right_brace, column)
         | 
| 162 | 
            +
                      column == right_brace.column || column == inner_last_space_count(inner)
         | 
| 163 | 
            +
                    end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                    def inner_last_space_count(inner)
         | 
| 166 | 
            +
                      inner.split("\n").last.count(' ')
         | 
| 162 167 | 
             
                    end
         | 
| 163 168 |  | 
| 164 169 | 
             
                    def no_space_inside_left_brace(left_brace, args_delimiter)
         | 
| @@ -197,10 +202,21 @@ module RuboCop | |
| 197 202 | 
             
                      args_delimiter&.is?('|')
         | 
| 198 203 | 
             
                    end
         | 
| 199 204 |  | 
| 200 | 
            -
                    def space_inside_right_brace(right_brace)
         | 
| 205 | 
            +
                    def space_inside_right_brace(inner, right_brace, column)
         | 
| 201 206 | 
             
                      brace_with_space = range_with_surrounding_space(right_brace, side: :left)
         | 
| 202 | 
            -
                       | 
| 203 | 
            -
             | 
| 207 | 
            +
                      begin_pos = brace_with_space.begin_pos
         | 
| 208 | 
            +
                      end_pos = brace_with_space.end_pos - 1
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                      if brace_with_space.source.match?(/\R/)
         | 
| 211 | 
            +
                        begin_pos = end_pos - (right_brace.column - column)
         | 
| 212 | 
            +
                      end
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                      if inner.end_with?(']')
         | 
| 215 | 
            +
                        end_pos -= 1
         | 
| 216 | 
            +
                        begin_pos = end_pos - (inner_last_space_count(inner) - column)
         | 
| 217 | 
            +
                      end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                      space(begin_pos, end_pos, 'Space inside } detected.')
         | 
| 204 220 | 
             
                    end
         | 
| 205 221 |  | 
| 206 222 | 
             
                    def no_space(begin_pos, end_pos, msg)
         | 
| @@ -46,10 +46,13 @@ module RuboCop | |
| 46 46 | 
             
                  #   # bad
         | 
| 47 47 | 
             
                  #   foo = { }
         | 
| 48 48 | 
             
                  #   bar = {    }
         | 
| 49 | 
            +
                  #   baz = {
         | 
| 50 | 
            +
                  #   }
         | 
| 49 51 | 
             
                  #
         | 
| 50 52 | 
             
                  #   # good
         | 
| 51 53 | 
             
                  #   foo = {}
         | 
| 52 54 | 
             
                  #   bar = {}
         | 
| 55 | 
            +
                  #   baz = {}
         | 
| 53 56 | 
             
                  #
         | 
| 54 57 | 
             
                  # @example EnforcedStyleForEmptyBraces: space
         | 
| 55 58 | 
             
                  #   # The `space` EnforcedStyleForEmptyBraces style enforces that
         | 
| @@ -60,8 +63,9 @@ module RuboCop | |
| 60 63 | 
             
                  #
         | 
| 61 64 | 
             
                  #   # good
         | 
| 62 65 | 
             
                  #   foo = { }
         | 
| 63 | 
            -
                  #   foo = { | 
| 64 | 
            -
                  #   foo = { | 
| 66 | 
            +
                  #   foo = {    }
         | 
| 67 | 
            +
                  #   foo = {
         | 
| 68 | 
            +
                  #   }
         | 
| 65 69 | 
             
                  #
         | 
| 66 70 | 
             
                  class SpaceInsideHashLiteralBraces < Base
         | 
| 67 71 | 
             
                    include SurroundingSpace
         | 
| @@ -77,6 +81,7 @@ module RuboCop | |
| 77 81 |  | 
| 78 82 | 
             
                      check(tokens[0], tokens[1])
         | 
| 79 83 | 
             
                      check(tokens[-2], tokens[-1]) if tokens.size > 2
         | 
| 84 | 
            +
                      check_whitespace_only_hash(node) if enforce_no_space_style_for_empty_braces?
         | 
| 80 85 | 
             
                    end
         | 
| 81 86 |  | 
| 82 87 | 
             
                    private
         | 
| @@ -103,7 +108,7 @@ module RuboCop | |
| 103 108 | 
             
                      if is_same_braces && style == :compact
         | 
| 104 109 | 
             
                        false
         | 
| 105 110 | 
             
                      elsif is_empty_braces
         | 
| 106 | 
            -
                         | 
| 111 | 
            +
                        !enforce_no_space_style_for_empty_braces?
         | 
| 107 112 | 
             
                      else
         | 
| 108 113 | 
             
                        style != :no_space
         | 
| 109 114 | 
             
                      end
         | 
| @@ -175,6 +180,26 @@ module RuboCop | |
| 175 180 |  | 
| 176 181 | 
             
                      range_between(begin_pos, range.end_pos - 1)
         | 
| 177 182 | 
             
                    end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                    def check_whitespace_only_hash(node)
         | 
| 185 | 
            +
                      range = range_inside_hash(node)
         | 
| 186 | 
            +
                      return unless range.source.match?(/\A\s+\z/m)
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                      add_offense(
         | 
| 189 | 
            +
                        range,
         | 
| 190 | 
            +
                        message: format(MSG, problem: 'empty hash literal braces detected')
         | 
| 191 | 
            +
                      ) do |corrector|
         | 
| 192 | 
            +
                        corrector.remove(range)
         | 
| 193 | 
            +
                      end
         | 
| 194 | 
            +
                    end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    def range_inside_hash(node)
         | 
| 197 | 
            +
                      range_between(node.location.begin.end_pos, node.location.end.begin_pos)
         | 
| 198 | 
            +
                    end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                    def enforce_no_space_style_for_empty_braces?
         | 
| 201 | 
            +
                      cop_config['EnforcedStyleForEmptyBraces'] == 'no_space'
         | 
| 202 | 
            +
                    end
         | 
| 178 203 | 
             
                  end
         | 
| 179 204 | 
             
                end
         | 
| 180 205 | 
             
              end
         | 
| @@ -45,7 +45,7 @@ module RuboCop | |
| 45 45 | 
             
                  #   # bad
         | 
| 46 46 | 
             
                  #   expect { do_something }.to change { object.attribute }
         | 
| 47 47 | 
             
                  #
         | 
| 48 | 
            -
                  # @example AllowedPatterns: [ | 
| 48 | 
            +
                  # @example AllowedPatterns: ['change']
         | 
| 49 49 | 
             
                  #
         | 
| 50 50 | 
             
                  #   # good
         | 
| 51 51 | 
             
                  #   expect { do_something }.to change { object.attribute }
         | 
| @@ -81,7 +81,7 @@ module RuboCop | |
| 81 81 | 
             
                    def allowed_method_pattern?(node)
         | 
| 82 82 | 
             
                      node.assignment? || node.operator_method? || node.method?(:[]) ||
         | 
| 83 83 | 
             
                        allowed_method?(node.last_argument.method_name) ||
         | 
| 84 | 
            -
                        matches_allowed_pattern?(node.last_argument. | 
| 84 | 
            +
                        matches_allowed_pattern?(node.last_argument.send_node.source)
         | 
| 85 85 | 
             
                    end
         | 
| 86 86 |  | 
| 87 87 | 
             
                    def message(send_node)
         | 
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module RuboCop
         | 
| 4 | 
            +
              module Cop
         | 
| 5 | 
            +
                module Lint
         | 
| 6 | 
            +
                  # Checks for duplicated magic comments.
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # @example
         | 
| 9 | 
            +
                  #
         | 
| 10 | 
            +
                  #   # bad
         | 
| 11 | 
            +
                  #
         | 
| 12 | 
            +
                  #   # encoding: ascii
         | 
| 13 | 
            +
                  #   # encoding: ascii
         | 
| 14 | 
            +
                  #
         | 
| 15 | 
            +
                  #   # good
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  #   # encoding: ascii
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  #   # bad
         | 
| 20 | 
            +
                  #
         | 
| 21 | 
            +
                  #   # frozen_string_literal: true
         | 
| 22 | 
            +
                  #   # frozen_string_literal: true
         | 
| 23 | 
            +
                  #
         | 
| 24 | 
            +
                  #   # good
         | 
| 25 | 
            +
                  #
         | 
| 26 | 
            +
                  #   # frozen_string_literal: true
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  class DuplicateMagicComment < Base
         | 
| 29 | 
            +
                    include FrozenStringLiteral
         | 
| 30 | 
            +
                    include RangeHelp
         | 
| 31 | 
            +
                    extend AutoCorrector
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    MSG = 'Duplicate magic comment detected.'
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def on_new_investigation
         | 
| 36 | 
            +
                      return if processed_source.buffer.source.empty?
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      magic_comment_lines.each_value do |comment_lines|
         | 
| 39 | 
            +
                        next if comment_lines.count <= 1
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                        comment_lines[1..].each do |comment_line|
         | 
| 42 | 
            +
                          range = processed_source.buffer.line_range(comment_line + 1)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                          register_offense(range)
         | 
| 45 | 
            +
                        end
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    private
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    def magic_comment_lines
         | 
| 52 | 
            +
                      comment_lines = { encoding_magic_comments: [], frozen_string_literal_magic_comments: [] }
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      leading_magic_comments.each.with_index do |magic_comment, index|
         | 
| 55 | 
            +
                        if magic_comment.encoding_specified?
         | 
| 56 | 
            +
                          comment_lines[:encoding_magic_comments] << index
         | 
| 57 | 
            +
                        elsif magic_comment.frozen_string_literal_specified?
         | 
| 58 | 
            +
                          comment_lines[:frozen_string_literal_magic_comments] << index
         | 
| 59 | 
            +
                        end
         | 
| 60 | 
            +
                      end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                      comment_lines
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    def register_offense(range)
         | 
| 66 | 
            +
                      add_offense(range) do |corrector|
         | 
| 67 | 
            +
                        corrector.remove(range_by_whole_lines(range, include_final_newline: true))
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| @@ -133,7 +133,7 @@ module RuboCop | |
| 133 133 | 
             
                    end
         | 
| 134 134 |  | 
| 135 135 | 
             
                    def found_instance_method(node, name)
         | 
| 136 | 
            -
                      return unless (scope = node.parent_module_name)
         | 
| 136 | 
            +
                      return found_sclass_method(node, name) unless (scope = node.parent_module_name)
         | 
| 137 137 |  | 
| 138 138 | 
             
                      # Humanize the scope
         | 
| 139 139 | 
             
                      scope = scope.sub(
         | 
| @@ -145,6 +145,16 @@ module RuboCop | |
| 145 145 | 
             
                      found_method(node, "#{scope}#{name}")
         | 
| 146 146 | 
             
                    end
         | 
| 147 147 |  | 
| 148 | 
            +
                    def found_sclass_method(node, name)
         | 
| 149 | 
            +
                      singleton_ancestor = node.each_ancestor.find(&:sclass_type?)
         | 
| 150 | 
            +
                      return unless singleton_ancestor
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                      singleton_receiver_node = singleton_ancestor.children[0]
         | 
| 153 | 
            +
                      return unless singleton_receiver_node.send_type?
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                      found_method(node, "#{singleton_receiver_node.method_name}.#{name}")
         | 
| 156 | 
            +
                    end
         | 
| 157 | 
            +
             | 
| 148 158 | 
             
                    def found_method(node, method_name)
         | 
| 149 159 | 
             
                      if @definitions.key?(method_name)
         | 
| 150 160 | 
             
                        loc = case node.type
         | 
| @@ -32,26 +32,40 @@ module RuboCop | |
| 32 32 | 
             
                      end
         | 
| 33 33 | 
             
                    end
         | 
| 34 34 |  | 
| 35 | 
            +
                    # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
         | 
| 35 36 | 
             
                    def each_repeated_character_class_element_loc(node)
         | 
| 36 37 | 
             
                      node.parsed_tree&.each_expression do |expr|
         | 
| 37 | 
            -
                        next if expr | 
| 38 | 
            +
                        next if skip_expression?(expr)
         | 
| 38 39 |  | 
| 39 40 | 
             
                        seen = Set.new
         | 
| 41 | 
            +
                        enum = expr.expressions.to_enum
         | 
| 42 | 
            +
                        expression_count = expr.expressions.count
         | 
| 40 43 |  | 
| 41 | 
            -
                         | 
| 42 | 
            -
                           | 
| 44 | 
            +
                        expression_count.times do |current_number|
         | 
| 45 | 
            +
                          current_child = enum.next
         | 
| 46 | 
            +
                          next if within_interpolation?(node, current_child)
         | 
| 43 47 |  | 
| 44 | 
            -
                           | 
| 48 | 
            +
                          current_child_source = current_child.to_s
         | 
| 49 | 
            +
                          next_child = enum.peek if current_number + 1 < expression_count
         | 
| 45 50 |  | 
| 46 | 
            -
                           | 
| 51 | 
            +
                          if seen.include?(current_child_source)
         | 
| 52 | 
            +
                            next if start_with_escaped_zero_number?(current_child_source, next_child.to_s)
         | 
| 47 53 |  | 
| 48 | 
            -
             | 
| 54 | 
            +
                            yield current_child.expression
         | 
| 55 | 
            +
                          end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                          seen << current_child_source
         | 
| 49 58 | 
             
                        end
         | 
| 50 59 | 
             
                      end
         | 
| 51 60 | 
             
                    end
         | 
| 61 | 
            +
                    # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
         | 
| 52 62 |  | 
| 53 63 | 
             
                    private
         | 
| 54 64 |  | 
| 65 | 
            +
                    def skip_expression?(expr)
         | 
| 66 | 
            +
                      expr.type != :set || expr.token == :intersection
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 55 69 | 
             
                    # Since we blank interpolations with a space for every char of the interpolation, we would
         | 
| 56 70 | 
             
                    # mark every space (except the first) as duplicate if we do not skip regexp_parser nodes
         | 
| 57 71 | 
             
                    # that are within an interpolation.
         | 
| @@ -61,6 +75,11 @@ module RuboCop | |
| 61 75 | 
             
                      interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
         | 
| 62 76 | 
             
                    end
         | 
| 63 77 |  | 
| 78 | 
            +
                    def start_with_escaped_zero_number?(current_child, next_child)
         | 
| 79 | 
            +
                      # Represents escaped code from `"\00"` (`"\u0000"`) to `"\07"` (`"\a"`).
         | 
| 80 | 
            +
                      current_child == '\\0' && next_child.match?(/[0-7]/)
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
             | 
| 64 83 | 
             
                    def interpolation_locs(node)
         | 
| 65 84 | 
             
                      @interpolation_locs ||= {}
         | 
| 66 85 |  | 
| @@ -85,7 +85,9 @@ module RuboCop | |
| 85 85 | 
             
                    private
         | 
| 86 86 |  | 
| 87 87 | 
             
                    def body_or_allowed_comment_lines?(node)
         | 
| 88 | 
            -
                       | 
| 88 | 
            +
                      return true if node.body
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                      cop_config['AllowComments'] && processed_source.contains_comment?(node.source_range)
         | 
| 89 91 | 
             
                    end
         | 
| 90 92 | 
             
                  end
         | 
| 91 93 | 
             
                end
         |