rubocop 1.15.0 → 1.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +104 -31
- data/lib/rubocop.rb +7 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_validator.rb +5 -5
- data/lib/rubocop/cop/base.rb +2 -2
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +38 -4
- data/lib/rubocop/cop/corrector.rb +4 -4
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +4 -3
- data/lib/rubocop/cop/layout/array_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/case_indentation.rb +57 -9
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +7 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +13 -15
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +26 -8
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +8 -0
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +122 -0
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +6 -6
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +2 -2
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +6 -6
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -6
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +6 -6
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +11 -9
- data/lib/rubocop/cop/layout/space_around_keyword.rb +28 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +7 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +62 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +13 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +32 -17
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +105 -74
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +3 -13
- data/lib/rubocop/cop/lint/unused_block_argument.rb +1 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +3 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -1
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +14 -3
- data/lib/rubocop/cop/mixin/string_literals_help.rb +2 -4
- data/lib/rubocop/cop/mixin/symbol_help.rb +13 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +249 -0
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +14 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +18 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +58 -8
- data/lib/rubocop/cop/style/in_pattern_then.rb +56 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +62 -0
- data/lib/rubocop/cop/style/multiline_when_then.rb +2 -11
- data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/quoted_symbols.rb +110 -0
- data/lib/rubocop/cop/style/raise_args.rb +2 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +24 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +10 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/string_concatenation.rb +32 -5
- data/lib/rubocop/cop/style/string_literals.rb +3 -2
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -0
- data/lib/rubocop/cop/style/swap_values.rb +1 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +10 -2
- data/lib/rubocop/cop/style/unpack_first.rb +1 -1
- data/lib/rubocop/cop/style/when_then.rb +6 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/directive_comment.rb +58 -6
- data/lib/rubocop/options.rb +4 -4
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +10 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +12 -5
| @@ -120,6 +120,12 @@ module RuboCop | |
| 120 120 | 
             
                      check_operator(:special_asgn, node.loc.operator, right.source_range)
         | 
| 121 121 | 
             
                    end
         | 
| 122 122 |  | 
| 123 | 
            +
                    def on_match_pattern(node)
         | 
| 124 | 
            +
                      return if target_ruby_version < 3.0
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                      check_operator(:match_pattern, node.loc.operator, node.source_range)
         | 
| 127 | 
            +
                    end
         | 
| 128 | 
            +
             | 
| 123 129 | 
             
                    alias on_or       on_binary
         | 
| 124 130 | 
             
                    alias on_and      on_binary
         | 
| 125 131 | 
             
                    alias on_lvasgn   on_assignment
         | 
| @@ -192,7 +198,7 @@ module RuboCop | |
| 192 198 | 
             
                      elsif excess_leading_space?(type, operator, with_space) ||
         | 
| 193 199 | 
             
                            excess_trailing_space?(right_operand, with_space)
         | 
| 194 200 | 
             
                        "Operator `#{operator.source}` should be surrounded " \
         | 
| 195 | 
            -
             | 
| 201 | 
            +
                          'by a single space.'
         | 
| 196 202 | 
             
                      end
         | 
| 197 203 | 
             
                    end
         | 
| 198 204 |  | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module RuboCop
         | 
| 4 | 
            +
              module Cop
         | 
| 5 | 
            +
                module Lint
         | 
| 6 | 
            +
                  # This cop checks for the presence of `in` pattern branches without a body.
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # @example
         | 
| 9 | 
            +
                  #
         | 
| 10 | 
            +
                  #   # bad
         | 
| 11 | 
            +
                  #   case condition
         | 
| 12 | 
            +
                  #   in [a]
         | 
| 13 | 
            +
                  #     do_something
         | 
| 14 | 
            +
                  #   in [a, b]
         | 
| 15 | 
            +
                  #   end
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  #   # good
         | 
| 18 | 
            +
                  #   case condition
         | 
| 19 | 
            +
                  #   in [a]
         | 
| 20 | 
            +
                  #     do_something
         | 
| 21 | 
            +
                  #   in [a, b]
         | 
| 22 | 
            +
                  #     nil
         | 
| 23 | 
            +
                  #   end
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  # @example AllowComments: true (default)
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  #   # good
         | 
| 28 | 
            +
                  #   case condition
         | 
| 29 | 
            +
                  #   in [a]
         | 
| 30 | 
            +
                  #     do_something
         | 
| 31 | 
            +
                  #   in [a, b]
         | 
| 32 | 
            +
                  #     # noop
         | 
| 33 | 
            +
                  #   end
         | 
| 34 | 
            +
                  #
         | 
| 35 | 
            +
                  # @example AllowComments: false
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  #   # bad
         | 
| 38 | 
            +
                  #   case condition
         | 
| 39 | 
            +
                  #   in [a]
         | 
| 40 | 
            +
                  #     do_something
         | 
| 41 | 
            +
                  #   in [a, b]
         | 
| 42 | 
            +
                  #     # noop
         | 
| 43 | 
            +
                  #   end
         | 
| 44 | 
            +
                  #
         | 
| 45 | 
            +
                  class EmptyInPattern < Base
         | 
| 46 | 
            +
                    extend TargetRubyVersion
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    MSG = 'Avoid `in` branches without a body.'
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    minimum_target_ruby_version 2.7
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def on_case_match(node)
         | 
| 53 | 
            +
                      node.in_pattern_branches.each do |branch|
         | 
| 54 | 
            +
                        next if branch.body || cop_config['AllowComments'] && comment_lines?(node)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                        add_offense(branch)
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
            end
         | 
| @@ -5,7 +5,7 @@ module RuboCop | |
| 5 5 | 
             
                module Lint
         | 
| 6 6 | 
             
                  # This cop checks for literals used as the conditions or as
         | 
| 7 7 | 
             
                  # operands in and/or expressions serving as the conditions of
         | 
| 8 | 
            -
                  # if/while/until.
         | 
| 8 | 
            +
                  # if/while/until/case-when/case-in.
         | 
| 9 9 | 
             
                  #
         | 
| 10 10 | 
             
                  # @example
         | 
| 11 11 | 
             
                  #
         | 
| @@ -67,6 +67,18 @@ module RuboCop | |
| 67 67 | 
             
                      end
         | 
| 68 68 | 
             
                    end
         | 
| 69 69 |  | 
| 70 | 
            +
                    def on_case_match(case_match_node)
         | 
| 71 | 
            +
                      if case_match_node.condition
         | 
| 72 | 
            +
                        check_case(case_match_node)
         | 
| 73 | 
            +
                      else
         | 
| 74 | 
            +
                        case_match_node.each_in_pattern do |in_pattern_node|
         | 
| 75 | 
            +
                          next unless in_pattern_node.condition.literal?
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                          add_offense(in_pattern_node)
         | 
| 78 | 
            +
                        end
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
             | 
| 70 82 | 
             
                    def on_send(node)
         | 
| 71 83 | 
             
                      return unless node.negation_method?
         | 
| 72 84 |  | 
| @@ -45,37 +45,52 @@ module RuboCop | |
| 45 45 | 
             
                  class MissingCopEnableDirective < Base
         | 
| 46 46 | 
             
                    include RangeHelp
         | 
| 47 47 |  | 
| 48 | 
            -
                    MSG = 'Re-enable %<cop>s  | 
| 49 | 
            -
                    MSG_BOUND = 'Re-enable %<cop>s  | 
| 48 | 
            +
                    MSG = 'Re-enable %<cop>s %<type>s with `# rubocop:enable` after disabling it.'
         | 
| 49 | 
            +
                    MSG_BOUND = 'Re-enable %<cop>s %<type>s within %<max_range>s lines after disabling it.'
         | 
| 50 50 |  | 
| 51 | 
            -
                    # rubocop:disable Metrics/AbcSize
         | 
| 52 51 | 
             
                    def on_new_investigation
         | 
| 53 | 
            -
                       | 
| 54 | 
            -
             | 
| 55 | 
            -
                         | 
| 56 | 
            -
             | 
| 57 | 
            -
                          # the case when max_range is Float::INFINITY
         | 
| 58 | 
            -
                          next if line_range.max - line_range.min < max_range + 2
         | 
| 52 | 
            +
                      each_missing_enable do |cop, line_range|
         | 
| 53 | 
            +
                        # This has to remain a strict inequality to handle
         | 
| 54 | 
            +
                        # the case when max_range is Float::INFINITY
         | 
| 55 | 
            +
                        next if line_range.max - line_range.min < max_range + 2
         | 
| 59 56 |  | 
| 60 | 
            -
             | 
| 57 | 
            +
                        range = source_range(processed_source.buffer, line_range.min, (0..0))
         | 
| 58 | 
            +
                        comment = processed_source.comment_at_line(line_range.begin)
         | 
| 61 59 |  | 
| 62 | 
            -
             | 
| 63 | 
            -
                        end
         | 
| 60 | 
            +
                        add_offense(range, message: message(cop, comment))
         | 
| 64 61 | 
             
                      end
         | 
| 65 62 | 
             
                    end
         | 
| 66 | 
            -
                    # rubocop:enable Metrics/AbcSize
         | 
| 67 63 |  | 
| 68 64 | 
             
                    private
         | 
| 69 65 |  | 
| 70 | 
            -
                    def  | 
| 66 | 
            +
                    def each_missing_enable
         | 
| 67 | 
            +
                      processed_source.disabled_line_ranges.each do |cop, line_ranges|
         | 
| 68 | 
            +
                        line_ranges.each { |line_range| yield cop, line_range }
         | 
| 69 | 
            +
                      end
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    def max_range
         | 
| 73 | 
            +
                      @max_range ||= cop_config['MaximumRangeSize']
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                    def message(cop, comment, type = 'cop')
         | 
| 77 | 
            +
                      if department_enabled?(cop, comment)
         | 
| 78 | 
            +
                        type = 'department'
         | 
| 79 | 
            +
                        cop = cop.split('/').first
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
             | 
| 71 82 | 
             
                      if max_range == Float::INFINITY
         | 
| 72 | 
            -
                        format(MSG, cop: cop)
         | 
| 83 | 
            +
                        format(MSG, cop: cop, type: type)
         | 
| 73 84 | 
             
                      else
         | 
| 74 | 
            -
                        format(MSG_BOUND, cop: cop, max_range: max_range)
         | 
| 85 | 
            +
                        format(MSG_BOUND, cop: cop, type: type, max_range: max_range)
         | 
| 75 86 | 
             
                      end
         | 
| 76 87 | 
             
                    end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    def department_enabled?(cop, comment)
         | 
| 90 | 
            +
                      DirectiveComment.new(comment).in_directive_department?(cop)
         | 
| 91 | 
            +
                    end
         | 
| 77 92 | 
             
                  end
         | 
| 78 93 | 
             
                end
         | 
| 79 94 | 
             
              end
         | 
| 80 95 | 
             
            end
         | 
| 81 | 
            -
            # rubocop:enable Lint/RedundantCopDisableDirective | 
| 96 | 
            +
            # rubocop:enable Lint/RedundantCopDisableDirective
         | 
| @@ -33,7 +33,7 @@ module RuboCop | |
| 33 33 | 
             
                    include PercentLiteral
         | 
| 34 34 |  | 
| 35 35 | 
             
                    MSG = 'Within percent literals, nested percent literals do not ' \
         | 
| 36 | 
            -
             | 
| 36 | 
            +
                          'function and may be unwanted in the result.'
         | 
| 37 37 |  | 
| 38 38 | 
             
                    # The array of regular expressions representing percent literals that,
         | 
| 39 39 | 
             
                    # if found within a percent literal expression, will cause a
         | 
| @@ -29,7 +29,7 @@ module RuboCop | |
| 29 29 | 
             
                    TRAILING_QUOTE = /['"]?,?$/.freeze
         | 
| 30 30 |  | 
| 31 31 | 
             
                    MSG = "Within `%w`/`%W`, quotes and ',' are unnecessary and may be " \
         | 
| 32 | 
            -
             | 
| 32 | 
            +
                          'unwanted in the resulting strings.'
         | 
| 33 33 |  | 
| 34 34 | 
             
                    def on_array(node)
         | 
| 35 35 | 
             
                      process(node, '%w', '%W')
         | 
| @@ -25,11 +25,12 @@ module RuboCop | |
| 25 25 | 
             
                  #
         | 
| 26 26 | 
             
                  #   # good
         | 
| 27 27 | 
             
                  #   x += 1
         | 
| 28 | 
            -
                  class RedundantCopDisableDirective < Base
         | 
| 28 | 
            +
                  class RedundantCopDisableDirective < Base # rubocop:todo Metrics/ClassLength
         | 
| 29 29 | 
             
                    include RangeHelp
         | 
| 30 30 | 
             
                    extend AutoCorrector
         | 
| 31 31 |  | 
| 32 32 | 
             
                    COP_NAME = 'Lint/RedundantCopDisableDirective'
         | 
| 33 | 
            +
                    DEPARTMENT_MARKER = 'DEPARTMENT'
         | 
| 33 34 |  | 
| 34 35 | 
             
                    attr_accessor :offenses_to_check
         | 
| 35 36 |  | 
| @@ -41,12 +42,9 @@ module RuboCop | |
| 41 42 | 
             
                    def on_new_investigation
         | 
| 42 43 | 
             
                      return unless offenses_to_check
         | 
| 43 44 |  | 
| 44 | 
            -
                      cop_disabled_line_ranges = processed_source.disabled_line_ranges
         | 
| 45 | 
            -
             | 
| 46 45 | 
             
                      redundant_cops = Hash.new { |h, k| h[k] = Set.new }
         | 
| 47 46 |  | 
| 48 | 
            -
                      each_redundant_disable | 
| 49 | 
            -
                                             offenses_to_check) do |comment, redundant_cop|
         | 
| 47 | 
            +
                      each_redundant_disable do |comment, redundant_cop|
         | 
| 50 48 | 
             
                        redundant_cops[comment].add(redundant_cop)
         | 
| 51 49 | 
             
                      end
         | 
| 52 50 |  | 
| @@ -56,20 +54,31 @@ module RuboCop | |
| 56 54 |  | 
| 57 55 | 
             
                    private
         | 
| 58 56 |  | 
| 57 | 
            +
                    def cop_disabled_line_ranges
         | 
| 58 | 
            +
                      processed_source.disabled_line_ranges
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    def disabled_ranges
         | 
| 62 | 
            +
                      cop_disabled_line_ranges[COP_NAME] || [0..0]
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 59 65 | 
             
                    def previous_line_blank?(range)
         | 
| 60 66 | 
             
                      processed_source.buffer.source_line(range.line - 1).blank?
         | 
| 61 67 | 
             
                    end
         | 
| 62 68 |  | 
| 63 | 
            -
                    def comment_range_with_surrounding_space( | 
| 64 | 
            -
                      if previous_line_blank?( | 
| 65 | 
            -
                         processed_source.comment_config.comment_only_line?( | 
| 69 | 
            +
                    def comment_range_with_surrounding_space(directive_comment_range, line_comment_range)
         | 
| 70 | 
            +
                      if previous_line_blank?(directive_comment_range) &&
         | 
| 71 | 
            +
                         processed_source.comment_config.comment_only_line?(directive_comment_range.line) &&
         | 
| 72 | 
            +
                         directive_comment_range.begin_pos == line_comment_range.begin_pos
         | 
| 66 73 | 
             
                        # When the previous line is blank, it should be retained
         | 
| 67 | 
            -
                        range_with_surrounding_space(range:  | 
| 74 | 
            +
                        range_with_surrounding_space(range: directive_comment_range, side: :right)
         | 
| 68 75 | 
             
                      else
         | 
| 69 76 | 
             
                        # Eat the entire comment, the preceding space, and the preceding
         | 
| 70 77 | 
             
                        # newline if there is one.
         | 
| 71 | 
            -
                        original_begin =  | 
| 72 | 
            -
                        range = range_with_surrounding_space( | 
| 78 | 
            +
                        original_begin = directive_comment_range.begin_pos
         | 
| 79 | 
            +
                        range = range_with_surrounding_space(
         | 
| 80 | 
            +
                          range: directive_comment_range, side: :left, newlines: true
         | 
| 81 | 
            +
                        )
         | 
| 73 82 |  | 
| 74 83 | 
             
                        range_with_surrounding_space(range: range,
         | 
| 75 84 | 
             
                                                     side: :right,
         | 
| @@ -94,32 +103,34 @@ module RuboCop | |
| 94 103 | 
             
                      range_with_surrounding_space(range: range, side: :right, newlines: false)
         | 
| 95 104 | 
             
                    end
         | 
| 96 105 |  | 
| 97 | 
            -
                    def each_redundant_disable( | 
| 98 | 
            -
                                               &block)
         | 
| 99 | 
            -
                      disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
         | 
| 100 | 
            -
             | 
| 106 | 
            +
                    def each_redundant_disable(&block)
         | 
| 101 107 | 
             
                      cop_disabled_line_ranges.each do |cop, line_ranges|
         | 
| 102 | 
            -
                        each_already_disabled(line_ranges,  | 
| 103 | 
            -
             | 
| 104 | 
            -
                        each_line_range(line_ranges, disabled_ranges, offenses, cop, &block)
         | 
| 108 | 
            +
                        each_already_disabled(cop, line_ranges, &block)
         | 
| 109 | 
            +
                        each_line_range(cop, line_ranges, &block)
         | 
| 105 110 | 
             
                      end
         | 
| 106 111 | 
             
                    end
         | 
| 107 112 |  | 
| 108 | 
            -
                    def each_line_range( | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
                        comment = processed_source.comment_at_line(line_range.begin)
         | 
| 112 | 
            -
                        next if ignore_offense?(disabled_ranges, line_range)
         | 
| 113 | 
            +
                    def each_line_range(cop, line_ranges)
         | 
| 114 | 
            +
                      line_ranges.each_with_index do |line_range, line_range_index|
         | 
| 115 | 
            +
                        next if ignore_offense?(line_range)
         | 
| 113 116 |  | 
| 114 | 
            -
                         | 
| 115 | 
            -
                         | 
| 117 | 
            +
                        comment = processed_source.comment_at_line(line_range.begin)
         | 
| 118 | 
            +
                        redundant = if all_disabled?(comment)
         | 
| 119 | 
            +
                                      find_redundant_all(line_range, line_ranges[line_range_index + 1])
         | 
| 120 | 
            +
                                    elsif department_disabled?(cop, comment)
         | 
| 121 | 
            +
                                      find_redundant_department(cop, line_range)
         | 
| 122 | 
            +
                                    else
         | 
| 123 | 
            +
                                      find_redundant_cop(cop, line_range)
         | 
| 124 | 
            +
                                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                        yield comment, redundant if redundant
         | 
| 116 127 | 
             
                      end
         | 
| 117 128 | 
             
                    end
         | 
| 118 129 |  | 
| 119 | 
            -
                    def each_already_disabled( | 
| 130 | 
            +
                    def each_already_disabled(cop, line_ranges)
         | 
| 120 131 | 
             
                      line_ranges.each_cons(2) do |previous_range, range|
         | 
| 121 | 
            -
                        next if ignore_offense?( | 
| 122 | 
            -
                        next  | 
| 132 | 
            +
                        next if ignore_offense?(range)
         | 
| 133 | 
            +
                        next unless followed_ranges?(previous_range, range)
         | 
| 123 134 |  | 
| 124 135 | 
             
                        # If a cop is disabled in a range that begins on the same line as
         | 
| 125 136 | 
             
                        # the end of the previous range, it means that the cop was
         | 
| @@ -130,42 +141,56 @@ module RuboCop | |
| 130 141 | 
             
                        # Comments disabling all cops don't count since it's reasonable
         | 
| 131 142 | 
             
                        # to disable a few select cops first and then all cops further
         | 
| 132 143 | 
             
                        # down in the code.
         | 
| 133 | 
            -
                        yield comment if comment && !all_disabled?(comment)
         | 
| 144 | 
            +
                        yield comment, cop if comment && !all_disabled?(comment)
         | 
| 134 145 | 
             
                      end
         | 
| 135 146 | 
             
                    end
         | 
| 136 147 |  | 
| 137 | 
            -
                     | 
| 138 | 
            -
             | 
| 139 | 
            -
                      if  | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
                       | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 148 | 
            +
                    def find_redundant_cop(cop, range)
         | 
| 149 | 
            +
                      cop_offenses = offenses_to_check.select { |offense| offense.cop_name == cop }
         | 
| 150 | 
            +
                      cop if range_with_offense?(range, cop_offenses)
         | 
| 151 | 
            +
                    end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                    def find_redundant_all(range, next_range)
         | 
| 154 | 
            +
                      # If there's a disable all comment followed by a comment
         | 
| 155 | 
            +
                      # specifically disabling `cop`, we don't report the `all`
         | 
| 156 | 
            +
                      # comment. If the disable all comment is truly redundant, we will
         | 
| 157 | 
            +
                      # detect that when examining the comments of another cop, and we
         | 
| 158 | 
            +
                      # get the full line range for the disable all.
         | 
| 159 | 
            +
                      has_no_next_range = next_range.nil? || !followed_ranges?(range, next_range)
         | 
| 160 | 
            +
                      'all' if has_no_next_range && range_with_offense?(range)
         | 
| 161 | 
            +
                    end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                    def find_redundant_department(cop, range)
         | 
| 164 | 
            +
                      department = cop.split('/').first
         | 
| 165 | 
            +
                      offenses = offenses_to_check.select { |offense| offense.cop_name.start_with?(department) }
         | 
| 166 | 
            +
                      add_department_marker(department) if range_with_offense?(range, offenses)
         | 
| 167 | 
            +
                    end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                    def followed_ranges?(range, next_range)
         | 
| 170 | 
            +
                      range.end == next_range.begin
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    def range_with_offense?(range, offenses = offenses_to_check)
         | 
| 174 | 
            +
                      offenses.none? { |offense| range.cover?(offense.line) }
         | 
| 153 175 | 
             
                    end
         | 
| 154 | 
            -
                    # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         | 
| 155 176 |  | 
| 156 177 | 
             
                    def all_disabled?(comment)
         | 
| 157 | 
            -
                       | 
| 178 | 
            +
                      DirectiveComment.new(comment).disabled_all?
         | 
| 158 179 | 
             
                    end
         | 
| 159 180 |  | 
| 160 | 
            -
                    def ignore_offense?( | 
| 181 | 
            +
                    def ignore_offense?(line_range)
         | 
| 161 182 | 
             
                      disabled_ranges.any? do |range|
         | 
| 162 183 | 
             
                        range.cover?(line_range.min) && range.cover?(line_range.max)
         | 
| 163 184 | 
             
                      end
         | 
| 164 185 | 
             
                    end
         | 
| 165 186 |  | 
| 187 | 
            +
                    def department_disabled?(cop, comment)
         | 
| 188 | 
            +
                      directive = DirectiveComment.new(comment)
         | 
| 189 | 
            +
                      directive.in_directive_department?(cop) && !directive.overridden_by_department?(cop)
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
             | 
| 166 192 | 
             
                    def directive_count(comment)
         | 
| 167 | 
            -
                       | 
| 168 | 
            -
                      cops_string.split(/,\s*/).size
         | 
| 193 | 
            +
                      DirectiveComment.new(comment).directive_count
         | 
| 169 194 | 
             
                    end
         | 
| 170 195 |  | 
| 171 196 | 
             
                    def add_offenses(redundant_cops)
         | 
| @@ -179,14 +204,11 @@ module RuboCop | |
| 179 204 | 
             
                    end
         | 
| 180 205 |  | 
| 181 206 | 
             
                    def add_offense_for_entire_comment(comment, cops)
         | 
| 182 | 
            -
                      location = comment. | 
| 183 | 
            -
                       | 
| 184 | 
            -
             | 
| 185 | 
            -
                      add_offense(
         | 
| 186 | 
            -
                        location,
         | 
| 187 | 
            -
                        message: "Unnecessary disabling of #{cop_list.join(', ')}."
         | 
| 188 | 
            -
                      ) do |corrector|
         | 
| 189 | 
            -
                        range = comment_range_with_surrounding_space(location)
         | 
| 207 | 
            +
                      location = DirectiveComment.new(comment).range
         | 
| 208 | 
            +
                      cop_names = cops.sort.map { |c| describe(c) }.join(', ')
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                      add_offense(location, message: message(cop_names)) do |corrector|
         | 
| 211 | 
            +
                        range = comment_range_with_surrounding_space(location, comment.loc.expression)
         | 
| 190 212 | 
             
                        corrector.remove(range)
         | 
| 191 213 | 
             
                      end
         | 
| 192 214 | 
             
                    end
         | 
| @@ -197,10 +219,8 @@ module RuboCop | |
| 197 219 | 
             
                      ranges = cop_ranges.map { |_, r| r }
         | 
| 198 220 |  | 
| 199 221 | 
             
                      cop_ranges.each do |cop, range|
         | 
| 200 | 
            -
                         | 
| 201 | 
            -
             | 
| 202 | 
            -
                          message: "Unnecessary disabling of #{describe(cop)}."
         | 
| 203 | 
            -
                        ) do |corrector|
         | 
| 222 | 
            +
                        cop_name = describe(cop)
         | 
| 223 | 
            +
                        add_offense(range, message: message(cop_name)) do |corrector|
         | 
| 204 224 | 
             
                          range = directive_range_in_list(range, ranges)
         | 
| 205 225 | 
             
                          corrector.remove(range)
         | 
| 206 226 | 
             
                        end
         | 
| @@ -208,6 +228,7 @@ module RuboCop | |
| 208 228 | 
             
                    end
         | 
| 209 229 |  | 
| 210 230 | 
             
                    def cop_range(comment, cop)
         | 
| 231 | 
            +
                      cop = remove_department_marker(cop)
         | 
| 211 232 | 
             
                      matching_range(comment.loc.expression, cop) ||
         | 
| 212 233 | 
             
                        matching_range(comment.loc.expression, Badge.parse(cop).cop_name) ||
         | 
| 213 234 | 
             
                        raise("Couldn't find #{cop} in comment: #{comment.text}")
         | 
| @@ -230,18 +251,16 @@ module RuboCop | |
| 230 251 | 
             
                    end
         | 
| 231 252 |  | 
| 232 253 | 
             
                    def describe(cop)
         | 
| 233 | 
            -
                      if cop == 'all'
         | 
| 234 | 
            -
             | 
| 235 | 
            -
                       | 
| 236 | 
            -
             | 
| 237 | 
            -
                       | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
                        end
         | 
| 244 | 
            -
                      end
         | 
| 254 | 
            +
                      return 'all cops' if cop == 'all'
         | 
| 255 | 
            +
                      return "`#{remove_department_marker(cop)}` department" if department_marker?(cop)
         | 
| 256 | 
            +
                      return "`#{cop}`" if all_cop_names.include?(cop)
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                      similar = NameSimilarity.find_similar_name(cop, all_cop_names)
         | 
| 259 | 
            +
                      similar ? "`#{cop}` (did you mean `#{similar}`?)" : "`#{cop}` (unknown cop)"
         | 
| 260 | 
            +
                    end
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                    def message(cop_names)
         | 
| 263 | 
            +
                      "Unnecessary disabling of #{cop_names}."
         | 
| 245 264 | 
             
                    end
         | 
| 246 265 |  | 
| 247 266 | 
             
                    def all_cop_names
         | 
| @@ -252,6 +271,18 @@ module RuboCop | |
| 252 271 | 
             
                      line = range.source_buffer.source_line(range.last_line)
         | 
| 253 272 | 
             
                      (line =~ /\s*\z/) == range.last_column
         | 
| 254 273 | 
             
                    end
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                    def department_marker?(department)
         | 
| 276 | 
            +
                      department.start_with?(DEPARTMENT_MARKER)
         | 
| 277 | 
            +
                    end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    def remove_department_marker(department)
         | 
| 280 | 
            +
                      department.gsub(DEPARTMENT_MARKER, '')
         | 
| 281 | 
            +
                    end
         | 
| 282 | 
            +
             | 
| 283 | 
            +
                    def add_department_marker(department)
         | 
| 284 | 
            +
                      DEPARTMENT_MARKER + department
         | 
| 285 | 
            +
                    end
         | 
| 255 286 | 
             
                  end
         | 
| 256 287 | 
             
                end
         | 
| 257 288 | 
             
              end
         |